ngx-com 0.0.18 → 0.0.20

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.
Files changed (48) hide show
  1. package/fesm2022/ngx-com-components-alert.mjs +346 -0
  2. package/fesm2022/ngx-com-components-alert.mjs.map +1 -0
  3. package/fesm2022/ngx-com-components-button.mjs +1 -1
  4. package/fesm2022/ngx-com-components-button.mjs.map +1 -1
  5. package/fesm2022/ngx-com-components-calendar.mjs +1267 -48
  6. package/fesm2022/ngx-com-components-calendar.mjs.map +1 -1
  7. package/fesm2022/ngx-com-components-card.mjs +1 -1
  8. package/fesm2022/ngx-com-components-card.mjs.map +1 -1
  9. package/fesm2022/ngx-com-components-carousel.mjs +708 -0
  10. package/fesm2022/ngx-com-components-carousel.mjs.map +1 -0
  11. package/fesm2022/ngx-com-components-checkbox.mjs +1 -1
  12. package/fesm2022/ngx-com-components-checkbox.mjs.map +1 -1
  13. package/fesm2022/ngx-com-components-code-block.mjs +158 -0
  14. package/fesm2022/ngx-com-components-code-block.mjs.map +1 -0
  15. package/fesm2022/ngx-com-components-collapsible.mjs +1 -1
  16. package/fesm2022/ngx-com-components-collapsible.mjs.map +1 -1
  17. package/fesm2022/ngx-com-components-confirm.mjs +3 -3
  18. package/fesm2022/ngx-com-components-confirm.mjs.map +1 -1
  19. package/fesm2022/ngx-com-components-dialog.mjs +703 -0
  20. package/fesm2022/ngx-com-components-dialog.mjs.map +1 -0
  21. package/fesm2022/ngx-com-components-dropdown.mjs +18 -21
  22. package/fesm2022/ngx-com-components-dropdown.mjs.map +1 -1
  23. package/fesm2022/ngx-com-components-item.mjs +1 -1
  24. package/fesm2022/ngx-com-components-item.mjs.map +1 -1
  25. package/fesm2022/ngx-com-components-paginator.mjs +3 -3
  26. package/fesm2022/ngx-com-components-paginator.mjs.map +1 -1
  27. package/fesm2022/ngx-com-components-radio.mjs +1 -1
  28. package/fesm2022/ngx-com-components-radio.mjs.map +1 -1
  29. package/fesm2022/ngx-com-components-segmented-control.mjs +1 -1
  30. package/fesm2022/ngx-com-components-segmented-control.mjs.map +1 -1
  31. package/fesm2022/ngx-com-components-switch.mjs +258 -0
  32. package/fesm2022/ngx-com-components-switch.mjs.map +1 -0
  33. package/fesm2022/ngx-com-components-table.mjs +631 -0
  34. package/fesm2022/ngx-com-components-table.mjs.map +1 -0
  35. package/fesm2022/ngx-com-components-tabs.mjs +2 -2
  36. package/fesm2022/ngx-com-components-tabs.mjs.map +1 -1
  37. package/fesm2022/ngx-com-components-toast.mjs +783 -0
  38. package/fesm2022/ngx-com-components-toast.mjs.map +1 -0
  39. package/package.json +29 -1
  40. package/types/ngx-com-components-alert.d.ts +166 -0
  41. package/types/ngx-com-components-calendar.d.ts +281 -5
  42. package/types/ngx-com-components-carousel.d.ts +281 -0
  43. package/types/ngx-com-components-code-block.d.ts +66 -0
  44. package/types/ngx-com-components-confirm.d.ts +2 -2
  45. package/types/ngx-com-components-dialog.d.ts +264 -0
  46. package/types/ngx-com-components-switch.d.ts +110 -0
  47. package/types/ngx-com-components-table.d.ts +377 -0
  48. package/types/ngx-com-components-toast.d.ts +217 -0
@@ -242,6 +242,33 @@ class NativeDateAdapter extends DateAdapter {
242
242
  return dateDiff > 0 ? 1 : -1;
243
243
  return 0;
244
244
  }
245
+ getHours(date) {
246
+ return date.getHours();
247
+ }
248
+ getMinutes(date) {
249
+ return date.getMinutes();
250
+ }
251
+ getSeconds(date) {
252
+ return date.getSeconds();
253
+ }
254
+ setTime(date, hours, minutes, seconds) {
255
+ const result = new Date(date);
256
+ result.setHours(hours, minutes, seconds, 0);
257
+ return result;
258
+ }
259
+ createDateTime(year, month, day, hours, minutes, seconds) {
260
+ if (month < 0 || month > 11) {
261
+ throw new Error(`Invalid month index "${month}". Month index must be between 0 and 11.`);
262
+ }
263
+ if (day < 1) {
264
+ throw new Error(`Invalid date "${day}". Date must be greater than 0.`);
265
+ }
266
+ const result = new Date(year, month, day, hours, minutes, seconds);
267
+ if (result.getMonth() !== month) {
268
+ throw new Error(`Invalid date "${day}" for month index "${month}".`);
269
+ }
270
+ return result;
271
+ }
245
272
  clampDate(date, min, max) {
246
273
  if (min && this.compareDate(date, min) < 0) {
247
274
  return min;
@@ -278,6 +305,11 @@ class NativeDateAdapter extends DateAdapter {
278
305
  monthYearShort: { year: 'numeric', month: 'short' },
279
306
  dayMonth: { day: 'numeric', month: 'long' },
280
307
  dayMonthYear: { day: 'numeric', month: 'long', year: 'numeric' },
308
+ time: { hour: 'numeric', minute: '2-digit' },
309
+ timeWithSeconds: { hour: 'numeric', minute: '2-digit', second: '2-digit' },
310
+ dateTimeShort: { dateStyle: 'short', timeStyle: 'short' },
311
+ dateTimeMedium: { dateStyle: 'medium', timeStyle: 'short' },
312
+ dateTimeLong: { dateStyle: 'long', timeStyle: 'medium' },
281
313
  };
282
314
  return formatMap[format] ?? { dateStyle: 'medium' };
283
315
  }
@@ -308,10 +340,9 @@ const calendarCellVariants = cva(
308
340
  'select-none',
309
341
  'transition-colors',
310
342
  'duration-150',
311
- 'outline-none',
312
- 'focus-visible:ring-2',
313
- 'focus-visible:ring-offset-2',
314
- 'focus-visible:ring-ring',
343
+ 'focus-visible:outline-[1px]',
344
+ 'focus-visible:outline-offset-2',
345
+ 'focus-visible:outline-ring',
315
346
  ], {
316
347
  variants: {
317
348
  view: {
@@ -451,11 +482,10 @@ const calendarHeaderButtonVariants = cva([
451
482
  'select-none',
452
483
  'transition-colors',
453
484
  'duration-150',
454
- 'outline-none',
455
485
  'text-foreground',
456
- 'focus-visible:ring-2',
457
- 'focus-visible:ring-offset-2',
458
- 'focus-visible:ring-ring',
486
+ 'focus-visible:outline-[1px]',
487
+ 'focus-visible:outline-offset-2',
488
+ 'focus-visible:outline-ring',
459
489
  'disabled:cursor-not-allowed',
460
490
  'disabled:text-disabled-foreground',
461
491
  ], {
@@ -3086,14 +3116,12 @@ const datepickerTriggerVariants = cva([
3086
3116
  'border',
3087
3117
  'bg-input-background',
3088
3118
  'text-input-foreground',
3089
- 'ring-offset-background',
3090
3119
  'transition-colors',
3091
3120
  'duration-150',
3092
3121
  'placeholder:text-input-placeholder',
3093
- 'focus-within:outline-none',
3094
- 'focus-within:ring-2',
3095
- 'focus-within:ring-offset-2',
3096
- 'focus-within:ring-ring',
3122
+ 'focus-within:outline-[1px]',
3123
+ 'focus-within:outline-offset-2',
3124
+ 'focus-within:outline-ring',
3097
3125
  'cursor-pointer',
3098
3126
  ], {
3099
3127
  variants: {
@@ -3127,15 +3155,15 @@ const datepickerTriggerVariants = cva([
3127
3155
  default: [],
3128
3156
  error: [
3129
3157
  'border-warn',
3130
- 'focus-within:ring-warn',
3158
+ 'focus-within:outline-warn',
3131
3159
  ],
3132
3160
  success: [
3133
3161
  'border-success',
3134
- 'focus-within:ring-success',
3162
+ 'focus-within:outline-success',
3135
3163
  ],
3136
3164
  },
3137
3165
  open: {
3138
- true: ['ring-2', 'ring-ring', 'border-primary'],
3166
+ true: ['outline-[1px]', 'outline-ring', 'border-primary'],
3139
3167
  false: [],
3140
3168
  },
3141
3169
  },
@@ -3208,9 +3236,9 @@ const datepickerIconVariants = cva([
3208
3236
  'text-muted-foreground',
3209
3237
  'transition-colors',
3210
3238
  'hover:text-foreground',
3211
- 'focus:outline-none',
3212
- 'focus:ring-1',
3213
- 'focus:ring-ring',
3239
+ 'focus-visible:outline-[1px]',
3240
+ 'focus-visible:outline-offset-2',
3241
+ 'focus-visible:outline-ring',
3214
3242
  'rounded-interactive-sm',
3215
3243
  ], {
3216
3244
  variants: {
@@ -3237,9 +3265,9 @@ const datepickerClearVariants = cva([
3237
3265
  'text-muted-foreground',
3238
3266
  'transition-colors',
3239
3267
  'hover:text-foreground',
3240
- 'focus:outline-none',
3241
- 'focus:ring-1',
3242
- 'focus:ring-ring',
3268
+ 'focus-visible:outline-[1px]',
3269
+ 'focus-visible:outline-offset-2',
3270
+ 'focus-visible:outline-ring',
3243
3271
  'shrink-0',
3244
3272
  ], {
3245
3273
  variants: {
@@ -3318,10 +3346,9 @@ const datepickerFooterButtonVariants = cva([
3318
3346
  'rounded-control-sm',
3319
3347
  'font-medium',
3320
3348
  'transition-colors',
3321
- 'focus:outline-none',
3322
- 'focus:ring-2',
3323
- 'focus:ring-ring',
3324
- 'focus:ring-offset-2',
3349
+ 'focus-visible:outline-[1px]',
3350
+ 'focus-visible:outline-offset-2',
3351
+ 'focus-visible:outline-ring',
3325
3352
  ], {
3326
3353
  variants: {
3327
3354
  size: {
@@ -3371,6 +3398,943 @@ const datepickerRangeSeparatorVariants = cva([
3371
3398
  },
3372
3399
  });
3373
3400
 
3401
+ /**
3402
+ * CVA variants for the time picker container.
3403
+ *
3404
+ * @tokens `--color-input-background`, `--color-input-foreground`, `--color-input-border`,
3405
+ * `--color-ring`, `--color-warn`, `--color-success`, `--radius-input`
3406
+ */
3407
+ const timepickerContainerVariants = cva([
3408
+ 'inline-flex',
3409
+ 'items-center',
3410
+ 'gap-1',
3411
+ 'rounded-input',
3412
+ 'transition-colors',
3413
+ 'duration-150',
3414
+ ], {
3415
+ variants: {
3416
+ variant: {
3417
+ standalone: [
3418
+ 'border',
3419
+ 'border-input-border',
3420
+ 'bg-input-background',
3421
+ 'text-input-foreground',
3422
+ 'focus-within:outline-[1px]',
3423
+ 'focus-within:outline-offset-2',
3424
+ 'focus-within:outline-ring',
3425
+ ],
3426
+ embedded: [
3427
+ 'border-transparent',
3428
+ 'bg-transparent',
3429
+ 'text-foreground',
3430
+ ],
3431
+ },
3432
+ size: {
3433
+ sm: ['h-8', 'px-2', 'text-xs', 'gap-0.5'],
3434
+ default: ['h-10', 'px-3', 'text-sm', 'gap-1'],
3435
+ lg: ['h-12', 'px-4', 'text-base', 'gap-1.5'],
3436
+ },
3437
+ state: {
3438
+ default: [],
3439
+ error: [
3440
+ 'border-warn',
3441
+ 'focus-within:outline-warn',
3442
+ ],
3443
+ success: [
3444
+ 'border-success',
3445
+ 'focus-within:outline-success',
3446
+ ],
3447
+ },
3448
+ },
3449
+ compoundVariants: [
3450
+ {
3451
+ variant: 'embedded',
3452
+ state: 'error',
3453
+ class: [],
3454
+ },
3455
+ {
3456
+ variant: 'embedded',
3457
+ state: 'success',
3458
+ class: [],
3459
+ },
3460
+ ],
3461
+ defaultVariants: {
3462
+ variant: 'standalone',
3463
+ size: 'default',
3464
+ state: 'default',
3465
+ },
3466
+ });
3467
+ /**
3468
+ * CVA variants for the disabled state of time picker.
3469
+ *
3470
+ * @tokens `--color-disabled`, `--color-disabled-foreground`
3471
+ */
3472
+ const timepickerDisabledVariants = cva([
3473
+ 'cursor-not-allowed',
3474
+ 'bg-disabled',
3475
+ 'text-disabled-foreground',
3476
+ 'pointer-events-none',
3477
+ ]);
3478
+ /**
3479
+ * CVA variants for each time segment input.
3480
+ *
3481
+ * @tokens `--color-primary-subtle`, `--color-primary-subtle-foreground`, `--radius-interactive-sm`
3482
+ */
3483
+ const timepickerSegmentVariants = cva([
3484
+ 'bg-transparent',
3485
+ 'outline-none',
3486
+ 'text-center',
3487
+ 'font-mono',
3488
+ 'tabular-nums',
3489
+ 'select-all',
3490
+ 'focus:bg-primary-subtle',
3491
+ 'focus:text-primary-subtle-foreground',
3492
+ 'focus:rounded-interactive-sm',
3493
+ ], {
3494
+ variants: {
3495
+ size: {
3496
+ sm: ['w-5', 'text-xs'],
3497
+ default: ['w-7', 'text-sm'],
3498
+ lg: ['w-9', 'text-base'],
3499
+ },
3500
+ },
3501
+ defaultVariants: {
3502
+ size: 'default',
3503
+ },
3504
+ });
3505
+ /**
3506
+ * CVA variants for the colon separator.
3507
+ *
3508
+ * @tokens `--color-muted-foreground`
3509
+ */
3510
+ const timepickerSeparatorVariants = cva([
3511
+ 'text-muted-foreground',
3512
+ 'select-none',
3513
+ 'font-mono',
3514
+ ], {
3515
+ variants: {
3516
+ size: {
3517
+ sm: ['text-xs'],
3518
+ default: ['text-sm'],
3519
+ lg: ['text-base'],
3520
+ },
3521
+ },
3522
+ defaultVariants: {
3523
+ size: 'default',
3524
+ },
3525
+ });
3526
+ /**
3527
+ * CVA variants for the AM/PM toggle button.
3528
+ *
3529
+ * @tokens `--color-muted`, `--color-muted-foreground`, `--color-muted-hover`, `--color-ring`,
3530
+ * `--radius-control-sm`
3531
+ */
3532
+ const timepickerPeriodVariants = cva([
3533
+ 'inline-flex',
3534
+ 'items-center',
3535
+ 'justify-center',
3536
+ 'rounded-control-sm',
3537
+ 'font-medium',
3538
+ 'transition-colors',
3539
+ 'select-none',
3540
+ 'bg-muted',
3541
+ 'text-muted-foreground',
3542
+ 'hover:bg-muted-hover',
3543
+ 'focus-visible:outline-[1px]',
3544
+ 'focus-visible:outline-offset-2',
3545
+ 'focus-visible:outline-ring',
3546
+ ], {
3547
+ variants: {
3548
+ size: {
3549
+ sm: ['h-5', 'px-1', 'text-xs', 'ml-0.5'],
3550
+ default: ['h-6', 'px-1.5', 'text-xs', 'ml-1'],
3551
+ lg: ['h-7', 'px-2', 'text-sm', 'ml-1.5'],
3552
+ },
3553
+ },
3554
+ defaultVariants: {
3555
+ size: 'default',
3556
+ },
3557
+ });
3558
+ /**
3559
+ * CVA variants for the time section divider in datepicker panel.
3560
+ *
3561
+ * @tokens `--color-border-subtle`
3562
+ */
3563
+ const timepickerSectionVariants = cva([
3564
+ 'flex',
3565
+ 'items-center',
3566
+ 'justify-center',
3567
+ 'border-t',
3568
+ 'border-border-subtle',
3569
+ ], {
3570
+ variants: {
3571
+ size: {
3572
+ sm: ['pt-2', 'mt-2'],
3573
+ default: ['pt-3', 'mt-3'],
3574
+ lg: ['pt-4', 'mt-4'],
3575
+ },
3576
+ },
3577
+ defaultVariants: {
3578
+ size: 'default',
3579
+ },
3580
+ });
3581
+ /**
3582
+ * CVA variants for time labels in date range picker.
3583
+ *
3584
+ * @tokens `--color-muted-foreground`
3585
+ */
3586
+ const timepickerLabelVariants = cva([
3587
+ 'text-muted-foreground',
3588
+ 'font-medium',
3589
+ ], {
3590
+ variants: {
3591
+ size: {
3592
+ sm: ['text-xs'],
3593
+ default: ['text-xs'],
3594
+ lg: ['text-sm'],
3595
+ },
3596
+ },
3597
+ defaultVariants: {
3598
+ size: 'default',
3599
+ },
3600
+ });
3601
+
3602
+ /**
3603
+ * Types and interfaces for the TimePicker component.
3604
+ */
3605
+ /** Creates a ComTimeValue */
3606
+ function createTimeValue(hours = 0, minutes = 0, seconds = 0) {
3607
+ return { hours, minutes, seconds };
3608
+ }
3609
+ /**
3610
+ * Compares two ComTimeValue objects.
3611
+ * @returns negative if a < b, 0 if equal, positive if a > b
3612
+ */
3613
+ function compareTime(a, b) {
3614
+ const diff = a.hours * 3600 + a.minutes * 60 + a.seconds - (b.hours * 3600 + b.minutes * 60 + b.seconds);
3615
+ return diff;
3616
+ }
3617
+ /** Generates a unique ID for time picker instances */
3618
+ let timePickerIdCounter = 0;
3619
+ function generateTimePickerId() {
3620
+ return `com-time-picker-${timePickerIdCounter++}`;
3621
+ }
3622
+
3623
+ /**
3624
+ * Time picker component with segmented numeric input fields.
3625
+ * Supports standalone usage with ControlValueAccessor and embedded usage
3626
+ * within datepicker/date-range-picker panels.
3627
+ *
3628
+ * Visual layout: `[HH] : [MM] : [SS] [AM|PM]`
3629
+ *
3630
+ * @tokens `--color-input-background`, `--color-input-foreground`, `--color-input-border`,
3631
+ * `--color-ring`, `--color-primary-subtle`, `--color-primary-subtle-foreground`,
3632
+ * `--color-muted`, `--color-muted-foreground`, `--color-muted-hover`,
3633
+ * `--color-disabled`, `--color-disabled-foreground`,
3634
+ * `--color-warn`, `--color-success`, `--color-border`
3635
+ *
3636
+ * @example
3637
+ * ```html
3638
+ * <!-- Standalone with reactive forms -->
3639
+ * <com-time-picker formControlName="startTime" />
3640
+ *
3641
+ * <!-- 12-hour format with seconds -->
3642
+ * <com-time-picker formControlName="alarm" [use12HourFormat]="true" [showSeconds]="true" />
3643
+ *
3644
+ * <!-- 15-minute steps -->
3645
+ * <com-time-picker formControlName="meeting" [minuteStep]="15" />
3646
+ *
3647
+ * <!-- Embedded inside datepicker panel -->
3648
+ * <com-time-picker variant="embedded" [value]="time" (timeChange)="onTime($event)" />
3649
+ * ```
3650
+ */
3651
+ class ComTimePicker {
3652
+ localeId = inject(LOCALE_ID);
3653
+ ngControl = inject(NgControl, { optional: true, self: true });
3654
+ timepickerId = generateTimePickerId();
3655
+ hoursInputRef = viewChild('hoursInput', ...(ngDevMode ? [{ debugName: "hoursInputRef" }] : []));
3656
+ minutesInputRef = viewChild('minutesInput', ...(ngDevMode ? [{ debugName: "minutesInputRef" }] : []));
3657
+ secondsInputRef = viewChild('secondsInput', ...(ngDevMode ? [{ debugName: "secondsInputRef" }] : []));
3658
+ periodButtonRef = viewChild('periodButton', ...(ngDevMode ? [{ debugName: "periodButtonRef" }] : []));
3659
+ // ============ INPUTS ============
3660
+ /** Current time value. */
3661
+ value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
3662
+ /** Whether the time picker is disabled. */
3663
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
3664
+ /** Whether the time picker is required. */
3665
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
3666
+ /** Whether to show the seconds segment. */
3667
+ showSeconds = input(false, ...(ngDevMode ? [{ debugName: "showSeconds" }] : []));
3668
+ /** 12h vs 24h format. `null` = auto-detect from locale. */
3669
+ use12HourFormat = input(null, ...(ngDevMode ? [{ debugName: "use12HourFormat" }] : []));
3670
+ /** Step interval for minutes. */
3671
+ minuteStep = input(1, ...(ngDevMode ? [{ debugName: "minuteStep" }] : []));
3672
+ /** Step interval for seconds. */
3673
+ secondStep = input(1, ...(ngDevMode ? [{ debugName: "secondStep" }] : []));
3674
+ /** Minimum selectable time. */
3675
+ minTime = input(null, ...(ngDevMode ? [{ debugName: "minTime" }] : []));
3676
+ /** Maximum selectable time. */
3677
+ maxTime = input(null, ...(ngDevMode ? [{ debugName: "maxTime" }] : []));
3678
+ /** Visual variant. */
3679
+ variant = input('standalone', ...(ngDevMode ? [{ debugName: "variant" }] : []));
3680
+ /** Size variant. */
3681
+ size = input('default', ...(ngDevMode ? [{ debugName: "size" }] : []));
3682
+ /** Validation state. */
3683
+ state = input('default', ...(ngDevMode ? [{ debugName: "state" }] : []));
3684
+ /** Accessible label for the group. */
3685
+ ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
3686
+ /** Additional CSS classes. */
3687
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : {}), alias: 'class' });
3688
+ /** Placeholder text for empty segments. */
3689
+ placeholder = input('--', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
3690
+ // ============ OUTPUTS ============
3691
+ /** Emitted when time value changes. */
3692
+ timeChange = output();
3693
+ // ============ INTERNAL STATE ============
3694
+ /** Internal value state. */
3695
+ internalValue = linkedSignal(() => this.value() ?? null, ...(ngDevMode ? [{ debugName: "internalValue" }] : []));
3696
+ /** Which segment is currently focused. */
3697
+ activeSegment = signal(null, ...(ngDevMode ? [{ debugName: "activeSegment" }] : []));
3698
+ /** Pending typed digits for auto-advance. */
3699
+ pendingDigits = signal('', ...(ngDevMode ? [{ debugName: "pendingDigits" }] : []));
3700
+ /** Live announcements for screen readers. */
3701
+ liveAnnouncement = signal('', ...(ngDevMode ? [{ debugName: "liveAnnouncement" }] : []));
3702
+ // ============ COMPUTED STATE ============
3703
+ /** Whether to use 12-hour format. */
3704
+ is12Hour = computed(() => {
3705
+ const explicit = this.use12HourFormat();
3706
+ if (explicit !== null)
3707
+ return explicit;
3708
+ try {
3709
+ const options = new Intl.DateTimeFormat(this.localeId, { hour: 'numeric' }).resolvedOptions();
3710
+ return options.hour12 === true;
3711
+ }
3712
+ catch {
3713
+ return false;
3714
+ }
3715
+ }, ...(ngDevMode ? [{ debugName: "is12Hour" }] : []));
3716
+ /** Current period (AM/PM). */
3717
+ period = computed(() => {
3718
+ const value = this.internalValue();
3719
+ if (!value)
3720
+ return 'AM';
3721
+ return value.hours >= 12 ? 'PM' : 'AM';
3722
+ }, ...(ngDevMode ? [{ debugName: "period" }] : []));
3723
+ /** Display hours (converted from 24h to 12h when needed). */
3724
+ displayHours = computed(() => {
3725
+ const value = this.internalValue();
3726
+ if (!value)
3727
+ return null;
3728
+ if (!this.is12Hour())
3729
+ return value.hours;
3730
+ const h = value.hours % 12;
3731
+ return h === 0 ? 12 : h;
3732
+ }, ...(ngDevMode ? [{ debugName: "displayHours" }] : []));
3733
+ /** Formatted hours string. */
3734
+ formattedHours = computed(() => {
3735
+ const h = this.displayHours();
3736
+ if (h === null)
3737
+ return '';
3738
+ return h.toString().padStart(2, '0');
3739
+ }, ...(ngDevMode ? [{ debugName: "formattedHours" }] : []));
3740
+ /** Formatted minutes string. */
3741
+ formattedMinutes = computed(() => {
3742
+ const value = this.internalValue();
3743
+ if (!value)
3744
+ return '';
3745
+ return value.minutes.toString().padStart(2, '0');
3746
+ }, ...(ngDevMode ? [{ debugName: "formattedMinutes" }] : []));
3747
+ /** Formatted seconds string. */
3748
+ formattedSeconds = computed(() => {
3749
+ const value = this.internalValue();
3750
+ if (!value)
3751
+ return '';
3752
+ return value.seconds.toString().padStart(2, '0');
3753
+ }, ...(ngDevMode ? [{ debugName: "formattedSeconds" }] : []));
3754
+ /** Container classes. */
3755
+ containerClasses = computed(() => {
3756
+ const base = timepickerContainerVariants({
3757
+ variant: this.variant(),
3758
+ size: this.size(),
3759
+ state: this.state(),
3760
+ });
3761
+ const disabled = this.disabled() ? timepickerDisabledVariants() : '';
3762
+ return joinClasses(base, disabled, this.userClass());
3763
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
3764
+ /** Segment input classes. */
3765
+ segmentClasses = computed(() => {
3766
+ return timepickerSegmentVariants({ size: this.size() });
3767
+ }, ...(ngDevMode ? [{ debugName: "segmentClasses" }] : []));
3768
+ /** Separator classes. */
3769
+ separatorClasses = computed(() => {
3770
+ return timepickerSeparatorVariants({ size: this.size() });
3771
+ }, ...(ngDevMode ? [{ debugName: "separatorClasses" }] : []));
3772
+ /** Period button classes. */
3773
+ periodClasses = computed(() => {
3774
+ return timepickerPeriodVariants({ size: this.size() });
3775
+ }, ...(ngDevMode ? [{ debugName: "periodClasses" }] : []));
3776
+ // ============ CVA CALLBACKS ============
3777
+ onChange = () => { };
3778
+ onTouched = () => { };
3779
+ onValidatorChange = () => { };
3780
+ constructor() {
3781
+ if (this.ngControl) {
3782
+ this.ngControl.valueAccessor = this;
3783
+ }
3784
+ }
3785
+ // ============ CVA IMPLEMENTATION ============
3786
+ writeValue(value) {
3787
+ this.internalValue.set(value);
3788
+ }
3789
+ registerOnChange(fn) {
3790
+ this.onChange = fn;
3791
+ }
3792
+ registerOnTouched(fn) {
3793
+ this.onTouched = fn;
3794
+ }
3795
+ setDisabledState(_isDisabled) {
3796
+ // Disabled state is handled via the disabled input
3797
+ }
3798
+ // ============ VALIDATOR IMPLEMENTATION ============
3799
+ validate() {
3800
+ const value = this.internalValue();
3801
+ if (this.required() && !value) {
3802
+ return { required: true };
3803
+ }
3804
+ if (value) {
3805
+ const minTime = this.minTime();
3806
+ if (minTime && compareTime(value, minTime) < 0) {
3807
+ return { minTime: { min: minTime, actual: value } };
3808
+ }
3809
+ const maxTime = this.maxTime();
3810
+ if (maxTime && compareTime(value, maxTime) > 0) {
3811
+ return { maxTime: { max: maxTime, actual: value } };
3812
+ }
3813
+ }
3814
+ return null;
3815
+ }
3816
+ registerOnValidatorChange(fn) {
3817
+ this.onValidatorChange = fn;
3818
+ }
3819
+ // ============ EVENT HANDLERS ============
3820
+ onSegmentFocus(segment) {
3821
+ this.activeSegment.set(segment);
3822
+ this.pendingDigits.set('');
3823
+ }
3824
+ onSegmentBlur(segment) {
3825
+ this.activeSegment.set(null);
3826
+ this.pendingDigits.set('');
3827
+ this.snapToStep(segment);
3828
+ this.onTouched();
3829
+ }
3830
+ onSegmentInput(event, segment) {
3831
+ // Prevent default browser input handling — we manage value via keydown
3832
+ const input = event.target;
3833
+ const value = this.internalValue();
3834
+ // Restore the formatted value to prevent browser from changing display
3835
+ if (segment === 'hours') {
3836
+ input.value = this.formattedHours();
3837
+ }
3838
+ else if (segment === 'minutes') {
3839
+ input.value = this.formattedMinutes();
3840
+ }
3841
+ else {
3842
+ input.value = this.formattedSeconds();
3843
+ }
3844
+ }
3845
+ onSegmentKeydown(event, segment) {
3846
+ switch (event.key) {
3847
+ case 'ArrowUp':
3848
+ event.preventDefault();
3849
+ this.incrementSegment(segment, 1);
3850
+ break;
3851
+ case 'ArrowDown':
3852
+ event.preventDefault();
3853
+ this.incrementSegment(segment, -1);
3854
+ break;
3855
+ case 'ArrowRight':
3856
+ event.preventDefault();
3857
+ this.focusNextSegment(segment);
3858
+ break;
3859
+ case 'ArrowLeft':
3860
+ event.preventDefault();
3861
+ this.focusPrevSegment(segment);
3862
+ break;
3863
+ case 'Home':
3864
+ event.preventDefault();
3865
+ this.setSegmentToMin(segment);
3866
+ break;
3867
+ case 'End':
3868
+ event.preventDefault();
3869
+ this.setSegmentToMax(segment);
3870
+ break;
3871
+ case 'Backspace':
3872
+ case 'Delete':
3873
+ event.preventDefault();
3874
+ this.pendingDigits.set('');
3875
+ break;
3876
+ default:
3877
+ if (/^[0-9]$/.test(event.key)) {
3878
+ event.preventDefault();
3879
+ this.handleDigitInput(event.key, segment);
3880
+ }
3881
+ break;
3882
+ }
3883
+ }
3884
+ onPeriodKeydown(event) {
3885
+ switch (event.key) {
3886
+ case 'ArrowUp':
3887
+ case 'ArrowDown':
3888
+ event.preventDefault();
3889
+ this.togglePeriod();
3890
+ break;
3891
+ case 'ArrowLeft':
3892
+ event.preventDefault();
3893
+ this.focusPrevSegment('period');
3894
+ break;
3895
+ case 'a':
3896
+ case 'A':
3897
+ event.preventDefault();
3898
+ this.setPeriod('AM');
3899
+ break;
3900
+ case 'p':
3901
+ case 'P':
3902
+ event.preventDefault();
3903
+ this.setPeriod('PM');
3904
+ break;
3905
+ }
3906
+ }
3907
+ togglePeriod() {
3908
+ const value = this.internalValue();
3909
+ if (!value) {
3910
+ this.updateValue({ hours: 12, minutes: 0, seconds: 0 });
3911
+ return;
3912
+ }
3913
+ const newHours = value.hours >= 12 ? value.hours - 12 : value.hours + 12;
3914
+ this.updateValue({ ...value, hours: newHours });
3915
+ }
3916
+ // ============ PRIVATE METHODS ============
3917
+ setPeriod(period) {
3918
+ const value = this.internalValue();
3919
+ if (!value) {
3920
+ const hours = period === 'AM' ? 0 : 12;
3921
+ this.updateValue({ hours, minutes: 0, seconds: 0 });
3922
+ return;
3923
+ }
3924
+ const currentPeriod = this.period();
3925
+ if (currentPeriod === period)
3926
+ return;
3927
+ const newHours = period === 'AM' ? value.hours - 12 : value.hours + 12;
3928
+ this.updateValue({ ...value, hours: newHours });
3929
+ }
3930
+ incrementSegment(segment, direction) {
3931
+ const value = this.internalValue() ?? { hours: 0, minutes: 0, seconds: 0 };
3932
+ const step = segment === 'minutes' ? this.minuteStep() : segment === 'seconds' ? this.secondStep() : 1;
3933
+ const delta = step * direction;
3934
+ let newValue;
3935
+ switch (segment) {
3936
+ case 'hours': {
3937
+ const max = this.is12Hour() ? 12 : 23;
3938
+ const min = this.is12Hour() ? 1 : 0;
3939
+ let h = this.is12Hour() ? (this.displayHours() ?? min) : value.hours;
3940
+ h += delta;
3941
+ // Wrap
3942
+ if (this.is12Hour()) {
3943
+ if (h > max)
3944
+ h = min;
3945
+ if (h < min)
3946
+ h = max;
3947
+ // Convert back to 24h
3948
+ const isPM = this.period() === 'PM';
3949
+ let h24 = h === 12 ? 0 : h;
3950
+ if (isPM)
3951
+ h24 += 12;
3952
+ newValue = { ...value, hours: h24 };
3953
+ }
3954
+ else {
3955
+ if (h > 23)
3956
+ h = 0;
3957
+ if (h < 0)
3958
+ h = 23;
3959
+ newValue = { ...value, hours: h };
3960
+ }
3961
+ break;
3962
+ }
3963
+ case 'minutes': {
3964
+ let m = value.minutes + delta;
3965
+ if (m > 59)
3966
+ m = 0;
3967
+ if (m < 0)
3968
+ m = 59;
3969
+ newValue = { ...value, minutes: m };
3970
+ break;
3971
+ }
3972
+ case 'seconds': {
3973
+ let s = value.seconds + delta;
3974
+ if (s > 59)
3975
+ s = 0;
3976
+ if (s < 0)
3977
+ s = 59;
3978
+ newValue = { ...value, seconds: s };
3979
+ break;
3980
+ }
3981
+ }
3982
+ this.updateValue(newValue);
3983
+ }
3984
+ handleDigitInput(digit, segment) {
3985
+ const pending = this.pendingDigits() + digit;
3986
+ const value = this.internalValue() ?? { hours: 0, minutes: 0, seconds: 0 };
3987
+ let parsed = parseInt(pending, 10);
3988
+ switch (segment) {
3989
+ case 'hours': {
3990
+ const max = this.is12Hour() ? 12 : 23;
3991
+ const min = this.is12Hour() ? 1 : 0;
3992
+ if (parsed > max)
3993
+ parsed = parseInt(digit, 10);
3994
+ if (parsed < min && pending.length >= 2)
3995
+ parsed = min;
3996
+ // Convert to 24h if 12h mode
3997
+ let h24 = parsed;
3998
+ if (this.is12Hour()) {
3999
+ const isPM = this.period() === 'PM';
4000
+ h24 = parsed === 12 ? 0 : parsed;
4001
+ if (isPM)
4002
+ h24 += 12;
4003
+ }
4004
+ this.updateValue({ ...value, hours: h24 });
4005
+ break;
4006
+ }
4007
+ case 'minutes': {
4008
+ if (parsed > 59)
4009
+ parsed = parseInt(digit, 10);
4010
+ this.updateValue({ ...value, minutes: parsed });
4011
+ break;
4012
+ }
4013
+ case 'seconds': {
4014
+ if (parsed > 59)
4015
+ parsed = parseInt(digit, 10);
4016
+ this.updateValue({ ...value, seconds: parsed });
4017
+ break;
4018
+ }
4019
+ }
4020
+ // Auto-advance after 2 digits
4021
+ if (pending.length >= 2) {
4022
+ this.pendingDigits.set('');
4023
+ this.focusNextSegment(segment);
4024
+ }
4025
+ else {
4026
+ this.pendingDigits.set(pending);
4027
+ }
4028
+ }
4029
+ snapToStep(segment) {
4030
+ const value = this.internalValue();
4031
+ if (!value)
4032
+ return;
4033
+ if (segment === 'minutes' && this.minuteStep() > 1) {
4034
+ const step = this.minuteStep();
4035
+ const snapped = Math.round(value.minutes / step) * step;
4036
+ const clamped = Math.min(snapped, 59);
4037
+ if (clamped !== value.minutes) {
4038
+ this.updateValue({ ...value, minutes: clamped });
4039
+ }
4040
+ }
4041
+ if (segment === 'seconds' && this.secondStep() > 1) {
4042
+ const step = this.secondStep();
4043
+ const snapped = Math.round(value.seconds / step) * step;
4044
+ const clamped = Math.min(snapped, 59);
4045
+ if (clamped !== value.seconds) {
4046
+ this.updateValue({ ...value, seconds: clamped });
4047
+ }
4048
+ }
4049
+ }
4050
+ setSegmentToMin(segment) {
4051
+ const value = this.internalValue() ?? { hours: 0, minutes: 0, seconds: 0 };
4052
+ switch (segment) {
4053
+ case 'hours': {
4054
+ if (this.is12Hour()) {
4055
+ // Min display is 1; convert to 24h
4056
+ const isPM = this.period() === 'PM';
4057
+ const h24 = isPM ? 13 : 1;
4058
+ this.updateValue({ ...value, hours: h24 });
4059
+ }
4060
+ else {
4061
+ this.updateValue({ ...value, hours: 0 });
4062
+ }
4063
+ break;
4064
+ }
4065
+ case 'minutes':
4066
+ this.updateValue({ ...value, minutes: 0 });
4067
+ break;
4068
+ case 'seconds':
4069
+ this.updateValue({ ...value, seconds: 0 });
4070
+ break;
4071
+ }
4072
+ }
4073
+ setSegmentToMax(segment) {
4074
+ const value = this.internalValue() ?? { hours: 0, minutes: 0, seconds: 0 };
4075
+ switch (segment) {
4076
+ case 'hours': {
4077
+ if (this.is12Hour()) {
4078
+ // Max display is 12; 12 in 12h = 0 in 24h (for AM) or 12 (for PM)
4079
+ const isPM = this.period() === 'PM';
4080
+ const h24 = isPM ? 12 : 0;
4081
+ this.updateValue({ ...value, hours: h24 });
4082
+ }
4083
+ else {
4084
+ this.updateValue({ ...value, hours: 23 });
4085
+ }
4086
+ break;
4087
+ }
4088
+ case 'minutes':
4089
+ this.updateValue({ ...value, minutes: 59 });
4090
+ break;
4091
+ case 'seconds':
4092
+ this.updateValue({ ...value, seconds: 59 });
4093
+ break;
4094
+ }
4095
+ }
4096
+ focusNextSegment(current) {
4097
+ switch (current) {
4098
+ case 'hours':
4099
+ this.minutesInputRef()?.nativeElement.focus();
4100
+ break;
4101
+ case 'minutes':
4102
+ if (this.showSeconds()) {
4103
+ this.secondsInputRef()?.nativeElement.focus();
4104
+ }
4105
+ else if (this.is12Hour()) {
4106
+ this.periodButtonRef()?.nativeElement.focus();
4107
+ }
4108
+ break;
4109
+ case 'seconds':
4110
+ if (this.is12Hour()) {
4111
+ this.periodButtonRef()?.nativeElement.focus();
4112
+ }
4113
+ break;
4114
+ }
4115
+ }
4116
+ focusPrevSegment(current) {
4117
+ switch (current) {
4118
+ case 'minutes':
4119
+ this.hoursInputRef()?.nativeElement.focus();
4120
+ break;
4121
+ case 'seconds':
4122
+ this.minutesInputRef()?.nativeElement.focus();
4123
+ break;
4124
+ case 'period':
4125
+ if (this.showSeconds()) {
4126
+ this.secondsInputRef()?.nativeElement.focus();
4127
+ }
4128
+ else {
4129
+ this.minutesInputRef()?.nativeElement.focus();
4130
+ }
4131
+ break;
4132
+ }
4133
+ }
4134
+ updateValue(value) {
4135
+ this.internalValue.set(value);
4136
+ this.onChange(value);
4137
+ this.timeChange.emit(value);
4138
+ this.onValidatorChange();
4139
+ if (value) {
4140
+ const h = this.is12Hour()
4141
+ ? `${(value.hours % 12 || 12)}:${value.minutes.toString().padStart(2, '0')}${this.showSeconds() ? ':' + value.seconds.toString().padStart(2, '0') : ''} ${value.hours >= 12 ? 'PM' : 'AM'}`
4142
+ : `${value.hours.toString().padStart(2, '0')}:${value.minutes.toString().padStart(2, '0')}${this.showSeconds() ? ':' + value.seconds.toString().padStart(2, '0') : ''}`;
4143
+ this.liveAnnouncement.set(`Time set to ${h}`);
4144
+ }
4145
+ }
4146
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComTimePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
4147
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComTimePicker, isStandalone: true, selector: "com-time-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, use12HourFormat: { classPropertyName: "use12HourFormat", publicName: "use12HourFormat", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, secondStep: { classPropertyName: "secondStep", publicName: "secondStep", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeChange: "timeChange" }, host: { properties: { "class.com-time-picker-disabled": "disabled()", "attr.role": "\"group\"", "attr.aria-label": "ariaLabel() || \"Time picker\"", "attr.aria-disabled": "disabled() || null" }, classAttribute: "com-time-picker-host inline-block" }, viewQueries: [{ propertyName: "hoursInputRef", first: true, predicate: ["hoursInput"], descendants: true, isSignal: true }, { propertyName: "minutesInputRef", first: true, predicate: ["minutesInput"], descendants: true, isSignal: true }, { propertyName: "secondsInputRef", first: true, predicate: ["secondsInput"], descendants: true, isSignal: true }, { propertyName: "periodButtonRef", first: true, predicate: ["periodButton"], descendants: true, isSignal: true }], exportAs: ["comTimePicker"], ngImport: i0, template: `
4148
+ <div [class]="containerClasses()">
4149
+ <!-- Hours -->
4150
+ <input
4151
+ #hoursInput
4152
+ type="text"
4153
+ inputmode="numeric"
4154
+ role="spinbutton"
4155
+ [class]="segmentClasses()"
4156
+ [attr.aria-label]="'Hours'"
4157
+ [attr.aria-valuenow]="displayHours()"
4158
+ [attr.aria-valuemin]="is12Hour() ? 1 : 0"
4159
+ [attr.aria-valuemax]="is12Hour() ? 12 : 23"
4160
+ [value]="formattedHours()"
4161
+ [placeholder]="placeholder()"
4162
+ [disabled]="disabled()"
4163
+ maxlength="2"
4164
+ (keydown)="onSegmentKeydown($event, 'hours')"
4165
+ (input)="onSegmentInput($event, 'hours')"
4166
+ (focus)="onSegmentFocus('hours')"
4167
+ (blur)="onSegmentBlur('hours')"
4168
+ />
4169
+
4170
+ <span [class]="separatorClasses()" aria-hidden="true">:</span>
4171
+
4172
+ <!-- Minutes -->
4173
+ <input
4174
+ #minutesInput
4175
+ type="text"
4176
+ inputmode="numeric"
4177
+ role="spinbutton"
4178
+ [class]="segmentClasses()"
4179
+ [attr.aria-label]="'Minutes'"
4180
+ [attr.aria-valuenow]="internalValue()?.minutes ?? null"
4181
+ [attr.aria-valuemin]="0"
4182
+ [attr.aria-valuemax]="59"
4183
+ [value]="formattedMinutes()"
4184
+ [placeholder]="placeholder()"
4185
+ [disabled]="disabled()"
4186
+ maxlength="2"
4187
+ (keydown)="onSegmentKeydown($event, 'minutes')"
4188
+ (input)="onSegmentInput($event, 'minutes')"
4189
+ (focus)="onSegmentFocus('minutes')"
4190
+ (blur)="onSegmentBlur('minutes')"
4191
+ />
4192
+
4193
+ @if (showSeconds()) {
4194
+ <span [class]="separatorClasses()" aria-hidden="true">:</span>
4195
+
4196
+ <!-- Seconds -->
4197
+ <input
4198
+ #secondsInput
4199
+ type="text"
4200
+ inputmode="numeric"
4201
+ role="spinbutton"
4202
+ [class]="segmentClasses()"
4203
+ [attr.aria-label]="'Seconds'"
4204
+ [attr.aria-valuenow]="internalValue()?.seconds ?? null"
4205
+ [attr.aria-valuemin]="0"
4206
+ [attr.aria-valuemax]="59"
4207
+ [value]="formattedSeconds()"
4208
+ [placeholder]="placeholder()"
4209
+ [disabled]="disabled()"
4210
+ maxlength="2"
4211
+ (keydown)="onSegmentKeydown($event, 'seconds')"
4212
+ (input)="onSegmentInput($event, 'seconds')"
4213
+ (focus)="onSegmentFocus('seconds')"
4214
+ (blur)="onSegmentBlur('seconds')"
4215
+ />
4216
+ }
4217
+
4218
+ @if (is12Hour()) {
4219
+ <button
4220
+ #periodButton
4221
+ type="button"
4222
+ [class]="periodClasses()"
4223
+ [attr.aria-label]="'Toggle AM/PM, currently ' + period()"
4224
+ [disabled]="disabled()"
4225
+ (click)="togglePeriod()"
4226
+ (keydown)="onPeriodKeydown($event)"
4227
+ >
4228
+ {{ period() }}
4229
+ </button>
4230
+ }
4231
+ </div>
4232
+
4233
+ <div class="sr-only" aria-live="polite" aria-atomic="true">
4234
+ {{ liveAnnouncement() }}
4235
+ </div>
4236
+ `, isInline: true, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4237
+ }
4238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComTimePicker, decorators: [{
4239
+ type: Component,
4240
+ args: [{ selector: 'com-time-picker', exportAs: 'comTimePicker', template: `
4241
+ <div [class]="containerClasses()">
4242
+ <!-- Hours -->
4243
+ <input
4244
+ #hoursInput
4245
+ type="text"
4246
+ inputmode="numeric"
4247
+ role="spinbutton"
4248
+ [class]="segmentClasses()"
4249
+ [attr.aria-label]="'Hours'"
4250
+ [attr.aria-valuenow]="displayHours()"
4251
+ [attr.aria-valuemin]="is12Hour() ? 1 : 0"
4252
+ [attr.aria-valuemax]="is12Hour() ? 12 : 23"
4253
+ [value]="formattedHours()"
4254
+ [placeholder]="placeholder()"
4255
+ [disabled]="disabled()"
4256
+ maxlength="2"
4257
+ (keydown)="onSegmentKeydown($event, 'hours')"
4258
+ (input)="onSegmentInput($event, 'hours')"
4259
+ (focus)="onSegmentFocus('hours')"
4260
+ (blur)="onSegmentBlur('hours')"
4261
+ />
4262
+
4263
+ <span [class]="separatorClasses()" aria-hidden="true">:</span>
4264
+
4265
+ <!-- Minutes -->
4266
+ <input
4267
+ #minutesInput
4268
+ type="text"
4269
+ inputmode="numeric"
4270
+ role="spinbutton"
4271
+ [class]="segmentClasses()"
4272
+ [attr.aria-label]="'Minutes'"
4273
+ [attr.aria-valuenow]="internalValue()?.minutes ?? null"
4274
+ [attr.aria-valuemin]="0"
4275
+ [attr.aria-valuemax]="59"
4276
+ [value]="formattedMinutes()"
4277
+ [placeholder]="placeholder()"
4278
+ [disabled]="disabled()"
4279
+ maxlength="2"
4280
+ (keydown)="onSegmentKeydown($event, 'minutes')"
4281
+ (input)="onSegmentInput($event, 'minutes')"
4282
+ (focus)="onSegmentFocus('minutes')"
4283
+ (blur)="onSegmentBlur('minutes')"
4284
+ />
4285
+
4286
+ @if (showSeconds()) {
4287
+ <span [class]="separatorClasses()" aria-hidden="true">:</span>
4288
+
4289
+ <!-- Seconds -->
4290
+ <input
4291
+ #secondsInput
4292
+ type="text"
4293
+ inputmode="numeric"
4294
+ role="spinbutton"
4295
+ [class]="segmentClasses()"
4296
+ [attr.aria-label]="'Seconds'"
4297
+ [attr.aria-valuenow]="internalValue()?.seconds ?? null"
4298
+ [attr.aria-valuemin]="0"
4299
+ [attr.aria-valuemax]="59"
4300
+ [value]="formattedSeconds()"
4301
+ [placeholder]="placeholder()"
4302
+ [disabled]="disabled()"
4303
+ maxlength="2"
4304
+ (keydown)="onSegmentKeydown($event, 'seconds')"
4305
+ (input)="onSegmentInput($event, 'seconds')"
4306
+ (focus)="onSegmentFocus('seconds')"
4307
+ (blur)="onSegmentBlur('seconds')"
4308
+ />
4309
+ }
4310
+
4311
+ @if (is12Hour()) {
4312
+ <button
4313
+ #periodButton
4314
+ type="button"
4315
+ [class]="periodClasses()"
4316
+ [attr.aria-label]="'Toggle AM/PM, currently ' + period()"
4317
+ [disabled]="disabled()"
4318
+ (click)="togglePeriod()"
4319
+ (keydown)="onPeriodKeydown($event)"
4320
+ >
4321
+ {{ period() }}
4322
+ </button>
4323
+ }
4324
+ </div>
4325
+
4326
+ <div class="sr-only" aria-live="polite" aria-atomic="true">
4327
+ {{ liveAnnouncement() }}
4328
+ </div>
4329
+ `, changeDetection: ChangeDetectionStrategy.OnPush, host: {
4330
+ class: 'com-time-picker-host inline-block',
4331
+ '[class.com-time-picker-disabled]': 'disabled()',
4332
+ '[attr.role]': '"group"',
4333
+ '[attr.aria-label]': 'ariaLabel() || "Time picker"',
4334
+ '[attr.aria-disabled]': 'disabled() || null',
4335
+ }, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
4336
+ }], ctorParameters: () => [], propDecorators: { hoursInputRef: [{ type: i0.ViewChild, args: ['hoursInput', { isSignal: true }] }], minutesInputRef: [{ type: i0.ViewChild, args: ['minutesInput', { isSignal: true }] }], secondsInputRef: [{ type: i0.ViewChild, args: ['secondsInput', { isSignal: true }] }], periodButtonRef: [{ type: i0.ViewChild, args: ['periodButton', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], use12HourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "use12HourFormat", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], secondStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondStep", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], timeChange: [{ type: i0.Output, args: ["timeChange"] }] } });
4337
+
3374
4338
  /** Default position for the datepicker panel. */
3375
4339
  const DEFAULT_POSITIONS$1 = [
3376
4340
  // Below trigger, aligned start
@@ -3472,6 +4436,14 @@ class ComDatepicker {
3472
4436
  ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
3473
4437
  /** ID of element describing the input. */
3474
4438
  ariaDescribedBy = input(null, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : []));
4439
+ /** Whether to show the time picker below the calendar. */
4440
+ showTimePicker = input(false, ...(ngDevMode ? [{ debugName: "showTimePicker" }] : []));
4441
+ /** 12h vs 24h format for the time picker. `null` = auto-detect. */
4442
+ use12HourFormat = input(null, ...(ngDevMode ? [{ debugName: "use12HourFormat" }] : []));
4443
+ /** Whether the time picker shows seconds. */
4444
+ showSeconds = input(false, ...(ngDevMode ? [{ debugName: "showSeconds" }] : []));
4445
+ /** Step interval for minutes in the time picker. */
4446
+ minuteStep = input(1, ...(ngDevMode ? [{ debugName: "minuteStep" }] : []));
3475
4447
  // ============ OUTPUTS ============
3476
4448
  /** Emitted when a date is selected. */
3477
4449
  dateChange = output();
@@ -3509,7 +4481,7 @@ class ComDatepicker {
3509
4481
  const value = this.internalValue();
3510
4482
  if (!value)
3511
4483
  return '';
3512
- return this.dateAdapter.format(value, this.dateFormat());
4484
+ return this.dateAdapter.format(value, this.effectiveDateFormat());
3513
4485
  }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
3514
4486
  /** Computed trigger classes. */
3515
4487
  triggerClasses = computed(() => {
@@ -3551,6 +4523,28 @@ class ComDatepicker {
3551
4523
  clearButtonClasses = computed(() => {
3552
4524
  return datepickerFooterButtonVariants({ size: this.size(), variant: 'secondary' });
3553
4525
  }, ...(ngDevMode ? [{ debugName: "clearButtonClasses" }] : []));
4526
+ /** Time section divider classes. */
4527
+ timeSectionClasses = computed(() => {
4528
+ return timepickerSectionVariants({ size: this.size() });
4529
+ }, ...(ngDevMode ? [{ debugName: "timeSectionClasses" }] : []));
4530
+ /** Time value derived from the current date value. */
4531
+ timeValue = computed(() => {
4532
+ const date = this.internalValue();
4533
+ if (!date)
4534
+ return null;
4535
+ return createTimeValue(this.dateAdapter.getHours(date), this.dateAdapter.getMinutes(date), this.dateAdapter.getSeconds(date));
4536
+ }, ...(ngDevMode ? [{ debugName: "timeValue" }] : []));
4537
+ /** Effective display format — switches to dateTime when time picker is shown. */
4538
+ effectiveDateFormat = computed(() => {
4539
+ if (this.showTimePicker()) {
4540
+ return this.showSeconds() ? 'dateTimeLong' : 'dateTimeMedium';
4541
+ }
4542
+ return this.dateFormat();
4543
+ }, ...(ngDevMode ? [{ debugName: "effectiveDateFormat" }] : []));
4544
+ /** Whether the panel should stay open (keepOpen or time picker shown). */
4545
+ effectiveKeepOpen = computed(() => {
4546
+ return this.keepOpen() || this.showTimePicker();
4547
+ }, ...(ngDevMode ? [{ debugName: "effectiveKeepOpen" }] : []));
3554
4548
  // ============ CVA CALLBACKS ============
3555
4549
  onChange = () => { };
3556
4550
  onTouched = () => { };
@@ -3663,7 +4657,7 @@ class ComDatepicker {
3663
4657
  selectToday() {
3664
4658
  const today = this.dateAdapter.today();
3665
4659
  this.updateValue(today);
3666
- if (!this.keepOpen()) {
4660
+ if (!this.effectiveKeepOpen()) {
3667
4661
  this.close();
3668
4662
  }
3669
4663
  }
@@ -3737,12 +4731,32 @@ class ComDatepicker {
3737
4731
  }
3738
4732
  }
3739
4733
  onDateSelected(date) {
3740
- this.updateValue(date);
3741
- if (!this.keepOpen()) {
4734
+ // Preserve time when selecting a new date if time picker is shown
4735
+ if (this.showTimePicker()) {
4736
+ const currentValue = this.internalValue();
4737
+ if (currentValue) {
4738
+ const withTime = this.dateAdapter.setTime(date, this.dateAdapter.getHours(currentValue), this.dateAdapter.getMinutes(currentValue), this.dateAdapter.getSeconds(currentValue));
4739
+ this.updateValue(withTime);
4740
+ }
4741
+ else {
4742
+ this.updateValue(date);
4743
+ }
4744
+ }
4745
+ else {
4746
+ this.updateValue(date);
4747
+ }
4748
+ if (!this.effectiveKeepOpen()) {
3742
4749
  this.close();
3743
4750
  }
3744
4751
  this.announce(`Selected ${this.dateAdapter.format(date, 'long')}`);
3745
4752
  }
4753
+ onTimeChange(time) {
4754
+ if (!time)
4755
+ return;
4756
+ const current = this.internalValue() ?? this.dateAdapter.today();
4757
+ const updated = this.dateAdapter.setTime(current, time.hours, time.minutes, time.seconds);
4758
+ this.updateValue(updated);
4759
+ }
3746
4760
  onActiveDateChange(date) {
3747
4761
  this.calendarActiveDate.set(date);
3748
4762
  }
@@ -3798,7 +4812,7 @@ class ComDatepicker {
3798
4812
  }
3799
4813
  return;
3800
4814
  }
3801
- const parsed = this.dateAdapter.parse(inputValue, this.dateFormat());
4815
+ const parsed = this.dateAdapter.parse(inputValue, this.effectiveDateFormat());
3802
4816
  if (parsed && this.dateAdapter.isValid(parsed)) {
3803
4817
  // Validate against min/max/filter
3804
4818
  if (this.isDateValid(parsed)) {
@@ -3833,7 +4847,7 @@ class ComDatepicker {
3833
4847
  this.liveAnnouncement.set(message);
3834
4848
  }
3835
4849
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
3836
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDatepicker, isStandalone: true, selector: "com-datepicker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, startView: { classPropertyName: "startView", publicName: "startView", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showTodayButton: { classPropertyName: "showTodayButton", publicName: "showTodayButton", isSignal: true, isRequired: false, transformFunction: null }, showFooterClearButton: { classPropertyName: "showFooterClearButton", publicName: "showFooterClearButton", isSignal: true, isRequired: false, transformFunction: null }, keepOpen: { classPropertyName: "keepOpen", publicName: "keepOpen", isSignal: true, isRequired: false, transformFunction: null }, allowManualInput: { classPropertyName: "allowManualInput", publicName: "allowManualInput", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange", opened: "opened", closed: "closed" }, host: { properties: { "class.com-datepicker-disabled": "disabled()", "class.com-datepicker-open": "isOpen()" }, classAttribute: "com-datepicker-host inline-block" }, providers: [
4850
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDatepicker, isStandalone: true, selector: "com-datepicker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, startView: { classPropertyName: "startView", publicName: "startView", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showTodayButton: { classPropertyName: "showTodayButton", publicName: "showTodayButton", isSignal: true, isRequired: false, transformFunction: null }, showFooterClearButton: { classPropertyName: "showFooterClearButton", publicName: "showFooterClearButton", isSignal: true, isRequired: false, transformFunction: null }, keepOpen: { classPropertyName: "keepOpen", publicName: "keepOpen", isSignal: true, isRequired: false, transformFunction: null }, allowManualInput: { classPropertyName: "allowManualInput", publicName: "allowManualInput", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, showTimePicker: { classPropertyName: "showTimePicker", publicName: "showTimePicker", isSignal: true, isRequired: false, transformFunction: null }, use12HourFormat: { classPropertyName: "use12HourFormat", publicName: "use12HourFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange", opened: "opened", closed: "closed" }, host: { properties: { "class.com-datepicker-disabled": "disabled()", "class.com-datepicker-open": "isOpen()" }, classAttribute: "com-datepicker-host inline-block" }, providers: [
3837
4851
  SingleSelectionStrategy,
3838
4852
  { provide: CALENDAR_SELECTION_STRATEGY, useExisting: SingleSelectionStrategy },
3839
4853
  ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerElement"], descendants: true, isSignal: true }, { propertyName: "inputRef", first: true, predicate: ["inputElement"], descendants: true, isSignal: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }], exportAs: ["comDatepicker"], ngImport: i0, template: `
@@ -3916,7 +4930,22 @@ class ComDatepicker {
3916
4930
  (activeDateChange)="onActiveDateChange($event)"
3917
4931
  />
3918
4932
 
3919
- @if (showTodayButton() || showFooterClearButton()) {
4933
+ @if (showTimePicker()) {
4934
+ <div [class]="timeSectionClasses()">
4935
+ <com-time-picker
4936
+ variant="embedded"
4937
+ [size]="size()"
4938
+ [value]="timeValue()"
4939
+ [use12HourFormat]="use12HourFormat()"
4940
+ [showSeconds]="showSeconds()"
4941
+ [minuteStep]="minuteStep()"
4942
+ [disabled]="disabled()"
4943
+ (timeChange)="onTimeChange($event)"
4944
+ />
4945
+ </div>
4946
+ }
4947
+
4948
+ @if (showTodayButton() || showFooterClearButton() || showTimePicker()) {
3920
4949
  <div [class]="footerClasses()">
3921
4950
  @if (showTodayButton()) {
3922
4951
  <button
@@ -3936,6 +4965,15 @@ class ComDatepicker {
3936
4965
  Clear
3937
4966
  </button>
3938
4967
  }
4968
+ @if (showTimePicker()) {
4969
+ <button
4970
+ type="button"
4971
+ [class]="todayButtonClasses()"
4972
+ (click)="close()"
4973
+ >
4974
+ Done
4975
+ </button>
4976
+ }
3939
4977
  </div>
3940
4978
  }
3941
4979
  </div>
@@ -3945,7 +4983,7 @@ class ComDatepicker {
3945
4983
  <div class="sr-only" aria-live="polite" aria-atomic="true">
3946
4984
  {{ liveAnnouncement() }}
3947
4985
  </div>
3948
- `, isInline: true, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ComCalendar, selector: "com-calendar", inputs: ["activeDate", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "bordered", "startView", "firstDayOfWeek", "monthColumns", "cellTemplate"], outputs: ["selectedChange", "viewChanged", "activeDateChange"] }, { kind: "component", type: ComIcon, selector: "com-icon", inputs: ["name", "img", "color", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4986
+ `, isInline: true, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ComCalendar, selector: "com-calendar", inputs: ["activeDate", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "bordered", "startView", "firstDayOfWeek", "monthColumns", "cellTemplate"], outputs: ["selectedChange", "viewChanged", "activeDateChange"] }, { kind: "component", type: ComIcon, selector: "com-icon", inputs: ["name", "img", "color", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "component", type: ComTimePicker, selector: "com-time-picker", inputs: ["value", "disabled", "required", "showSeconds", "use12HourFormat", "minuteStep", "secondStep", "minTime", "maxTime", "variant", "size", "state", "ariaLabel", "class", "placeholder"], outputs: ["timeChange"], exportAs: ["comTimePicker"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3949
4987
  }
3950
4988
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDatepicker, decorators: [{
3951
4989
  type: Component,
@@ -4029,7 +5067,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4029
5067
  (activeDateChange)="onActiveDateChange($event)"
4030
5068
  />
4031
5069
 
4032
- @if (showTodayButton() || showFooterClearButton()) {
5070
+ @if (showTimePicker()) {
5071
+ <div [class]="timeSectionClasses()">
5072
+ <com-time-picker
5073
+ variant="embedded"
5074
+ [size]="size()"
5075
+ [value]="timeValue()"
5076
+ [use12HourFormat]="use12HourFormat()"
5077
+ [showSeconds]="showSeconds()"
5078
+ [minuteStep]="minuteStep()"
5079
+ [disabled]="disabled()"
5080
+ (timeChange)="onTimeChange($event)"
5081
+ />
5082
+ </div>
5083
+ }
5084
+
5085
+ @if (showTodayButton() || showFooterClearButton() || showTimePicker()) {
4033
5086
  <div [class]="footerClasses()">
4034
5087
  @if (showTodayButton()) {
4035
5088
  <button
@@ -4049,6 +5102,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4049
5102
  Clear
4050
5103
  </button>
4051
5104
  }
5105
+ @if (showTimePicker()) {
5106
+ <button
5107
+ type="button"
5108
+ [class]="todayButtonClasses()"
5109
+ (click)="close()"
5110
+ >
5111
+ Done
5112
+ </button>
5113
+ }
4052
5114
  </div>
4053
5115
  }
4054
5116
  </div>
@@ -4063,6 +5125,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4063
5125
  A11yModule,
4064
5126
  ComCalendar,
4065
5127
  ComIcon,
5128
+ ComTimePicker,
4066
5129
  ], providers: [
4067
5130
  SingleSelectionStrategy,
4068
5131
  { provide: CALENDAR_SELECTION_STRATEGY, useExisting: SingleSelectionStrategy },
@@ -4071,7 +5134,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4071
5134
  '[class.com-datepicker-disabled]': 'disabled()',
4072
5135
  '[class.com-datepicker-open]': 'isOpen()',
4073
5136
  }, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
4074
- }], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['triggerElement', { isSignal: true }] }], inputRef: [{ type: i0.ViewChild, args: ['inputElement', { isSignal: true }] }], panelTemplateRef: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], startView: [{ type: i0.Input, args: [{ isSignal: true, alias: "startView", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showTodayButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTodayButton", required: false }] }], showFooterClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooterClearButton", required: false }] }], keepOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepOpen", required: false }] }], allowManualInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowManualInput", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
5137
+ }], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['triggerElement', { isSignal: true }] }], inputRef: [{ type: i0.ViewChild, args: ['inputElement', { isSignal: true }] }], panelTemplateRef: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], startView: [{ type: i0.Input, args: [{ isSignal: true, alias: "startView", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showTodayButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTodayButton", required: false }] }], showFooterClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooterClearButton", required: false }] }], keepOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepOpen", required: false }] }], allowManualInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowManualInput", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], showTimePicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTimePicker", required: false }] }], use12HourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "use12HourFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
4075
5138
 
4076
5139
  /** Default position for the datepicker panel. */
4077
5140
  const DEFAULT_POSITIONS = [
@@ -4179,6 +5242,14 @@ class ComDateRangePicker {
4179
5242
  startAriaLabel = input(null, ...(ngDevMode ? [{ debugName: "startAriaLabel" }] : []));
4180
5243
  /** Accessible label for the end input. */
4181
5244
  endAriaLabel = input(null, ...(ngDevMode ? [{ debugName: "endAriaLabel" }] : []));
5245
+ /** Whether to show time pickers below the calendar. */
5246
+ showTimePicker = input(false, ...(ngDevMode ? [{ debugName: "showTimePicker" }] : []));
5247
+ /** 12h vs 24h format for the time pickers. `null` = auto-detect. */
5248
+ use12HourFormat = input(null, ...(ngDevMode ? [{ debugName: "use12HourFormat" }] : []));
5249
+ /** Whether the time pickers show seconds. */
5250
+ showSeconds = input(false, ...(ngDevMode ? [{ debugName: "showSeconds" }] : []));
5251
+ /** Step interval for minutes in the time pickers. */
5252
+ minuteStep = input(1, ...(ngDevMode ? [{ debugName: "minuteStep" }] : []));
4182
5253
  // ============ OUTPUTS ============
4183
5254
  /** Emitted when a complete range is selected. */
4184
5255
  rangeChange = output();
@@ -4230,14 +5301,14 @@ class ComDateRangePicker {
4230
5301
  const value = this.internalValue();
4231
5302
  if (!value?.start)
4232
5303
  return '';
4233
- return this.dateAdapter.format(value.start, this.dateFormat());
5304
+ return this.dateAdapter.format(value.start, this.effectiveDateFormat());
4234
5305
  }, ...(ngDevMode ? [{ debugName: "startDisplayValue" }] : []));
4235
5306
  /** Formatted end display value. */
4236
5307
  endDisplayValue = computed(() => {
4237
5308
  const value = this.internalValue();
4238
5309
  if (!value?.end)
4239
5310
  return '';
4240
- return this.dateAdapter.format(value.end, this.dateFormat());
5311
+ return this.dateAdapter.format(value.end, this.effectiveDateFormat());
4241
5312
  }, ...(ngDevMode ? [{ debugName: "endDisplayValue" }] : []));
4242
5313
  /** Computed trigger classes. */
4243
5314
  triggerClasses = computed(() => {
@@ -4283,6 +5354,39 @@ class ComDateRangePicker {
4283
5354
  clearButtonClasses = computed(() => {
4284
5355
  return datepickerFooterButtonVariants({ size: this.size(), variant: 'secondary' });
4285
5356
  }, ...(ngDevMode ? [{ debugName: "clearButtonClasses" }] : []));
5357
+ /** Time section divider classes. */
5358
+ timeSectionClasses = computed(() => {
5359
+ return timepickerSectionVariants({ size: this.size() });
5360
+ }, ...(ngDevMode ? [{ debugName: "timeSectionClasses" }] : []));
5361
+ /** Time label classes. */
5362
+ timeLabelClasses = computed(() => {
5363
+ return timepickerLabelVariants({ size: this.size() });
5364
+ }, ...(ngDevMode ? [{ debugName: "timeLabelClasses" }] : []));
5365
+ /** Start time value derived from the start date. */
5366
+ startTimeValue = computed(() => {
5367
+ const value = this.internalValue();
5368
+ if (!value?.start)
5369
+ return null;
5370
+ return createTimeValue(this.dateAdapter.getHours(value.start), this.dateAdapter.getMinutes(value.start), this.dateAdapter.getSeconds(value.start));
5371
+ }, ...(ngDevMode ? [{ debugName: "startTimeValue" }] : []));
5372
+ /** End time value derived from the end date. */
5373
+ endTimeValue = computed(() => {
5374
+ const value = this.internalValue();
5375
+ if (!value?.end)
5376
+ return null;
5377
+ return createTimeValue(this.dateAdapter.getHours(value.end), this.dateAdapter.getMinutes(value.end), this.dateAdapter.getSeconds(value.end));
5378
+ }, ...(ngDevMode ? [{ debugName: "endTimeValue" }] : []));
5379
+ /** Effective display format — switches to dateTime when time picker is shown. */
5380
+ effectiveDateFormat = computed(() => {
5381
+ if (this.showTimePicker()) {
5382
+ return this.showSeconds() ? 'dateTimeLong' : 'dateTimeMedium';
5383
+ }
5384
+ return this.dateFormat();
5385
+ }, ...(ngDevMode ? [{ debugName: "effectiveDateFormat" }] : []));
5386
+ /** Whether the panel should stay open (keepOpen or time picker shown). */
5387
+ effectiveKeepOpen = computed(() => {
5388
+ return this.keepOpen() || this.showTimePicker();
5389
+ }, ...(ngDevMode ? [{ debugName: "effectiveKeepOpen" }] : []));
4286
5390
  // ============ CVA CALLBACKS ============
4287
5391
  onChange = () => { };
4288
5392
  onTouched = () => { };
@@ -4420,7 +5524,7 @@ class ComDateRangePicker {
4420
5524
  ? createDateRangeValue(today, currentValue.start)
4421
5525
  : createDateRangeValue(currentValue.start, today);
4422
5526
  this.updateValue(newRange);
4423
- if (!this.keepOpen()) {
5527
+ if (!this.effectiveKeepOpen()) {
4424
5528
  this.close();
4425
5529
  }
4426
5530
  }
@@ -4516,7 +5620,7 @@ class ComDateRangePicker {
4516
5620
  if (range.start && range.end) {
4517
5621
  // Complete range selected
4518
5622
  this.announce(`Range selected: ${this.formatDate(range.start)} to ${this.formatDate(range.end)}`);
4519
- if (!this.keepOpen()) {
5623
+ if (!this.effectiveKeepOpen()) {
4520
5624
  this.close();
4521
5625
  }
4522
5626
  }
@@ -4528,6 +5632,22 @@ class ComDateRangePicker {
4528
5632
  onActiveDateChange(date) {
4529
5633
  this.calendarActiveDate.set(date);
4530
5634
  }
5635
+ onStartTimeChange(time) {
5636
+ if (!time)
5637
+ return;
5638
+ const value = this.internalValue();
5639
+ const startDate = value?.start ?? this.dateAdapter.today();
5640
+ const updated = this.dateAdapter.setTime(startDate, time.hours, time.minutes, time.seconds);
5641
+ this.updateValue(createDateRangeValue(updated, value?.end ?? null));
5642
+ }
5643
+ onEndTimeChange(time) {
5644
+ if (!time)
5645
+ return;
5646
+ const value = this.internalValue();
5647
+ const endDate = value?.end ?? this.dateAdapter.today();
5648
+ const updated = this.dateAdapter.setTime(endDate, time.hours, time.minutes, time.seconds);
5649
+ this.updateValue(createDateRangeValue(value?.start ?? null, updated));
5650
+ }
4531
5651
  // ============ PRIVATE METHODS ============
4532
5652
  createOverlay() {
4533
5653
  if (this.overlayRef) {
@@ -4581,7 +5701,7 @@ class ComDateRangePicker {
4581
5701
  }
4582
5702
  return;
4583
5703
  }
4584
- const parsed = this.dateAdapter.parse(inputValue, this.dateFormat());
5704
+ const parsed = this.dateAdapter.parse(inputValue, this.effectiveDateFormat());
4585
5705
  if (parsed && this.dateAdapter.isValid(parsed) && this.isDateValid(parsed)) {
4586
5706
  // Ensure start <= end
4587
5707
  if (currentValue?.end && this.dateAdapter.compareDate(parsed, currentValue.end) > 0) {
@@ -4606,7 +5726,7 @@ class ComDateRangePicker {
4606
5726
  }
4607
5727
  return;
4608
5728
  }
4609
- const parsed = this.dateAdapter.parse(inputValue, this.dateFormat());
5729
+ const parsed = this.dateAdapter.parse(inputValue, this.effectiveDateFormat());
4610
5730
  if (parsed && this.dateAdapter.isValid(parsed) && this.isDateValid(parsed)) {
4611
5731
  // Ensure start <= end
4612
5732
  if (currentValue?.start && this.dateAdapter.compareDate(parsed, currentValue.start) < 0) {
@@ -4644,7 +5764,7 @@ class ComDateRangePicker {
4644
5764
  this.liveAnnouncement.set(message);
4645
5765
  }
4646
5766
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDateRangePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
4647
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDateRangePicker, isStandalone: true, selector: "com-date-range-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, startView: { classPropertyName: "startView", publicName: "startView", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, startPlaceholder: { classPropertyName: "startPlaceholder", publicName: "startPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, endPlaceholder: { classPropertyName: "endPlaceholder", publicName: "endPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showTodayButton: { classPropertyName: "showTodayButton", publicName: "showTodayButton", isSignal: true, isRequired: false, transformFunction: null }, showFooterClearButton: { classPropertyName: "showFooterClearButton", publicName: "showFooterClearButton", isSignal: true, isRequired: false, transformFunction: null }, keepOpen: { classPropertyName: "keepOpen", publicName: "keepOpen", isSignal: true, isRequired: false, transformFunction: null }, allowManualInput: { classPropertyName: "allowManualInput", publicName: "allowManualInput", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, startAriaLabel: { classPropertyName: "startAriaLabel", publicName: "startAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, endAriaLabel: { classPropertyName: "endAriaLabel", publicName: "endAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange", opened: "opened", closed: "closed" }, host: { properties: { "class.com-date-range-picker-disabled": "disabled()", "class.com-date-range-picker-open": "isOpen()" }, classAttribute: "com-date-range-picker-host inline-block" }, providers: [
5767
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDateRangePicker, isStandalone: true, selector: "com-date-range-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: true, isRequired: false, transformFunction: null }, startView: { classPropertyName: "startView", publicName: "startView", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, startPlaceholder: { classPropertyName: "startPlaceholder", publicName: "startPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, endPlaceholder: { classPropertyName: "endPlaceholder", publicName: "endPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, showTodayButton: { classPropertyName: "showTodayButton", publicName: "showTodayButton", isSignal: true, isRequired: false, transformFunction: null }, showFooterClearButton: { classPropertyName: "showFooterClearButton", publicName: "showFooterClearButton", isSignal: true, isRequired: false, transformFunction: null }, keepOpen: { classPropertyName: "keepOpen", publicName: "keepOpen", isSignal: true, isRequired: false, transformFunction: null }, allowManualInput: { classPropertyName: "allowManualInput", publicName: "allowManualInput", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, startAriaLabel: { classPropertyName: "startAriaLabel", publicName: "startAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, endAriaLabel: { classPropertyName: "endAriaLabel", publicName: "endAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, showTimePicker: { classPropertyName: "showTimePicker", publicName: "showTimePicker", isSignal: true, isRequired: false, transformFunction: null }, use12HourFormat: { classPropertyName: "use12HourFormat", publicName: "use12HourFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange", opened: "opened", closed: "closed" }, host: { properties: { "class.com-date-range-picker-disabled": "disabled()", "class.com-date-range-picker-open": "isOpen()" }, classAttribute: "com-date-range-picker-host inline-block" }, providers: [
4648
5768
  RangeSelectionStrategy,
4649
5769
  { provide: CALENDAR_SELECTION_STRATEGY, useExisting: RangeSelectionStrategy },
4650
5770
  ], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerElement"], descendants: true, isSignal: true }, { propertyName: "startInputRef", first: true, predicate: ["startInputElement"], descendants: true, isSignal: true }, { propertyName: "endInputRef", first: true, predicate: ["endInputElement"], descendants: true, isSignal: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }], exportAs: ["comDateRangePicker"], ngImport: i0, template: `
@@ -4751,7 +5871,45 @@ class ComDateRangePicker {
4751
5871
  (activeDateChange)="onActiveDateChange($event)"
4752
5872
  />
4753
5873
 
4754
- @if (showTodayButton() || showFooterClearButton()) {
5874
+ @if (showTimePicker()) {
5875
+ <div [class]="timeSectionClasses()">
5876
+ <div class="flex items-center gap-3">
5877
+ <div class="flex flex-col gap-1">
5878
+ <span [class]="timeLabelClasses()">Start time</span>
5879
+ <com-time-picker
5880
+ variant="embedded"
5881
+ [size]="size()"
5882
+ [value]="startTimeValue()"
5883
+ [use12HourFormat]="use12HourFormat()"
5884
+ [showSeconds]="showSeconds()"
5885
+ [minuteStep]="minuteStep()"
5886
+ [disabled]="disabled()"
5887
+ ariaLabel="Start time"
5888
+ (timeChange)="onStartTimeChange($event)"
5889
+ />
5890
+ </div>
5891
+ <span class="text-muted-foreground mt-5">
5892
+ <com-icon name="arrow-right" [size]="iconSize()" />
5893
+ </span>
5894
+ <div class="flex flex-col gap-1">
5895
+ <span [class]="timeLabelClasses()">End time</span>
5896
+ <com-time-picker
5897
+ variant="embedded"
5898
+ [size]="size()"
5899
+ [value]="endTimeValue()"
5900
+ [use12HourFormat]="use12HourFormat()"
5901
+ [showSeconds]="showSeconds()"
5902
+ [minuteStep]="minuteStep()"
5903
+ [disabled]="disabled()"
5904
+ ariaLabel="End time"
5905
+ (timeChange)="onEndTimeChange($event)"
5906
+ />
5907
+ </div>
5908
+ </div>
5909
+ </div>
5910
+ }
5911
+
5912
+ @if (showTodayButton() || showFooterClearButton() || showTimePicker()) {
4755
5913
  <div [class]="footerClasses()">
4756
5914
  @if (showTodayButton()) {
4757
5915
  <button
@@ -4771,6 +5929,15 @@ class ComDateRangePicker {
4771
5929
  Clear
4772
5930
  </button>
4773
5931
  }
5932
+ @if (showTimePicker()) {
5933
+ <button
5934
+ type="button"
5935
+ [class]="todayButtonClasses()"
5936
+ (click)="close()"
5937
+ >
5938
+ Done
5939
+ </button>
5940
+ }
4774
5941
  </div>
4775
5942
  }
4776
5943
  </div>
@@ -4780,7 +5947,7 @@ class ComDateRangePicker {
4780
5947
  <div class="sr-only" aria-live="polite" aria-atomic="true">
4781
5948
  {{ liveAnnouncement() }}
4782
5949
  </div>
4783
- `, isInline: true, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ComCalendar, selector: "com-calendar", inputs: ["activeDate", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "bordered", "startView", "firstDayOfWeek", "monthColumns", "cellTemplate"], outputs: ["selectedChange", "viewChanged", "activeDateChange"] }, { kind: "component", type: ComIcon, selector: "com-icon", inputs: ["name", "img", "color", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5950
+ `, isInline: true, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ComCalendar, selector: "com-calendar", inputs: ["activeDate", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "bordered", "startView", "firstDayOfWeek", "monthColumns", "cellTemplate"], outputs: ["selectedChange", "viewChanged", "activeDateChange"] }, { kind: "component", type: ComIcon, selector: "com-icon", inputs: ["name", "img", "color", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "component", type: ComTimePicker, selector: "com-time-picker", inputs: ["value", "disabled", "required", "showSeconds", "use12HourFormat", "minuteStep", "secondStep", "minTime", "maxTime", "variant", "size", "state", "ariaLabel", "class", "placeholder"], outputs: ["timeChange"], exportAs: ["comTimePicker"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4784
5951
  }
4785
5952
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDateRangePicker, decorators: [{
4786
5953
  type: Component,
@@ -4888,7 +6055,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4888
6055
  (activeDateChange)="onActiveDateChange($event)"
4889
6056
  />
4890
6057
 
4891
- @if (showTodayButton() || showFooterClearButton()) {
6058
+ @if (showTimePicker()) {
6059
+ <div [class]="timeSectionClasses()">
6060
+ <div class="flex items-center gap-3">
6061
+ <div class="flex flex-col gap-1">
6062
+ <span [class]="timeLabelClasses()">Start time</span>
6063
+ <com-time-picker
6064
+ variant="embedded"
6065
+ [size]="size()"
6066
+ [value]="startTimeValue()"
6067
+ [use12HourFormat]="use12HourFormat()"
6068
+ [showSeconds]="showSeconds()"
6069
+ [minuteStep]="minuteStep()"
6070
+ [disabled]="disabled()"
6071
+ ariaLabel="Start time"
6072
+ (timeChange)="onStartTimeChange($event)"
6073
+ />
6074
+ </div>
6075
+ <span class="text-muted-foreground mt-5">
6076
+ <com-icon name="arrow-right" [size]="iconSize()" />
6077
+ </span>
6078
+ <div class="flex flex-col gap-1">
6079
+ <span [class]="timeLabelClasses()">End time</span>
6080
+ <com-time-picker
6081
+ variant="embedded"
6082
+ [size]="size()"
6083
+ [value]="endTimeValue()"
6084
+ [use12HourFormat]="use12HourFormat()"
6085
+ [showSeconds]="showSeconds()"
6086
+ [minuteStep]="minuteStep()"
6087
+ [disabled]="disabled()"
6088
+ ariaLabel="End time"
6089
+ (timeChange)="onEndTimeChange($event)"
6090
+ />
6091
+ </div>
6092
+ </div>
6093
+ </div>
6094
+ }
6095
+
6096
+ @if (showTodayButton() || showFooterClearButton() || showTimePicker()) {
4892
6097
  <div [class]="footerClasses()">
4893
6098
  @if (showTodayButton()) {
4894
6099
  <button
@@ -4908,6 +6113,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4908
6113
  Clear
4909
6114
  </button>
4910
6115
  }
6116
+ @if (showTimePicker()) {
6117
+ <button
6118
+ type="button"
6119
+ [class]="todayButtonClasses()"
6120
+ (click)="close()"
6121
+ >
6122
+ Done
6123
+ </button>
6124
+ }
4911
6125
  </div>
4912
6126
  }
4913
6127
  </div>
@@ -4922,6 +6136,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4922
6136
  A11yModule,
4923
6137
  ComCalendar,
4924
6138
  ComIcon,
6139
+ ComTimePicker,
4925
6140
  ], providers: [
4926
6141
  RangeSelectionStrategy,
4927
6142
  { provide: CALENDAR_SELECTION_STRATEGY, useExisting: RangeSelectionStrategy },
@@ -4930,12 +6145,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4930
6145
  '[class.com-date-range-picker-disabled]': 'disabled()',
4931
6146
  '[class.com-date-range-picker-open]': 'isOpen()',
4932
6147
  }, styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
4933
- }], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['triggerElement', { isSignal: true }] }], startInputRef: [{ type: i0.ViewChild, args: ['startInputElement', { isSignal: true }] }], endInputRef: [{ type: i0.ViewChild, args: ['endInputElement', { isSignal: true }] }], panelTemplateRef: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], startView: [{ type: i0.Input, args: [{ isSignal: true, alias: "startView", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], startPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "startPlaceholder", required: false }] }], endPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPlaceholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showTodayButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTodayButton", required: false }] }], showFooterClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooterClearButton", required: false }] }], keepOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepOpen", required: false }] }], allowManualInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowManualInput", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], startAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAriaLabel", required: false }] }], endAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "endAriaLabel", required: false }] }], rangeChange: [{ type: i0.Output, args: ["rangeChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
6148
+ }], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['triggerElement', { isSignal: true }] }], startInputRef: [{ type: i0.ViewChild, args: ['startInputElement', { isSignal: true }] }], endInputRef: [{ type: i0.ViewChild, args: ['endInputElement', { isSignal: true }] }], panelTemplateRef: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], startAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAt", required: false }] }], startView: [{ type: i0.Input, args: [{ isSignal: true, alias: "startView", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], startPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "startPlaceholder", required: false }] }], endPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPlaceholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], showTodayButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTodayButton", required: false }] }], showFooterClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooterClearButton", required: false }] }], keepOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepOpen", required: false }] }], allowManualInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowManualInput", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], startAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAriaLabel", required: false }] }], endAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "endAriaLabel", required: false }] }], showTimePicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTimePicker", required: false }] }], use12HourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "use12HourFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], rangeChange: [{ type: i0.Output, args: ["rangeChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
4934
6149
 
4935
6150
  /**
4936
6151
  * Datepicker components public API.
4937
6152
  */
4938
6153
 
6154
+ /**
6155
+ * TimePicker component public API.
6156
+ */
6157
+
4939
6158
  /**
4940
6159
  * ngx-com/components/calendar
4941
6160
  * Calendar component public API
@@ -4945,5 +6164,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
4945
6164
  * Generated bundle index. Do not edit.
4946
6165
  */
4947
6166
 
4948
- export { CALENDAR_SELECTION_STRATEGY, CalendarSelectionStrategy, CalendarViewBase, ComCalendar, ComCalendarCell, ComCalendarHeader, ComCalendarMonthView, ComCalendarMultiYearView, ComCalendarYearView, ComDateRangePicker, ComDatepicker, DATE_ADAPTER, DAYS_PER_WEEK, DateAdapter, MONTHS_PER_ROW, MultiSelectionStrategy, NativeDateAdapter, RangeSelectionStrategy, SingleSelectionStrategy, WEEKS_PER_MONTH, WeekSelectionStrategy, YEARS_PER_PAGE, YEARS_PER_ROW, calendarCellVariants, calendarCellWrapperVariants, calendarHeaderButtonVariants, calendarHeaderVariants, calendarVariants, createCalendarCell, createDateRange, createDateRangeValue, createGrid, datepickerClearVariants, datepickerDisabledVariants, datepickerFooterButtonVariants, datepickerFooterVariants, datepickerIconVariants, datepickerInputVariants, datepickerPanelVariants, datepickerRangeSeparatorVariants, datepickerTriggerVariants, generateDatepickerId, getMultiYearStartingYear, getWeekdayHeaders, isDateDisabled, isMonthDisabled, isYearDisabled, navigateGrid, provideMultiSelectionStrategy, provideNativeDateAdapter, provideRangeSelectionStrategy, provideSingleSelectionStrategy, provideWeekSelectionStrategy };
6167
+ export { CALENDAR_SELECTION_STRATEGY, CalendarSelectionStrategy, CalendarViewBase, ComCalendar, ComCalendarCell, ComCalendarHeader, ComCalendarMonthView, ComCalendarMultiYearView, ComCalendarYearView, ComDateRangePicker, ComDatepicker, ComTimePicker, DATE_ADAPTER, DAYS_PER_WEEK, DateAdapter, MONTHS_PER_ROW, MultiSelectionStrategy, NativeDateAdapter, RangeSelectionStrategy, SingleSelectionStrategy, WEEKS_PER_MONTH, WeekSelectionStrategy, YEARS_PER_PAGE, YEARS_PER_ROW, calendarCellVariants, calendarCellWrapperVariants, calendarHeaderButtonVariants, calendarHeaderVariants, calendarVariants, compareTime, createCalendarCell, createDateRange, createDateRangeValue, createGrid, createTimeValue, datepickerClearVariants, datepickerDisabledVariants, datepickerFooterButtonVariants, datepickerFooterVariants, datepickerIconVariants, datepickerInputVariants, datepickerPanelVariants, datepickerRangeSeparatorVariants, datepickerTriggerVariants, generateDatepickerId, generateTimePickerId, getMultiYearStartingYear, getWeekdayHeaders, isDateDisabled, isMonthDisabled, isYearDisabled, navigateGrid, provideMultiSelectionStrategy, provideNativeDateAdapter, provideRangeSelectionStrategy, provideSingleSelectionStrategy, provideWeekSelectionStrategy, timepickerContainerVariants, timepickerDisabledVariants, timepickerLabelVariants, timepickerPeriodVariants, timepickerSectionVariants, timepickerSegmentVariants, timepickerSeparatorVariants };
4949
6168
  //# sourceMappingURL=ngx-com-components-calendar.mjs.map