i-tech-shared-components 1.4.64 → 1.4.65-alpha.1771957526834

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.
@@ -8,7 +8,7 @@ import moment from 'moment';
8
8
  import * as momentTimezone from 'moment-timezone';
9
9
  import { MatIconButton, MatFabButton, MatButton, MatButtonModule } from '@angular/material/button';
10
10
  import * as i2$1 from '@angular/common';
11
- import { NgClass, NgIf, NgOptimizedImage, NgFor, NgForOf, UpperCasePipe, SlicePipe, LowerCasePipe, CommonModule } from '@angular/common';
11
+ import { NgClass, NgIf, NgOptimizedImage, NgFor, NgForOf, UpperCasePipe, SlicePipe, LowerCasePipe, CommonModule, DecimalPipe } from '@angular/common';
12
12
  import * as i1$2 from '@angular/material/tooltip';
13
13
  import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
14
14
  import * as i1$1 from '@angular/material/icon';
@@ -2912,6 +2912,422 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
2912
2912
  type: Output
2913
2913
  }] } });
2914
2914
 
2915
+ class TimeInputComponent {
2916
+ set submit(value) {
2917
+ if (value && this.ngControl?.control) {
2918
+ this.ngControl.control.markAsTouched();
2919
+ }
2920
+ this._submit = value;
2921
+ }
2922
+ get submit() { return this._submit; }
2923
+ get hourOptions() {
2924
+ if (this.mode === '12h') {
2925
+ return Array.from({ length: 12 }, (_, i) => i + 1);
2926
+ }
2927
+ return Array.from({ length: 24 }, (_, i) => i);
2928
+ }
2929
+ get minuteOptions() {
2930
+ return Array.from({ length: 60 }, (_, i) => i);
2931
+ }
2932
+ get selectedHourValue() {
2933
+ if (this.hours === '--')
2934
+ return null;
2935
+ return parseInt(this.hours, 10);
2936
+ }
2937
+ get selectedMinuteValue() {
2938
+ if (this.minutes === '--')
2939
+ return null;
2940
+ return parseInt(this.minutes, 10);
2941
+ }
2942
+ get hasValue() {
2943
+ return this.hours !== '--' && this.minutes !== '--';
2944
+ }
2945
+ get isDisabled() {
2946
+ return this.readOnly || (this.ngControl?.control?.disabled ?? false);
2947
+ }
2948
+ constructor(inputService) {
2949
+ this.inputService = inputService;
2950
+ this.required = false;
2951
+ this.mode = '12h';
2952
+ this.readOnly = false;
2953
+ this.selectionChanges = new EventEmitter();
2954
+ this.hours = '--';
2955
+ this.minutes = '--';
2956
+ this.amPm = 'AM';
2957
+ this.activeSegment = null;
2958
+ this.isPickerOpen = false;
2959
+ this._submit = false;
2960
+ this.hourBuffer = '';
2961
+ this.minuteBuffer = '';
2962
+ this.customErrorStateMatcher = {
2963
+ isErrorState: (control) => {
2964
+ return !!(control && control.invalid && this._submit);
2965
+ }
2966
+ };
2967
+ this.ngControl = this.inputService.injectNgControl();
2968
+ }
2969
+ ngOnInit() {
2970
+ const initialValue = this.ngControl.control?.value;
2971
+ if (initialValue) {
2972
+ this.parseControlValue(initialValue);
2973
+ }
2974
+ this.valueChangesSub = this.ngControl.control?.valueChanges.subscribe(v => {
2975
+ this.parseControlValue(v);
2976
+ });
2977
+ }
2978
+ ngOnDestroy() {
2979
+ this.valueChangesSub?.unsubscribe();
2980
+ }
2981
+ parseControlValue(v) {
2982
+ if (!v) {
2983
+ this.hours = '--';
2984
+ this.minutes = '--';
2985
+ this.amPm = 'AM';
2986
+ return;
2987
+ }
2988
+ const parts = v.split(':');
2989
+ if (parts.length < 2)
2990
+ return;
2991
+ const h24 = parseInt(parts[0], 10);
2992
+ const m = parseInt(parts[1], 10);
2993
+ if (isNaN(h24) || isNaN(m))
2994
+ return;
2995
+ this.minutes = String(m).padStart(2, '0');
2996
+ if (this.mode === '12h') {
2997
+ if (h24 === 0) {
2998
+ this.hours = '12';
2999
+ this.amPm = 'AM';
3000
+ }
3001
+ else if (h24 < 12) {
3002
+ this.hours = String(h24).padStart(2, '0');
3003
+ this.amPm = 'AM';
3004
+ }
3005
+ else if (h24 === 12) {
3006
+ this.hours = '12';
3007
+ this.amPm = 'PM';
3008
+ }
3009
+ else {
3010
+ this.hours = String(h24 - 12).padStart(2, '0');
3011
+ this.amPm = 'PM';
3012
+ }
3013
+ }
3014
+ else {
3015
+ this.hours = String(h24).padStart(2, '0');
3016
+ }
3017
+ }
3018
+ emitControlValue() {
3019
+ if (!this.hasValue)
3020
+ return;
3021
+ const h24 = this.toHours24();
3022
+ if (h24 === null)
3023
+ return;
3024
+ const timeStr = `${String(h24).padStart(2, '0')}:${this.minutes}`;
3025
+ this.ngControl.control.setValue(timeStr, { emitEvent: false });
3026
+ this.ngControl.control.markAsDirty();
3027
+ this.selectionChanges.emit(timeStr);
3028
+ }
3029
+ toHours24() {
3030
+ if (this.hours === '--')
3031
+ return null;
3032
+ const h = parseInt(this.hours, 10);
3033
+ if (this.mode === '24h')
3034
+ return h;
3035
+ if (this.amPm === 'AM') {
3036
+ return h === 12 ? 0 : h;
3037
+ }
3038
+ else {
3039
+ return h === 12 ? 12 : h + 12;
3040
+ }
3041
+ }
3042
+ activateSegment(segment, event) {
3043
+ if (this.isDisabled)
3044
+ return;
3045
+ event.stopPropagation();
3046
+ this.activeSegment = segment;
3047
+ setTimeout(() => this.timeFieldEl?.nativeElement.focus());
3048
+ }
3049
+ deactivate() {
3050
+ this.activeSegment = null;
3051
+ this.hourBuffer = '';
3052
+ this.minuteBuffer = '';
3053
+ }
3054
+ onKeyDown(event) {
3055
+ if (this.activeSegment === null)
3056
+ return;
3057
+ if (this.activeSegment === 'hours')
3058
+ this.onHoursKey(event);
3059
+ else if (this.activeSegment === 'minutes')
3060
+ this.onMinutesKey(event);
3061
+ else if (this.activeSegment === 'ampm')
3062
+ this.onAmPmKey(event);
3063
+ }
3064
+ onHoursKey(event) {
3065
+ const key = event.key;
3066
+ if (key === 'Tab') {
3067
+ this.activeSegment = 'minutes';
3068
+ this.hourBuffer = '';
3069
+ return;
3070
+ }
3071
+ if (key === 'ArrowRight') {
3072
+ event.preventDefault();
3073
+ this.activeSegment = 'minutes';
3074
+ this.hourBuffer = '';
3075
+ return;
3076
+ }
3077
+ if (key === 'ArrowUp' || key === 'ArrowDown') {
3078
+ event.preventDefault();
3079
+ this.adjustHours(key === 'ArrowUp' ? 1 : -1);
3080
+ return;
3081
+ }
3082
+ if (!/^\d$/.test(key))
3083
+ return;
3084
+ event.preventDefault();
3085
+ const digit = parseInt(key, 10);
3086
+ this.hourBuffer += key;
3087
+ if (this.mode === '12h') {
3088
+ if (this.hourBuffer.length === 1 && digit >= 2 && digit <= 9) {
3089
+ this.hours = '0' + key;
3090
+ this.hourBuffer = '';
3091
+ this.activeSegment = 'minutes';
3092
+ }
3093
+ else if (this.hourBuffer.length === 2) {
3094
+ const num = parseInt(this.hourBuffer, 10);
3095
+ if (num >= 1 && num <= 12) {
3096
+ this.hours = this.hourBuffer;
3097
+ }
3098
+ else {
3099
+ this.hours = '0' + this.hourBuffer[1];
3100
+ }
3101
+ this.hourBuffer = '';
3102
+ this.activeSegment = 'minutes';
3103
+ }
3104
+ else {
3105
+ this.hours = '0' + key;
3106
+ }
3107
+ }
3108
+ else {
3109
+ if (this.hourBuffer.length === 1 && digit >= 3) {
3110
+ this.hours = '0' + key;
3111
+ this.hourBuffer = '';
3112
+ this.activeSegment = 'minutes';
3113
+ }
3114
+ else if (this.hourBuffer.length === 2) {
3115
+ const num = parseInt(this.hourBuffer, 10);
3116
+ if (num >= 0 && num <= 23) {
3117
+ this.hours = this.hourBuffer;
3118
+ }
3119
+ else {
3120
+ this.hours = '0' + this.hourBuffer[1];
3121
+ }
3122
+ this.hourBuffer = '';
3123
+ this.activeSegment = 'minutes';
3124
+ }
3125
+ else {
3126
+ this.hours = '0' + key;
3127
+ }
3128
+ }
3129
+ this.emitControlValue();
3130
+ }
3131
+ adjustHours(delta) {
3132
+ if (this.mode === '12h') {
3133
+ const current = this.hours === '--' ? 12 : parseInt(this.hours, 10);
3134
+ let next = current + delta;
3135
+ if (next > 12)
3136
+ next = 1;
3137
+ if (next < 1)
3138
+ next = 12;
3139
+ this.hours = String(next).padStart(2, '0');
3140
+ }
3141
+ else {
3142
+ const current = this.hours === '--' ? 0 : parseInt(this.hours, 10);
3143
+ let next = current + delta;
3144
+ if (next > 23)
3145
+ next = 0;
3146
+ if (next < 0)
3147
+ next = 23;
3148
+ this.hours = String(next).padStart(2, '0');
3149
+ }
3150
+ if (this.minutes === '--')
3151
+ this.minutes = '00';
3152
+ this.emitControlValue();
3153
+ }
3154
+ onMinutesKey(event) {
3155
+ const key = event.key;
3156
+ if (key === 'Tab') {
3157
+ if (this.mode === '12h')
3158
+ this.activeSegment = 'ampm';
3159
+ else
3160
+ this.deactivate();
3161
+ this.minuteBuffer = '';
3162
+ return;
3163
+ }
3164
+ if (key === 'ArrowLeft') {
3165
+ event.preventDefault();
3166
+ this.activeSegment = 'hours';
3167
+ this.minuteBuffer = '';
3168
+ return;
3169
+ }
3170
+ if (key === 'ArrowRight' && this.mode === '12h') {
3171
+ event.preventDefault();
3172
+ this.activeSegment = 'ampm';
3173
+ this.minuteBuffer = '';
3174
+ return;
3175
+ }
3176
+ if (key === 'ArrowUp' || key === 'ArrowDown') {
3177
+ event.preventDefault();
3178
+ this.adjustMinutes(key === 'ArrowUp' ? 1 : -1);
3179
+ return;
3180
+ }
3181
+ if (!/^\d$/.test(key))
3182
+ return;
3183
+ event.preventDefault();
3184
+ const digit = parseInt(key, 10);
3185
+ this.minuteBuffer += key;
3186
+ if (this.minuteBuffer.length === 1 && digit >= 6) {
3187
+ this.minutes = '0' + key;
3188
+ this.minuteBuffer = '';
3189
+ if (this.mode === '12h')
3190
+ this.activeSegment = 'ampm';
3191
+ else
3192
+ this.deactivate();
3193
+ }
3194
+ else if (this.minuteBuffer.length === 2) {
3195
+ const num = parseInt(this.minuteBuffer, 10);
3196
+ if (num >= 0 && num <= 59) {
3197
+ this.minutes = this.minuteBuffer;
3198
+ }
3199
+ else {
3200
+ this.minutes = '0' + this.minuteBuffer[1];
3201
+ }
3202
+ this.minuteBuffer = '';
3203
+ if (this.mode === '12h')
3204
+ this.activeSegment = 'ampm';
3205
+ else
3206
+ this.deactivate();
3207
+ }
3208
+ else {
3209
+ this.minutes = '0' + key;
3210
+ }
3211
+ this.emitControlValue();
3212
+ }
3213
+ adjustMinutes(delta) {
3214
+ const current = this.minutes === '--' ? 0 : parseInt(this.minutes, 10);
3215
+ let next = current + delta;
3216
+ if (next > 59)
3217
+ next = 0;
3218
+ if (next < 0)
3219
+ next = 59;
3220
+ this.minutes = String(next).padStart(2, '0');
3221
+ if (this.hours === '--') {
3222
+ this.hours = this.mode === '12h' ? '12' : '00';
3223
+ }
3224
+ this.emitControlValue();
3225
+ }
3226
+ onAmPmKey(event) {
3227
+ const key = event.key.toLowerCase();
3228
+ if (key === 'arrowleft') {
3229
+ event.preventDefault();
3230
+ this.activeSegment = 'minutes';
3231
+ return;
3232
+ }
3233
+ if (key === 'a') {
3234
+ this.amPm = 'AM';
3235
+ this.emitControlValue();
3236
+ }
3237
+ else if (key === 'p') {
3238
+ this.amPm = 'PM';
3239
+ this.emitControlValue();
3240
+ }
3241
+ else if (key === 'arrowup' || key === 'arrowdown') {
3242
+ event.preventDefault();
3243
+ this.amPm = this.amPm === 'AM' ? 'PM' : 'AM';
3244
+ this.emitControlValue();
3245
+ }
3246
+ }
3247
+ togglePicker(event) {
3248
+ if (this.isDisabled)
3249
+ return;
3250
+ event.stopPropagation();
3251
+ this.isPickerOpen = !this.isPickerOpen;
3252
+ if (this.isPickerOpen) {
3253
+ setTimeout(() => this.scrollPickerToSelected());
3254
+ }
3255
+ }
3256
+ scrollPickerToSelected() {
3257
+ if (this.hourColEl?.nativeElement) {
3258
+ const selected = this.hourColEl.nativeElement.querySelector('.selected');
3259
+ if (selected) {
3260
+ selected.scrollIntoView({ block: 'center', behavior: 'instant' });
3261
+ }
3262
+ }
3263
+ if (this.minuteColEl?.nativeElement) {
3264
+ const selected = this.minuteColEl.nativeElement.querySelector('.selected');
3265
+ if (selected) {
3266
+ selected.scrollIntoView({ block: 'center', behavior: 'instant' });
3267
+ }
3268
+ }
3269
+ }
3270
+ selectHour(h) {
3271
+ this.hours = String(h).padStart(2, '0');
3272
+ if (this.minutes === '--')
3273
+ this.minutes = '00';
3274
+ this.emitControlValue();
3275
+ }
3276
+ selectMinute(m) {
3277
+ this.minutes = String(m).padStart(2, '0');
3278
+ if (this.hours === '--') {
3279
+ this.hours = this.mode === '12h' ? '12' : '00';
3280
+ }
3281
+ this.emitControlValue();
3282
+ }
3283
+ selectAmPm(v) {
3284
+ this.amPm = v;
3285
+ this.emitControlValue();
3286
+ }
3287
+ onDocumentClick() {
3288
+ if (this.isPickerOpen) {
3289
+ this.isPickerOpen = false;
3290
+ }
3291
+ if (this.activeSegment !== null) {
3292
+ this.deactivate();
3293
+ }
3294
+ }
3295
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TimeInputComponent, deps: [{ token: InputService }], target: i0.ɵɵFactoryTarget.Component }); }
3296
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: TimeInputComponent, isStandalone: true, selector: "i-tech-time-input", inputs: { submit: "submit", label: "label", required: "required", mode: "mode", readOnly: "readOnly" }, outputs: { selectionChanges: "selectionChanges" }, host: { listeners: { "document:click": "onDocumentClick()" } }, viewQueries: [{ propertyName: "timeFieldEl", first: true, predicate: ["timeField"], descendants: true }, { propertyName: "hourColEl", first: true, predicate: ["hourCol"], descendants: true }, { propertyName: "minuteColEl", first: true, predicate: ["minuteCol"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"ngControl\" class=\"time-input\">\n\n <!-- Label row -->\n <div *ngIf=\"label\" class=\"time-input__label-row\">\n <span class=\"time-input__label\">{{ label | translate }}</span>\n <span *ngIf=\"required\" class=\"time-input__required\">*</span>\n </div>\n\n <!-- Field row -->\n <div class=\"time-field\"\n #timeField\n tabindex=\"0\"\n [class.has-value]=\"hasValue\"\n [class.focused]=\"activeSegment !== null\"\n [class.disabled]=\"isDisabled\"\n [class.open]=\"isPickerOpen\"\n (keydown)=\"onKeyDown($event)\"\n >\n <span class=\"segment\"\n [class.active]=\"activeSegment === 'hours'\"\n (click)=\"activateSegment('hours', $event)\"\n >{{ hours }}</span>\n\n <span class=\"sep\">:</span>\n\n <span class=\"segment\"\n [class.active]=\"activeSegment === 'minutes'\"\n (click)=\"activateSegment('minutes', $event)\"\n >{{ minutes }}</span>\n\n <span *ngIf=\"mode === '12h'\"\n class=\"segment segment--ampm\"\n [class.active]=\"activeSegment === 'ampm'\"\n (click)=\"activateSegment('ampm', $event)\"\n >&nbsp;{{ amPm }}</span>\n\n <!-- Clock icon button -->\n <button class=\"clock-btn\"\n type=\"button\"\n [disabled]=\"isDisabled\"\n tabindex=\"-1\"\n (click)=\"togglePicker($event)\"\n >\n <mat-icon>schedule</mat-icon>\n </button>\n </div>\n\n <!-- Picker panel -->\n <div *ngIf=\"isPickerOpen\" class=\"picker-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-columns\">\n\n <!-- Hours column -->\n <div class=\"picker-col\" #hourCol>\n <div *ngFor=\"let h of hourOptions\"\n class=\"picker-item\"\n [class.selected]=\"h === selectedHourValue\"\n (click)=\"selectHour(h)\"\n >{{ h | number:'2.0-0' }}</div>\n </div>\n\n <div class=\"picker-divider\">:</div>\n\n <!-- Minutes column -->\n <div class=\"picker-col\" #minuteCol>\n <div *ngFor=\"let m of minuteOptions\"\n class=\"picker-item\"\n [class.selected]=\"m === selectedMinuteValue\"\n (click)=\"selectMinute(m)\"\n >{{ m | number:'2.0-0' }}</div>\n </div>\n </div>\n\n <!-- AM/PM row (12h mode only) -->\n <div *ngIf=\"mode === '12h'\" class=\"picker-ampm\">\n <button type=\"button\" [class.active]=\"amPm === 'AM'\" (click)=\"selectAmPm('AM')\">AM</button>\n <button type=\"button\" [class.active]=\"amPm === 'PM'\" (click)=\"selectAmPm('PM')\">PM</button>\n </div>\n </div>\n\n <!-- Error -->\n <div *ngIf=\"!!(ngControl.control.errors && submit)\" class=\"error-text\">\n {{ ngControl.control | generateErrorMessages : (label || '') }}\n </div>\n</div>\n", styles: [".time-input{position:relative;display:inline-block}.time-input__label-row{display:flex;align-items:center;gap:2px;margin-bottom:4px}.time-input__label{font-size:14px;line-height:19px;color:var(--input-label-color, #647081);display:inline-block}.time-input__required{color:var(--error-border-color, #f44336);font-size:14px}.time-field{display:flex;align-items:center;border:1px solid #e0e0e0;border-radius:4px;height:34px;padding:3px 5px 3px 8px;cursor:pointer;box-sizing:border-box;outline:none;background:var(--white-color, #fff)}.time-field:hover:not(.disabled){border-color:#9fa6b1}.time-field.focused{border-color:#0060df;border-width:2px;padding:2px 4px 2px 7px}.time-field.disabled{background-color:var(--disabled-input-background, #f5f5f5);cursor:default;pointer-events:none}.segment{min-width:18px;text-align:center;border-radius:2px;padding:1px 2px;font-size:13px;font-family:Noto Sans,sans-serif;color:var(--neutral30, #424954);-webkit-user-select:none;user-select:none}.segment.active{background:#0060df;color:#fff;border-radius:2px}.segment--ampm{min-width:28px}.time-field:not(.has-value) .segment{color:var(--placeholder-color, #aaa)}.sep{font-size:13px;color:var(--neutral30, #424954);margin:0 1px;-webkit-user-select:none;user-select:none}.time-field:not(.has-value) .sep{color:var(--placeholder-color, #aaa)}.clock-btn{display:flex;align-items:center;justify-content:center;border:none;background:transparent;cursor:pointer;padding:0;margin-left:auto;outline:none;color:var(--neutral50, #647081)}.clock-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.clock-btn:disabled{opacity:.4;cursor:default}.picker-panel{position:absolute;z-index:1000;background:#fff;border-radius:8px;box-shadow:0 4px 16px #00000026;min-width:150px;top:calc(100% + 4px);left:0}.picker-columns{display:flex;align-items:flex-start;gap:4px;padding:8px 4px 8px 8px}.picker-divider{font-size:16px;color:var(--neutral30, #424954);padding-top:6px;align-self:flex-start;-webkit-user-select:none;user-select:none}.picker-col{height:160px;overflow-y:auto;width:50px;scrollbar-width:thin}.picker-col::-webkit-scrollbar{width:4px}.picker-col::-webkit-scrollbar-thumb{background:var(--neutral80, #d7d9de);border-radius:2px}.picker-item{padding:6px 8px;text-align:center;cursor:pointer;border-radius:4px;font-size:13px;font-family:Noto Sans,sans-serif;color:var(--neutral30, #424954)}.picker-item:hover{background:var(--secondary95, #f0f4ff)}.picker-item.selected{background:#0060df;color:#fff;font-weight:600}.picker-ampm{display:flex;justify-content:center;gap:8px;padding:8px;border-top:1px solid var(--neutral90, #e0e0e0)}.picker-ampm button{padding:4px 16px;border:1px solid var(--neutral80, #d7d9de);border-radius:4px;background:transparent;cursor:pointer;font-size:13px;font-family:Noto Sans,sans-serif;color:var(--neutral30, #424954)}.picker-ampm button:hover{background:var(--secondary95, #f0f4ff)}.picker-ampm button.active{background:#0060df;color:#fff;border-color:#0060df;font-weight:600}.error-text{font-size:10px;color:var(--error-border-color, #f44336);padding-top:2px;line-height:14px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: GenerateErrorMessagesPipe, name: "generateErrorMessages" }] }); }
3297
+ }
3298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TimeInputComponent, decorators: [{
3299
+ type: Component,
3300
+ args: [{ selector: 'i-tech-time-input', standalone: true, imports: [
3301
+ NgIf, NgFor, NgClass, DecimalPipe,
3302
+ ReactiveFormsModule, TranslateModule,
3303
+ MatIcon, GenerateErrorMessagesPipe
3304
+ ], template: "<div *ngIf=\"ngControl\" class=\"time-input\">\n\n <!-- Label row -->\n <div *ngIf=\"label\" class=\"time-input__label-row\">\n <span class=\"time-input__label\">{{ label | translate }}</span>\n <span *ngIf=\"required\" class=\"time-input__required\">*</span>\n </div>\n\n <!-- Field row -->\n <div class=\"time-field\"\n #timeField\n tabindex=\"0\"\n [class.has-value]=\"hasValue\"\n [class.focused]=\"activeSegment !== null\"\n [class.disabled]=\"isDisabled\"\n [class.open]=\"isPickerOpen\"\n (keydown)=\"onKeyDown($event)\"\n >\n <span class=\"segment\"\n [class.active]=\"activeSegment === 'hours'\"\n (click)=\"activateSegment('hours', $event)\"\n >{{ hours }}</span>\n\n <span class=\"sep\">:</span>\n\n <span class=\"segment\"\n [class.active]=\"activeSegment === 'minutes'\"\n (click)=\"activateSegment('minutes', $event)\"\n >{{ minutes }}</span>\n\n <span *ngIf=\"mode === '12h'\"\n class=\"segment segment--ampm\"\n [class.active]=\"activeSegment === 'ampm'\"\n (click)=\"activateSegment('ampm', $event)\"\n >&nbsp;{{ amPm }}</span>\n\n <!-- Clock icon button -->\n <button class=\"clock-btn\"\n type=\"button\"\n [disabled]=\"isDisabled\"\n tabindex=\"-1\"\n (click)=\"togglePicker($event)\"\n >\n <mat-icon>schedule</mat-icon>\n </button>\n </div>\n\n <!-- Picker panel -->\n <div *ngIf=\"isPickerOpen\" class=\"picker-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"picker-columns\">\n\n <!-- Hours column -->\n <div class=\"picker-col\" #hourCol>\n <div *ngFor=\"let h of hourOptions\"\n class=\"picker-item\"\n [class.selected]=\"h === selectedHourValue\"\n (click)=\"selectHour(h)\"\n >{{ h | number:'2.0-0' }}</div>\n </div>\n\n <div class=\"picker-divider\">:</div>\n\n <!-- Minutes column -->\n <div class=\"picker-col\" #minuteCol>\n <div *ngFor=\"let m of minuteOptions\"\n class=\"picker-item\"\n [class.selected]=\"m === selectedMinuteValue\"\n (click)=\"selectMinute(m)\"\n >{{ m | number:'2.0-0' }}</div>\n </div>\n </div>\n\n <!-- AM/PM row (12h mode only) -->\n <div *ngIf=\"mode === '12h'\" class=\"picker-ampm\">\n <button type=\"button\" [class.active]=\"amPm === 'AM'\" (click)=\"selectAmPm('AM')\">AM</button>\n <button type=\"button\" [class.active]=\"amPm === 'PM'\" (click)=\"selectAmPm('PM')\">PM</button>\n </div>\n </div>\n\n <!-- Error -->\n <div *ngIf=\"!!(ngControl.control.errors && submit)\" class=\"error-text\">\n {{ ngControl.control | generateErrorMessages : (label || '') }}\n </div>\n</div>\n", styles: [".time-input{position:relative;display:inline-block}.time-input__label-row{display:flex;align-items:center;gap:2px;margin-bottom:4px}.time-input__label{font-size:14px;line-height:19px;color:var(--input-label-color, #647081);display:inline-block}.time-input__required{color:var(--error-border-color, #f44336);font-size:14px}.time-field{display:flex;align-items:center;border:1px solid #e0e0e0;border-radius:4px;height:34px;padding:3px 5px 3px 8px;cursor:pointer;box-sizing:border-box;outline:none;background:var(--white-color, #fff)}.time-field:hover:not(.disabled){border-color:#9fa6b1}.time-field.focused{border-color:#0060df;border-width:2px;padding:2px 4px 2px 7px}.time-field.disabled{background-color:var(--disabled-input-background, #f5f5f5);cursor:default;pointer-events:none}.segment{min-width:18px;text-align:center;border-radius:2px;padding:1px 2px;font-size:13px;font-family:Noto Sans,sans-serif;color:var(--neutral30, #424954);-webkit-user-select:none;user-select:none}.segment.active{background:#0060df;color:#fff;border-radius:2px}.segment--ampm{min-width:28px}.time-field:not(.has-value) .segment{color:var(--placeholder-color, #aaa)}.sep{font-size:13px;color:var(--neutral30, #424954);margin:0 1px;-webkit-user-select:none;user-select:none}.time-field:not(.has-value) .sep{color:var(--placeholder-color, #aaa)}.clock-btn{display:flex;align-items:center;justify-content:center;border:none;background:transparent;cursor:pointer;padding:0;margin-left:auto;outline:none;color:var(--neutral50, #647081)}.clock-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.clock-btn:disabled{opacity:.4;cursor:default}.picker-panel{position:absolute;z-index:1000;background:#fff;border-radius:8px;box-shadow:0 4px 16px #00000026;min-width:150px;top:calc(100% + 4px);left:0}.picker-columns{display:flex;align-items:flex-start;gap:4px;padding:8px 4px 8px 8px}.picker-divider{font-size:16px;color:var(--neutral30, #424954);padding-top:6px;align-self:flex-start;-webkit-user-select:none;user-select:none}.picker-col{height:160px;overflow-y:auto;width:50px;scrollbar-width:thin}.picker-col::-webkit-scrollbar{width:4px}.picker-col::-webkit-scrollbar-thumb{background:var(--neutral80, #d7d9de);border-radius:2px}.picker-item{padding:6px 8px;text-align:center;cursor:pointer;border-radius:4px;font-size:13px;font-family:Noto Sans,sans-serif;color:var(--neutral30, #424954)}.picker-item:hover{background:var(--secondary95, #f0f4ff)}.picker-item.selected{background:#0060df;color:#fff;font-weight:600}.picker-ampm{display:flex;justify-content:center;gap:8px;padding:8px;border-top:1px solid var(--neutral90, #e0e0e0)}.picker-ampm button{padding:4px 16px;border:1px solid var(--neutral80, #d7d9de);border-radius:4px;background:transparent;cursor:pointer;font-size:13px;font-family:Noto Sans,sans-serif;color:var(--neutral30, #424954)}.picker-ampm button:hover{background:var(--secondary95, #f0f4ff)}.picker-ampm button.active{background:#0060df;color:#fff;border-color:#0060df;font-weight:600}.error-text{font-size:10px;color:var(--error-border-color, #f44336);padding-top:2px;line-height:14px}\n"] }]
3305
+ }], ctorParameters: () => [{ type: InputService }], propDecorators: { submit: [{
3306
+ type: Input
3307
+ }], label: [{
3308
+ type: Input
3309
+ }], required: [{
3310
+ type: Input
3311
+ }], mode: [{
3312
+ type: Input
3313
+ }], readOnly: [{
3314
+ type: Input
3315
+ }], selectionChanges: [{
3316
+ type: Output
3317
+ }], timeFieldEl: [{
3318
+ type: ViewChild,
3319
+ args: ['timeField']
3320
+ }], hourColEl: [{
3321
+ type: ViewChild,
3322
+ args: ['hourCol']
3323
+ }], minuteColEl: [{
3324
+ type: ViewChild,
3325
+ args: ['minuteCol']
3326
+ }], onDocumentClick: [{
3327
+ type: HostListener,
3328
+ args: ['document:click']
3329
+ }] } });
3330
+
2915
3331
  /*
2916
3332
  * Public API Surface of shared-components
2917
3333
  */
@@ -2920,5 +3336,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
2920
3336
  * Generated bundle index. Do not edit.
2921
3337
  */
2922
3338
 
2923
- export { AgGridButtonCellComponent, AgGridFunctionsService, ArrayToStringPipe, AutocompleteSelectComponent, ButtonComponent, ButtonType, ClearValueComponent, CompaniesEnum, DATA_ENDPOINT, DatePickerComponent, DateRangeDatepickerComponent, DateRangeSelectionComponent, DateTimePickerComponent, DriverCategories, DriverCategoryEnum, DriverStatus, GenerateErrorMessagesPipe, GetValueByKeyFromObjectPipe, IconButtonComponent, InputMaskDirective, InputService, LabelComponent, LabelTypeEnum, MenuComponent, NewSidebarComponent, ParseDateService, PhoneNumberInputComponent, ProcessedStatusCellRendererComponent, RoleEnum, SegmentedButtonComponent, SelectWithSearchComponent, TextInputComponent, TooltipCellRendererComponent, formatPhoneNumber, internationalPhoneValidator };
3339
+ export { AgGridButtonCellComponent, AgGridFunctionsService, ArrayToStringPipe, AutocompleteSelectComponent, ButtonComponent, ButtonType, ClearValueComponent, CompaniesEnum, DATA_ENDPOINT, DatePickerComponent, DateRangeDatepickerComponent, DateRangeSelectionComponent, DateTimePickerComponent, DriverCategories, DriverCategoryEnum, DriverStatus, GenerateErrorMessagesPipe, GetValueByKeyFromObjectPipe, IconButtonComponent, InputMaskDirective, InputService, LabelComponent, LabelTypeEnum, MenuComponent, NewSidebarComponent, ParseDateService, PhoneNumberInputComponent, ProcessedStatusCellRendererComponent, RoleEnum, SegmentedButtonComponent, SelectWithSearchComponent, TextInputComponent, TimeInputComponent, TooltipCellRendererComponent, formatPhoneNumber, internationalPhoneValidator };
2924
3340
  //# sourceMappingURL=i-tech-shared-components.mjs.map