pdm-ui-kit 0.1.20 → 0.1.22

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.
@@ -4,6 +4,7 @@ import * as i0 from '@angular/core';
4
4
  import { EventEmitter, Component, ChangeDetectionStrategy, Input, Output, HostListener, ViewChildren, ViewChild, NgModule } from '@angular/core';
5
5
  import { icons } from 'lucide';
6
6
  import * as i1$1 from '@angular/platform-browser';
7
+ import { format } from 'date-fns';
7
8
 
8
9
  class PdmAccordionComponent {
9
10
  constructor() {
@@ -390,23 +391,40 @@ class PdmButtonComponent {
390
391
  get isDisabled() {
391
392
  return this.disabled || this.loading || this.variant === 'loading';
392
393
  }
394
+ get resolvedVariant() {
395
+ return this.isValidVariant(this.variant) ? this.variant : 'default';
396
+ }
397
+ get resolvedState() {
398
+ return this.state === 'hover' ? 'hover' : 'default';
399
+ }
400
+ get resolvedSize() {
401
+ if (this.size === 'small' || this.size === 'large') {
402
+ return this.size;
403
+ }
404
+ return 'default';
405
+ }
406
+ get showsIconSlot() {
407
+ const variant = this.resolvedVariant;
408
+ return variant === 'with-icon' || variant === 'icon' || variant === 'icon-circle' || variant === 'rounded';
409
+ }
393
410
  get rootClasses() {
394
- const currentState = this.state === 'hover' ? 'hover' : 'default';
395
- const toneClass = this.toneClassMap[this.variant][currentState];
411
+ const currentState = this.resolvedState;
412
+ const variant = this.resolvedVariant;
413
+ const toneClass = this.toneClassMap[variant][currentState];
396
414
  return [
397
415
  'inline-flex items-center justify-center gap-2 rounded-md border text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-clip-padding',
398
- this.variant === 'link' ? 'px-4 py-2 h-9' : '',
399
- this.variant === 'icon' ? 'h-9 w-9 p-0' : '',
400
- this.variant === 'icon-circle' ? 'h-10 w-10 rounded-full p-0' : '',
401
- this.variant === 'rounded' ? 'h-9 w-9 rounded-full p-0' : '',
402
- this.variant !== 'icon' && this.variant !== 'icon-circle' && this.variant !== 'rounded'
403
- ? this.size === 'small'
416
+ variant === 'link' ? 'px-4 py-2 h-9' : '',
417
+ variant === 'icon' ? 'h-9 w-9 p-0' : '',
418
+ variant === 'icon-circle' ? 'h-10 w-10 rounded-full p-0' : '',
419
+ variant === 'rounded' ? 'h-9 w-9 rounded-full p-0' : '',
420
+ variant !== 'icon' && variant !== 'icon-circle' && variant !== 'rounded'
421
+ ? this.resolvedSize === 'small'
404
422
  ? 'h-8 px-3 text-xs'
405
- : this.size === 'large'
423
+ : this.resolvedSize === 'large'
406
424
  ? 'h-10 px-8'
407
425
  : 'h-9 px-4'
408
426
  : '',
409
- this.variant === 'link' && this.state === 'hover' ? 'underline underline-offset-4' : '',
427
+ variant === 'link' && currentState === 'hover' ? 'underline underline-offset-4' : '',
410
428
  toneClass,
411
429
  this.className
412
430
  ];
@@ -416,12 +434,27 @@ class PdmButtonComponent {
416
434
  this.pressed.emit(event);
417
435
  }
418
436
  }
437
+ isValidVariant(value) {
438
+ return (value === 'default' ||
439
+ value === 'primary' ||
440
+ value === 'destructive' ||
441
+ value === 'outline' ||
442
+ value === 'subtle' ||
443
+ value === 'secondary' ||
444
+ value === 'ghost' ||
445
+ value === 'link' ||
446
+ value === 'with-icon' ||
447
+ value === 'icon' ||
448
+ value === 'icon-circle' ||
449
+ value === 'rounded' ||
450
+ value === 'loading');
451
+ }
419
452
  }
420
453
  PdmButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
421
- PdmButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmButtonComponent, selector: "pdm-button", inputs: { type: "type", variant: "variant", state: "state", size: "size", disabled: "disabled", loading: "loading", className: "className" }, outputs: { pressed: "pressed" }, ngImport: i0, template: "<button\n [type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading\"\n [ngClass]=\"rootClasses\"\n (click)=\"onClick($event)\"\n>\n <span\n *ngIf=\"loading\"\n class=\"inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-r-transparent\"\n aria-hidden=\"true\"\n ></span>\n <ng-content select=\"[pdmButtonIcon]\" *ngIf=\"variant === 'with-icon' || variant === 'icon' || variant === 'icon-circle' || variant === 'rounded'\"></ng-content>\n <ng-content></ng-content>\n</button>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
454
+ PdmButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmButtonComponent, selector: "pdm-button", inputs: { type: "type", variant: "variant", state: "state", size: "size", disabled: "disabled", loading: "loading", className: "className" }, outputs: { pressed: "pressed" }, ngImport: i0, template: "<button\n [type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading\"\n [ngClass]=\"rootClasses\"\n (click)=\"onClick($event)\"\n>\n <span\n *ngIf=\"loading\"\n class=\"inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-r-transparent\"\n aria-hidden=\"true\"\n ></span>\n <ng-content select=\"[pdmButtonIcon]\" *ngIf=\"showsIconSlot\"></ng-content>\n <ng-content></ng-content>\n</button>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
422
455
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmButtonComponent, decorators: [{
423
456
  type: Component,
424
- args: [{ selector: 'pdm-button', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading\"\n [ngClass]=\"rootClasses\"\n (click)=\"onClick($event)\"\n>\n <span\n *ngIf=\"loading\"\n class=\"inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-r-transparent\"\n aria-hidden=\"true\"\n ></span>\n <ng-content select=\"[pdmButtonIcon]\" *ngIf=\"variant === 'with-icon' || variant === 'icon' || variant === 'icon-circle' || variant === 'rounded'\"></ng-content>\n <ng-content></ng-content>\n</button>\n" }]
457
+ args: [{ selector: 'pdm-button', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading\"\n [ngClass]=\"rootClasses\"\n (click)=\"onClick($event)\"\n>\n <span\n *ngIf=\"loading\"\n class=\"inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-r-transparent\"\n aria-hidden=\"true\"\n ></span>\n <ng-content select=\"[pdmButtonIcon]\" *ngIf=\"showsIconSlot\"></ng-content>\n <ng-content></ng-content>\n</button>\n" }]
425
458
  }], propDecorators: { type: [{
426
459
  type: Input
427
460
  }], variant: [{
@@ -440,71 +473,472 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
440
473
  type: Output
441
474
  }] } });
442
475
 
476
+ const DEFAULT_VIEW_MONTH = new Date(2025, 5, 1); // June 2025 (Figma default)
477
+ const DAY_MS = 24 * 60 * 60 * 1000;
443
478
  class PdmCalendarComponent {
444
- constructor() {
445
- this.mode = 'single';
446
- this.month = 6;
447
- this.year = 2025;
448
- this.selectedDay = 25;
449
- this.rangeStartDay = 25;
450
- this.rangeEndDay = 9;
479
+ constructor(cdr) {
480
+ this.cdr = cdr;
481
+ this._value = null;
482
+ this._rangeValue = null;
483
+ this._month = null;
484
+ this.variant = 'single';
451
485
  this.className = '';
486
+ this.disabledDates = [];
487
+ this.minDate = null;
488
+ this.maxDate = null;
489
+ this.isDateDisabled = null;
490
+ this.allowSameDayRange = true;
491
+ this.readonly = false;
492
+ this.valueChange = new EventEmitter();
493
+ this.rangeValueChange = new EventEmitter();
494
+ this.monthChange = new EventEmitter();
495
+ this.dateClick = new EventEmitter();
496
+ this.disabledDateClick = new EventEmitter();
452
497
  this.weekdays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
498
+ this.monthOptions = [
499
+ { value: 0, label: 'Jan' },
500
+ { value: 1, label: 'Feb' },
501
+ { value: 2, label: 'Mar' },
502
+ { value: 3, label: 'Apr' },
503
+ { value: 4, label: 'May' },
504
+ { value: 5, label: 'Jun' },
505
+ { value: 6, label: 'Jul' },
506
+ { value: 7, label: 'Aug' },
507
+ { value: 8, label: 'Sep' },
508
+ { value: 9, label: 'Oct' },
509
+ { value: 10, label: 'Nov' },
510
+ { value: 11, label: 'Dec' }
511
+ ];
512
+ this.trackByIndex = (index) => {
513
+ return index;
514
+ };
515
+ this.trackByDate = (_index, cell) => {
516
+ return this.dateKey(cell.date);
517
+ };
518
+ }
519
+ set value(value) {
520
+ this._value = this.normalizeDate(value);
521
+ }
522
+ get value() {
523
+ return this._value;
524
+ }
525
+ set rangeValue(value) {
526
+ this._rangeValue = value
527
+ ? {
528
+ start: this.normalizeDate(value.start),
529
+ end: this.normalizeDate(value.end)
530
+ }
531
+ : null;
532
+ }
533
+ get rangeValue() {
534
+ return this._rangeValue;
535
+ }
536
+ set month(value) {
537
+ this._month = value ? this.startOfMonth(value) : null;
538
+ }
539
+ get month() {
540
+ return this._month;
541
+ }
542
+ get resolvedVariant() {
543
+ return this.variant === 'range' ? 'range' : 'single';
544
+ }
545
+ get visibleMonths() {
546
+ const baseMonth = this.getAnchorMonth();
547
+ if (this.resolvedVariant === 'single') {
548
+ return [
549
+ {
550
+ date: baseMonth,
551
+ title: this.formatMonthYear(baseMonth),
552
+ titleStyle: 'dropdowns',
553
+ dropdownMonth: this.formatMonthShort(baseMonth),
554
+ dropdownYear: String(baseMonth.getFullYear()),
555
+ showPrevButton: true,
556
+ showNextButton: true,
557
+ weeks: this.buildMonthWeeks(baseMonth, false)
558
+ }
559
+ ];
560
+ }
561
+ const nextMonth = this.addMonths(baseMonth, 1);
562
+ return [
563
+ {
564
+ date: baseMonth,
565
+ title: this.formatMonthYear(baseMonth),
566
+ titleStyle: 'plain',
567
+ showPrevButton: true,
568
+ showNextButton: false,
569
+ weeks: this.buildMonthWeeks(baseMonth, true)
570
+ },
571
+ {
572
+ date: nextMonth,
573
+ title: this.formatMonthYear(nextMonth),
574
+ titleStyle: 'plain',
575
+ showPrevButton: false,
576
+ showNextButton: true,
577
+ weeks: this.buildMonthWeeks(nextMonth, true)
578
+ }
579
+ ];
580
+ }
581
+ get singleHeaderMonth() {
582
+ return this.getAnchorMonth().getMonth();
583
+ }
584
+ get singleHeaderYear() {
585
+ return this.getAnchorMonth().getFullYear();
586
+ }
587
+ get yearOptions() {
588
+ const currentYear = this.singleHeaderYear;
589
+ const minYear = this.minDate ? this.minDate.getFullYear() : currentYear - 100;
590
+ const maxYear = this.maxDate ? this.maxDate.getFullYear() : currentYear + 100;
591
+ const years = [];
592
+ for (let year = minYear; year <= maxYear; year += 1) {
593
+ years.push(year);
594
+ }
595
+ return years;
596
+ }
597
+ get rootClasses() {
598
+ return [
599
+ 'border-border bg-background relative rounded-[10px] border p-3 shadow-sm',
600
+ this.resolvedVariant === 'range'
601
+ ? 'inline-flex items-start justify-center gap-4 shrink-0 grow-0 basis-auto'
602
+ : 'inline-flex flex-col gap-4 shrink-0 grow-0 basis-auto',
603
+ this.className
604
+ ];
605
+ }
606
+ get rootStyle() {
607
+ const width = this.resolvedVariant === 'range' ? '488px' : '250px';
608
+ return {
609
+ width,
610
+ minWidth: width,
611
+ maxWidth: width,
612
+ minHeight: '293px',
613
+ flex: '0 0 auto',
614
+ alignSelf: 'flex-start'
615
+ };
616
+ }
617
+ monthPanelClasses(_index) {
618
+ return ['flex flex-col items-start', this.resolvedVariant === 'range' ? 'w-[224px] gap-4' : 'w-full gap-0'];
619
+ }
620
+ headerClasses(month) {
621
+ return ['flex w-full items-center justify-between', month.titleStyle === 'dropdowns' ? '' : 'mb-4'];
622
+ }
623
+ navButtonClasses() {
624
+ return [
625
+ 'flex h-8 w-8 items-center justify-center rounded-md text-foreground',
626
+ 'disabled:pointer-events-none disabled:opacity-40'
627
+ ];
628
+ }
629
+ navPlaceholderClasses() {
630
+ return ['h-7 w-7 shrink-0'];
631
+ }
632
+ dropdownWrapClasses() {
633
+ return ['flex w-40 items-center justify-center gap-2'];
634
+ }
635
+ dropdownClasses(widthClass) {
636
+ return ['flex h-8 items-center justify-center gap-1 px-1', widthClass];
637
+ }
638
+ dropdownSelectClasses() {
639
+ return [
640
+ 'text-foreground h-full bg-transparent text-sm font-medium leading-5',
641
+ 'appearance-none border-0 outline-none ring-0 focus:outline-none focus:ring-0 text-center cursor-pointer'
642
+ ];
643
+ }
644
+ get dropdownSelectStyle() {
645
+ return {
646
+ appearance: 'none',
647
+ WebkitAppearance: 'none',
648
+ MozAppearance: 'none',
649
+ background: 'transparent',
650
+ border: '0',
651
+ boxShadow: 'none',
652
+ outline: '0',
653
+ padding: '0',
654
+ margin: '0'
655
+ };
656
+ }
657
+ calendarGridWrapClasses() {
658
+ return ['flex w-full flex-col items-start'];
659
+ }
660
+ weekdayRowClasses() {
661
+ return ['flex w-full items-center'];
662
+ }
663
+ weekdayCellClasses() {
664
+ return ['text-muted-foreground flex h-[21px] w-8 items-center justify-center rounded-md text-xs leading-4'];
665
+ }
666
+ weekRowClasses() {
667
+ return ['flex w-full items-start pt-2'];
668
+ }
669
+ dayCellClasses(cell) {
670
+ return [
671
+ 'relative flex h-8 w-8 shrink-0 items-center justify-center',
672
+ cell.rangeFill ? 'bg-accent' : '',
673
+ cell.rangeLeftCap ? 'rounded-l-md' : '',
674
+ cell.rangeRightCap ? 'rounded-r-md' : ''
675
+ ];
676
+ }
677
+ dayButtonClasses(cell) {
678
+ return [
679
+ 'relative z-10 flex h-8 w-8 items-center justify-center rounded-md text-sm leading-5',
680
+ cell.selected ? 'bg-primary text-primary-foreground' : cell.rangeFill ? 'text-accent-foreground' : 'text-foreground',
681
+ cell.muted && !cell.rangeFill ? 'opacity-50' : '',
682
+ cell.disabled ? 'cursor-not-allowed opacity-40' : '',
683
+ !cell.disabled && !this.readonly && !cell.selected ? 'hover:bg-accent/70' : ''
684
+ ];
685
+ }
686
+ dayLabelClasses(_cell) {
687
+ return ['font-normal'];
688
+ }
689
+ goToPreviousMonth() {
690
+ this.setAnchorMonth(this.addMonths(this.getAnchorMonth(), -1));
691
+ }
692
+ goToNextMonth() {
693
+ this.setAnchorMonth(this.addMonths(this.getAnchorMonth(), 1));
694
+ }
695
+ onSingleMonthChange(monthValue) {
696
+ const month = Number(monthValue);
697
+ if (Number.isNaN(month) || month < 0 || month > 11) {
698
+ return;
699
+ }
700
+ const anchor = this.getAnchorMonth();
701
+ this.setAnchorMonth(new Date(anchor.getFullYear(), month, 1));
702
+ }
703
+ onSingleYearChange(yearValue) {
704
+ const year = Number(yearValue);
705
+ if (Number.isNaN(year)) {
706
+ return;
707
+ }
708
+ const anchor = this.getAnchorMonth();
709
+ this.setAnchorMonth(new Date(year, anchor.getMonth(), 1));
710
+ }
711
+ onDatePressed(cell) {
712
+ const date = this.cloneDate(cell.date);
713
+ if (cell.disabled) {
714
+ this.disabledDateClick.emit(date);
715
+ return;
716
+ }
717
+ if (this.readonly) {
718
+ return;
719
+ }
720
+ this.dateClick.emit(date);
721
+ if (this.resolvedVariant === 'single') {
722
+ this._value = date;
723
+ this.valueChange.emit(this.cloneDate(date));
724
+ this.syncVisibleMonthToDate(date);
725
+ this.cdr.markForCheck();
726
+ return;
727
+ }
728
+ this.handleRangeSelection(date);
729
+ this.cdr.markForCheck();
730
+ }
731
+ handleRangeSelection(date) {
732
+ const current = this._rangeValue;
733
+ const currentStart = current?.start ? this.cloneDate(current.start) : null;
734
+ const currentEnd = current?.end ? this.cloneDate(current.end) : null;
735
+ if (!currentStart || (currentStart && currentEnd)) {
736
+ this._rangeValue = { start: date, end: null };
737
+ this.rangeValueChange.emit({ start: this.cloneDate(date), end: null });
738
+ this.syncVisibleMonthToDate(date);
739
+ return;
740
+ }
741
+ if (this.isSameDay(currentStart, date) && !this.allowSameDayRange) {
742
+ this._rangeValue = { start: date, end: null };
743
+ this.rangeValueChange.emit({ start: this.cloneDate(date), end: null });
744
+ return;
745
+ }
746
+ const start = this.compareDate(date, currentStart) < 0 ? date : currentStart;
747
+ const end = this.compareDate(date, currentStart) < 0 ? currentStart : date;
748
+ if (this.rangeContainsBlockedDate(start, end)) {
749
+ this.disabledDateClick.emit(this.cloneDate(date));
750
+ return;
751
+ }
752
+ this._rangeValue = { start, end };
753
+ this.rangeValueChange.emit({ start: this.cloneDate(start), end: this.cloneDate(end) });
754
+ this.syncVisibleMonthToDate(start);
755
+ }
756
+ buildMonthWeeks(month, includeRange) {
757
+ const firstOfMonth = this.startOfMonth(month);
758
+ const start = this.startOfWeek(firstOfMonth);
759
+ const end = this.endOfWeek(this.endOfMonth(firstOfMonth));
760
+ const weeks = [];
761
+ let cursor = this.cloneDate(start);
762
+ while (this.compareDate(cursor, end) <= 0) {
763
+ const row = [];
764
+ for (let col = 0; col < 7; col += 1) {
765
+ row.push(this.buildCell(cursor, month, includeRange));
766
+ cursor = this.addDays(cursor, 1);
767
+ }
768
+ weeks.push(row);
769
+ }
770
+ for (const row of weeks) {
771
+ for (let col = 0; col < row.length; col += 1) {
772
+ const cell = row[col];
773
+ if (!cell.inRange) {
774
+ continue;
775
+ }
776
+ const leftInRow = col > 0 ? row[col - 1].inRange : false;
777
+ const rightInRow = col < row.length - 1 ? row[col + 1].inRange : false;
778
+ cell.rangeLeftCap = !leftInRow;
779
+ cell.rangeRightCap = !rightInRow;
780
+ }
781
+ }
782
+ return weeks;
783
+ }
784
+ buildCell(date, visibleMonth, includeRange) {
785
+ const normalized = this.cloneDate(date);
786
+ const inCurrentMonth = normalized.getMonth() === visibleMonth.getMonth() && normalized.getFullYear() === visibleMonth.getFullYear();
787
+ const disabled = this.isBlocked(normalized);
788
+ const selectedSingle = this.resolvedVariant === 'single' && !!this._value && this.isSameDay(normalized, this._value);
789
+ const rangeStart = includeRange && !!this._rangeValue?.start && this.isSameDay(normalized, this._rangeValue.start);
790
+ const rangeEnd = includeRange && !!this._rangeValue?.end && this.isSameDay(normalized, this._rangeValue.end);
791
+ const inRange = includeRange &&
792
+ !!this._rangeValue?.start &&
793
+ !!this._rangeValue?.end &&
794
+ this.compareDate(normalized, this._rangeValue.start) >= 0 &&
795
+ this.compareDate(normalized, this._rangeValue.end) <= 0;
796
+ return {
797
+ date: normalized,
798
+ label: normalized.getDate(),
799
+ muted: !inCurrentMonth,
800
+ disabled,
801
+ selected: selectedSingle || rangeStart || rangeEnd,
802
+ inRange,
803
+ rangeFill: inRange,
804
+ rangeLeftCap: false,
805
+ rangeRightCap: false
806
+ };
807
+ }
808
+ getAnchorMonth() {
809
+ if (this._month) {
810
+ return this.cloneDate(this._month);
811
+ }
812
+ if (this.resolvedVariant === 'single' && this._value) {
813
+ return this.startOfMonth(this._value);
814
+ }
815
+ if (this.resolvedVariant === 'range' && this._rangeValue?.start) {
816
+ return this.startOfMonth(this._rangeValue.start);
817
+ }
818
+ return this.startOfMonth(DEFAULT_VIEW_MONTH);
819
+ }
820
+ setAnchorMonth(month) {
821
+ this._month = this.startOfMonth(month);
822
+ this.monthChange.emit(this.cloneDate(this._month));
823
+ }
824
+ syncVisibleMonthToDate(date) {
825
+ const nextMonth = this.startOfMonth(date);
826
+ if (!this._month || !this.isSameMonth(this._month, nextMonth)) {
827
+ this._month = nextMonth;
828
+ this.monthChange.emit(this.cloneDate(nextMonth));
829
+ }
830
+ }
831
+ isBlocked(date) {
832
+ if (this.minDate && this.compareDate(date, this.minDate) < 0) {
833
+ return true;
834
+ }
835
+ if (this.maxDate && this.compareDate(date, this.maxDate) > 0) {
836
+ return true;
837
+ }
838
+ const blockedSet = new Set((this.disabledDates || []).map((item) => this.dateKey(item)));
839
+ if (blockedSet.has(this.dateKey(date))) {
840
+ return true;
841
+ }
842
+ return !!this.isDateDisabled?.(this.cloneDate(date));
843
+ }
844
+ rangeContainsBlockedDate(start, end) {
845
+ let cursor = this.cloneDate(start);
846
+ while (this.compareDate(cursor, end) <= 0) {
847
+ if (this.isBlocked(cursor)) {
848
+ return true;
849
+ }
850
+ cursor = this.addDays(cursor, 1);
851
+ }
852
+ return false;
853
+ }
854
+ normalizeDate(value) {
855
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
856
+ return null;
857
+ }
858
+ return new Date(value.getFullYear(), value.getMonth(), value.getDate());
859
+ }
860
+ cloneDate(date) {
861
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
862
+ }
863
+ startOfMonth(date) {
864
+ return new Date(date.getFullYear(), date.getMonth(), 1);
865
+ }
866
+ endOfMonth(date) {
867
+ return new Date(date.getFullYear(), date.getMonth() + 1, 0);
868
+ }
869
+ startOfWeek(date) {
870
+ return this.addDays(date, -date.getDay());
871
+ }
872
+ endOfWeek(date) {
873
+ return this.addDays(date, 6 - date.getDay());
874
+ }
875
+ addMonths(date, months) {
876
+ return new Date(date.getFullYear(), date.getMonth() + months, 1);
453
877
  }
454
- get leftMonthName() {
455
- return this.monthName(this.month - 1);
456
- }
457
- get rightMonthName() {
458
- const rightMonth = this.month % 12;
459
- return this.monthName(rightMonth);
460
- }
461
- get leftCells() {
462
- return this.buildMonthCells(this.year, this.month - 1, this.selectedDay, this.mode === 'range' ? this.rangeStartDay : undefined, this.mode === 'range' ? 31 : undefined);
463
- }
464
- get rightCells() {
465
- const rightMonth = this.month % 12;
466
- const rightYear = this.month === 12 ? this.year + 1 : this.year;
467
- return this.buildMonthCells(rightYear, rightMonth, this.mode === 'range' ? this.rangeEndDay : undefined, 1, this.mode === 'range' ? this.rangeEndDay : undefined);
468
- }
469
- monthName(monthIndex) {
470
- const safe = ((monthIndex % 12) + 12) % 12;
471
- return new Date(this.year, safe, 1).toLocaleString('en-US', { month: 'long' });
472
- }
473
- buildMonthCells(year, monthIndex, selectedDay, rangeStartDay, rangeEndDay) {
474
- const firstDay = new Date(year, monthIndex, 1);
475
- const startWeekday = firstDay.getDay();
476
- const daysInMonth = new Date(year, monthIndex + 1, 0).getDate();
477
- const cells = [];
478
- for (let i = 0; i < 42; i += 1) {
479
- const dayNumber = i - startWeekday + 1;
480
- const date = new Date(year, monthIndex, dayNumber);
481
- const outside = dayNumber < 1 || dayNumber > daysInMonth;
482
- const day = date.getDate();
483
- const selected = !outside && !!selectedDay && day === selectedDay;
484
- const inRange = !outside && !!rangeStartDay && !!rangeEndDay && day >= rangeStartDay && day <= rangeEndDay;
485
- cells.push({ date, day, outside, selected, inRange });
486
- }
487
- return cells;
878
+ addDays(date, days) {
879
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
880
+ }
881
+ compareDate(a, b) {
882
+ return this.dateValue(a) - this.dateValue(b);
883
+ }
884
+ dateValue(date) {
885
+ return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) / DAY_MS;
886
+ }
887
+ isSameDay(a, b) {
888
+ return this.compareDate(a, b) === 0;
889
+ }
890
+ isSameMonth(a, b) {
891
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
892
+ }
893
+ dateKey(date) {
894
+ const y = date.getFullYear();
895
+ const m = String(date.getMonth() + 1).padStart(2, '0');
896
+ const d = String(date.getDate()).padStart(2, '0');
897
+ return `${y}-${m}-${d}`;
898
+ }
899
+ formatMonthShort(date) {
900
+ return date.toLocaleString('en-US', { month: 'short' });
901
+ }
902
+ formatMonthYear(date) {
903
+ return date.toLocaleString('en-US', { month: 'long', year: 'numeric' });
488
904
  }
489
905
  }
490
- PdmCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
491
- PdmCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: { mode: "mode", month: "month", year: "year", selectedDay: "selectedDay", rangeStartDay: "rangeStartDay", rangeEndDay: "rangeEndDay", className: "className" }, ngImport: i0, template: "<section\n [ngClass]=\"[\n 'rounded-lg border border-border bg-background p-3 shadow-sm',\n mode === 'range' ? 'w-full max-w-2xl' : 'w-full max-w-sm',\n className\n ]\"\n>\n <div [ngClass]=\"['grid gap-4', mode === 'range' ? 'grid-cols-2' : 'grid-cols-1']\">\n <div class=\"space-y-4\">\n <header class=\"flex items-center justify-between\">\n <button type=\"button\" class=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u2039</button>\n <div [ngClass]=\"['flex items-center justify-center gap-1', mode === 'range' ? 'w-full' : 'w-full']\">\n <ng-container *ngIf=\"mode === 'single'; else monthText\">\n <span class=\"inline-flex h-8 items-center rounded-md border border-border px-2 text-sm font-medium text-foreground shadow-sm\">Jun</span>\n <span class=\"inline-flex h-8 items-center rounded-md border border-border px-2 text-sm font-medium text-foreground shadow-sm\">2025</span>\n </ng-container>\n <ng-template #monthText>\n <span class=\"text-sm font-medium text-foreground\">{{ leftMonthName }} {{ year }}</span>\n </ng-template>\n </div>\n <button type=\"button\" class=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">{{ mode === 'range' ? '' : '\u203A' }}</button>\n </header>\n\n <div>\n <div class=\"grid grid-cols-7\">\n <span *ngFor=\"let day of weekdays\" class=\"inline-flex h-5 items-center justify-center text-xs font-normal text-muted-foreground\">{{ day }}</span>\n </div>\n <div class=\"mt-2 grid grid-cols-7 gap-y-2\">\n <button\n *ngFor=\"let cell of leftCells\"\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-sm font-normal transition-colors hover:bg-accent hover:text-accent-foreground',\n cell.outside ? 'text-muted-foreground opacity-50' : 'text-foreground',\n cell.inRange ? 'bg-accent text-accent-foreground' : '',\n cell.selected ? 'bg-primary text-primary-foreground' : ''\n ]\"\n >\n {{ cell.day }}\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"mode === 'range'\" class=\"space-y-4\">\n <header class=\"flex items-center justify-between\">\n <span class=\"text-sm font-medium text-foreground\">{{ rightMonthName }} {{ month === 12 ? year + 1 : year }}</span>\n <button type=\"button\" class=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u203A</button>\n </header>\n\n <div>\n <div class=\"grid grid-cols-7\">\n <span *ngFor=\"let day of weekdays\" class=\"inline-flex h-5 items-center justify-center text-xs font-normal text-muted-foreground\">{{ day }}</span>\n </div>\n <div class=\"mt-2 grid grid-cols-7 gap-y-2\">\n <button\n *ngFor=\"let cell of rightCells\"\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-sm font-normal transition-colors hover:bg-accent hover:text-accent-foreground',\n cell.outside ? 'text-muted-foreground opacity-50' : 'text-foreground',\n cell.inRange ? 'bg-accent text-accent-foreground' : '',\n cell.selected ? 'bg-primary text-primary-foreground' : ''\n ]\"\n >\n {{ cell.day }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</section>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
906
+ PdmCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCalendarComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
907
+ PdmCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: { variant: "variant", className: "className", disabledDates: "disabledDates", minDate: "minDate", maxDate: "maxDate", isDateDisabled: "isDateDisabled", allowSameDayRange: "allowSameDayRange", readonly: "readonly", value: "value", rangeValue: "rangeValue", month: "month" }, outputs: { valueChange: "valueChange", rangeValueChange: "rangeValueChange", monthChange: "monthChange", dateClick: "dateClick", disabledDateClick: "disabledDateClick" }, ngImport: i0, template: "<div [ngClass]=\"rootClasses\" [ngStyle]=\"rootStyle\">\n <div *ngFor=\"let month of visibleMonths; let monthIndex = index; trackBy: trackByIndex\" [ngClass]=\"monthPanelClasses(monthIndex)\">\n <div [ngClass]=\"headerClasses(month)\">\n <button\n *ngIf=\"month.showPrevButton; else prevPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Previous month\"\n (click)=\"goToPreviousMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #prevPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container *ngIf=\"month.titleStyle === 'dropdowns'; else plainTitle\">\n <div [ngClass]=\"dropdownWrapClasses()\">\n <div [ngClass]=\"dropdownClasses('w-[72px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderMonth\"\n aria-label=\"Month\"\n (change)=\"onSingleMonthChange($any($event.target).value)\"\n >\n <option *ngFor=\"let monthOption of monthOptions\" [value]=\"monthOption.value\">{{ monthOption.label }}</option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n <div [ngClass]=\"dropdownClasses('w-[82px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderYear\"\n aria-label=\"Year\"\n (change)=\"onSingleYearChange($any($event.target).value)\"\n >\n <option *ngFor=\"let year of yearOptions\" [value]=\"year\">{{ year }}</option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n </div>\n </ng-container>\n\n <ng-template #plainTitle>\n <div class=\"flex min-w-0 flex-1 items-center justify-center\">\n <p class=\"text-foreground text-center text-sm font-medium leading-5\">\n {{ month.title }}\n </p>\n </div>\n </ng-template>\n\n <button\n *ngIf=\"month.showNextButton; else nextPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #nextPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n </div>\n\n <div [ngClass]=\"calendarGridWrapClasses()\">\n <div [ngClass]=\"weekdayRowClasses()\">\n <div *ngFor=\"let day of weekdays; trackBy: trackByIndex\" [ngClass]=\"weekdayCellClasses()\">\n <span>{{ day }}</span>\n </div>\n </div>\n\n <div *ngFor=\"let week of month.weeks; trackBy: trackByIndex\" [ngClass]=\"weekRowClasses()\">\n <div *ngFor=\"let cell of week; trackBy: trackByDate\" [ngClass]=\"dayCellClasses(cell)\">\n <button\n type=\"button\"\n [ngClass]=\"dayButtonClasses(cell)\"\n [disabled]=\"readonly\"\n [attr.aria-selected]=\"cell.selected\"\n [attr.aria-disabled]=\"cell.disabled || readonly\"\n [attr.title]=\"cell.date | date : 'yyyy-MM-dd'\"\n (click)=\"onDatePressed(cell)\"\n >\n <span [ngClass]=\"dayLabelClasses(cell)\">{{ cell.label }}</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
492
908
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCalendarComponent, decorators: [{
493
909
  type: Component,
494
- args: [{ selector: 'pdm-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<section\n [ngClass]=\"[\n 'rounded-lg border border-border bg-background p-3 shadow-sm',\n mode === 'range' ? 'w-full max-w-2xl' : 'w-full max-w-sm',\n className\n ]\"\n>\n <div [ngClass]=\"['grid gap-4', mode === 'range' ? 'grid-cols-2' : 'grid-cols-1']\">\n <div class=\"space-y-4\">\n <header class=\"flex items-center justify-between\">\n <button type=\"button\" class=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u2039</button>\n <div [ngClass]=\"['flex items-center justify-center gap-1', mode === 'range' ? 'w-full' : 'w-full']\">\n <ng-container *ngIf=\"mode === 'single'; else monthText\">\n <span class=\"inline-flex h-8 items-center rounded-md border border-border px-2 text-sm font-medium text-foreground shadow-sm\">Jun</span>\n <span class=\"inline-flex h-8 items-center rounded-md border border-border px-2 text-sm font-medium text-foreground shadow-sm\">2025</span>\n </ng-container>\n <ng-template #monthText>\n <span class=\"text-sm font-medium text-foreground\">{{ leftMonthName }} {{ year }}</span>\n </ng-template>\n </div>\n <button type=\"button\" class=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">{{ mode === 'range' ? '' : '\u203A' }}</button>\n </header>\n\n <div>\n <div class=\"grid grid-cols-7\">\n <span *ngFor=\"let day of weekdays\" class=\"inline-flex h-5 items-center justify-center text-xs font-normal text-muted-foreground\">{{ day }}</span>\n </div>\n <div class=\"mt-2 grid grid-cols-7 gap-y-2\">\n <button\n *ngFor=\"let cell of leftCells\"\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-sm font-normal transition-colors hover:bg-accent hover:text-accent-foreground',\n cell.outside ? 'text-muted-foreground opacity-50' : 'text-foreground',\n cell.inRange ? 'bg-accent text-accent-foreground' : '',\n cell.selected ? 'bg-primary text-primary-foreground' : ''\n ]\"\n >\n {{ cell.day }}\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"mode === 'range'\" class=\"space-y-4\">\n <header class=\"flex items-center justify-between\">\n <span class=\"text-sm font-medium text-foreground\">{{ rightMonthName }} {{ month === 12 ? year + 1 : year }}</span>\n <button type=\"button\" class=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u203A</button>\n </header>\n\n <div>\n <div class=\"grid grid-cols-7\">\n <span *ngFor=\"let day of weekdays\" class=\"inline-flex h-5 items-center justify-center text-xs font-normal text-muted-foreground\">{{ day }}</span>\n </div>\n <div class=\"mt-2 grid grid-cols-7 gap-y-2\">\n <button\n *ngFor=\"let cell of rightCells\"\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-sm font-normal transition-colors hover:bg-accent hover:text-accent-foreground',\n cell.outside ? 'text-muted-foreground opacity-50' : 'text-foreground',\n cell.inRange ? 'bg-accent text-accent-foreground' : '',\n cell.selected ? 'bg-primary text-primary-foreground' : ''\n ]\"\n >\n {{ cell.day }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</section>\n" }]
495
- }], propDecorators: { mode: [{
910
+ args: [{ selector: 'pdm-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"rootClasses\" [ngStyle]=\"rootStyle\">\n <div *ngFor=\"let month of visibleMonths; let monthIndex = index; trackBy: trackByIndex\" [ngClass]=\"monthPanelClasses(monthIndex)\">\n <div [ngClass]=\"headerClasses(month)\">\n <button\n *ngIf=\"month.showPrevButton; else prevPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Previous month\"\n (click)=\"goToPreviousMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #prevPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container *ngIf=\"month.titleStyle === 'dropdowns'; else plainTitle\">\n <div [ngClass]=\"dropdownWrapClasses()\">\n <div [ngClass]=\"dropdownClasses('w-[72px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderMonth\"\n aria-label=\"Month\"\n (change)=\"onSingleMonthChange($any($event.target).value)\"\n >\n <option *ngFor=\"let monthOption of monthOptions\" [value]=\"monthOption.value\">{{ monthOption.label }}</option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n <div [ngClass]=\"dropdownClasses('w-[82px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderYear\"\n aria-label=\"Year\"\n (change)=\"onSingleYearChange($any($event.target).value)\"\n >\n <option *ngFor=\"let year of yearOptions\" [value]=\"year\">{{ year }}</option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n </div>\n </ng-container>\n\n <ng-template #plainTitle>\n <div class=\"flex min-w-0 flex-1 items-center justify-center\">\n <p class=\"text-foreground text-center text-sm font-medium leading-5\">\n {{ month.title }}\n </p>\n </div>\n </ng-template>\n\n <button\n *ngIf=\"month.showNextButton; else nextPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #nextPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n </div>\n\n <div [ngClass]=\"calendarGridWrapClasses()\">\n <div [ngClass]=\"weekdayRowClasses()\">\n <div *ngFor=\"let day of weekdays; trackBy: trackByIndex\" [ngClass]=\"weekdayCellClasses()\">\n <span>{{ day }}</span>\n </div>\n </div>\n\n <div *ngFor=\"let week of month.weeks; trackBy: trackByIndex\" [ngClass]=\"weekRowClasses()\">\n <div *ngFor=\"let cell of week; trackBy: trackByDate\" [ngClass]=\"dayCellClasses(cell)\">\n <button\n type=\"button\"\n [ngClass]=\"dayButtonClasses(cell)\"\n [disabled]=\"readonly\"\n [attr.aria-selected]=\"cell.selected\"\n [attr.aria-disabled]=\"cell.disabled || readonly\"\n [attr.title]=\"cell.date | date : 'yyyy-MM-dd'\"\n (click)=\"onDatePressed(cell)\"\n >\n <span [ngClass]=\"dayLabelClasses(cell)\">{{ cell.label }}</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
911
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { variant: [{
496
912
  type: Input
497
- }], month: [{
913
+ }], className: [{
498
914
  type: Input
499
- }], year: [{
915
+ }], disabledDates: [{
500
916
  type: Input
501
- }], selectedDay: [{
917
+ }], minDate: [{
502
918
  type: Input
503
- }], rangeStartDay: [{
919
+ }], maxDate: [{
504
920
  type: Input
505
- }], rangeEndDay: [{
921
+ }], isDateDisabled: [{
506
922
  type: Input
507
- }], className: [{
923
+ }], allowSameDayRange: [{
924
+ type: Input
925
+ }], readonly: [{
926
+ type: Input
927
+ }], valueChange: [{
928
+ type: Output
929
+ }], rangeValueChange: [{
930
+ type: Output
931
+ }], monthChange: [{
932
+ type: Output
933
+ }], dateClick: [{
934
+ type: Output
935
+ }], disabledDateClick: [{
936
+ type: Output
937
+ }], value: [{
938
+ type: Input
939
+ }], rangeValue: [{
940
+ type: Input
941
+ }], month: [{
508
942
  type: Input
509
943
  }] } });
510
944
 
@@ -1092,10 +1526,10 @@ class PdmIconComponent {
1092
1526
  }
1093
1527
  }
1094
1528
  PdmIconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmIconComponent, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
1095
- PdmIconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmIconComponent, selector: "pdm-icon", inputs: { name: "name", library: "library", assetUrl: "assetUrl", size: "size", strokeWidth: "strokeWidth", className: "className", ariaLabel: "ariaLabel", decorative: "decorative" }, ngImport: i0, template: "<ng-container *ngIf=\"assetUrl; else inlineIcon\">\n <img\n [src]=\"assetUrl\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [ngClass]=\"className\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n alt=\"\"\n />\n</ng-container>\n\n<ng-template #inlineIcon>\n <span\n [ngClass]=\"className\"\n [style.display]=\"'inline-flex'\"\n [style.align-items]=\"'center'\"\n [style.justify-content]=\"'center'\"\n [style.line-height]=\"0\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n [innerHTML]=\"svgMarkup\"\n ></span>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1529
+ PdmIconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmIconComponent, selector: "pdm-icon", inputs: { name: "name", library: "library", assetUrl: "assetUrl", size: "size", strokeWidth: "strokeWidth", className: "className", ariaLabel: "ariaLabel", decorative: "decorative" }, ngImport: i0, template: "<ng-container *ngIf=\"assetUrl; else inlineIcon\">\n <img\n [src]=\"assetUrl\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [ngClass]=\"className\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n alt=\"\"\n />\n</ng-container>\n\n<ng-template #inlineIcon>\n <span\n [ngClass]=\"className\"\n [style.display]=\"'inline-flex'\"\n [style.align-items]=\"'center'\"\n [style.justify-content]=\"'center'\"\n [style.line-height]=\"0\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n [innerHTML]=\"svgMarkup\"\n ></span>\n</ng-template>\n", styles: [":host{display:inline-flex;align-items:center;justify-content:center;line-height:0;flex-shrink:0}:host svg{display:block}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1096
1530
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmIconComponent, decorators: [{
1097
1531
  type: Component,
1098
- args: [{ selector: 'pdm-icon', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"assetUrl; else inlineIcon\">\n <img\n [src]=\"assetUrl\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [ngClass]=\"className\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n alt=\"\"\n />\n</ng-container>\n\n<ng-template #inlineIcon>\n <span\n [ngClass]=\"className\"\n [style.display]=\"'inline-flex'\"\n [style.align-items]=\"'center'\"\n [style.justify-content]=\"'center'\"\n [style.line-height]=\"0\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n [innerHTML]=\"svgMarkup\"\n ></span>\n</ng-template>\n" }]
1532
+ args: [{ selector: 'pdm-icon', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"assetUrl; else inlineIcon\">\n <img\n [src]=\"assetUrl\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [ngClass]=\"className\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n alt=\"\"\n />\n</ng-container>\n\n<ng-template #inlineIcon>\n <span\n [ngClass]=\"className\"\n [style.display]=\"'inline-flex'\"\n [style.align-items]=\"'center'\"\n [style.justify-content]=\"'center'\"\n [style.line-height]=\"0\"\n [style.width.px]=\"resolvedSize\"\n [style.height.px]=\"resolvedSize\"\n [attr.role]=\"decorative ? null : 'img'\"\n [attr.aria-hidden]=\"decorative ? 'true' : null\"\n [attr.aria-label]=\"!decorative ? ariaLabel || name : null\"\n [innerHTML]=\"svgMarkup\"\n ></span>\n</ng-template>\n", styles: [":host{display:inline-flex;align-items:center;justify-content:center;line-height:0;flex-shrink:0}:host svg{display:block}\n"] }]
1099
1533
  }], ctorParameters: function () { return [{ type: i1$1.DomSanitizer }]; }, propDecorators: { name: [{
1100
1534
  type: Input
1101
1535
  }], library: [{
@@ -1358,63 +1792,299 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1358
1792
  type: Output
1359
1793
  }] } });
1360
1794
 
1361
- class PdmDatePickerComponent {
1795
+ class PdmLabelComponent {
1362
1796
  constructor() {
1363
- this.variant = 'default';
1797
+ this.forId = '';
1798
+ this.required = false;
1364
1799
  this.className = '';
1365
- this.open = false;
1366
- this.label = 'Date of Birth';
1367
- this.value = 'Select a date';
1368
- this.month = 6;
1369
- this.year = 2025;
1370
- this.selectedDay = 25;
1371
- this.time = '10:30:00';
1372
- this.naturalLanguageValue = 'In 2 days';
1373
- this.naturalLanguageHint = 'Your post will be published on June 21, 2025.';
1374
- this.openChange = new EventEmitter();
1800
+ }
1801
+ }
1802
+ PdmLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1803
+ PdmLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmLabelComponent, selector: "pdm-label", inputs: { forId: "forId", required: "required", className: "className" }, ngImport: i0, template: "<label\n [attr.for]=\"forId\"\n [ngClass]=\"['text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className]\"\n>\n <ng-content></ng-content>\n <span *ngIf=\"required\" class=\"ml-1 text-destructive\">*</span>\n</label>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1804
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmLabelComponent, decorators: [{
1805
+ type: Component,
1806
+ args: [{ selector: 'pdm-label', changeDetection: ChangeDetectionStrategy.OnPush, template: "<label\n [attr.for]=\"forId\"\n [ngClass]=\"['text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className]\"\n>\n <ng-content></ng-content>\n <span *ngIf=\"required\" class=\"ml-1 text-destructive\">*</span>\n</label>\n" }]
1807
+ }], propDecorators: { forId: [{
1808
+ type: Input
1809
+ }], required: [{
1810
+ type: Input
1811
+ }], className: [{
1812
+ type: Input
1813
+ }] } });
1814
+
1815
+ let nextDatePickerId = 0;
1816
+ class PdmDatePickerComponent {
1817
+ constructor(elementRef, cdr) {
1818
+ this.elementRef = elementRef;
1819
+ this.cdr = cdr;
1820
+ this._value = null;
1821
+ this._rangeValue = null;
1822
+ this._open = false;
1823
+ this.instanceId = `pdm-date-picker-${++nextDatePickerId}`;
1824
+ this.triggerFocused = false;
1825
+ this.id = '';
1826
+ this.variant = 'single';
1827
+ this.label = '';
1828
+ this.labelClassName = '';
1829
+ this.className = '';
1830
+ this.triggerClassName = '';
1831
+ this.panelClassName = '';
1832
+ this.placeholder = 'Pick a date';
1833
+ this.rangePlaceholder = 'Pick a date range';
1834
+ this.format = 'MMM d, yyyy';
1835
+ this.disabled = false;
1836
+ this.readonly = false;
1837
+ this.required = false;
1838
+ this.invalid = false;
1839
+ this.allowSameDayRange = true;
1840
+ this.closeOnSelect = true;
1841
+ this.minDate = null;
1842
+ this.maxDate = null;
1843
+ this.disabledDates = [];
1844
+ this.isDateDisabled = null;
1375
1845
  this.valueChange = new EventEmitter();
1846
+ this.rangeValueChange = new EventEmitter();
1847
+ this.openChange = new EventEmitter();
1848
+ this.monthChange = new EventEmitter();
1376
1849
  }
1377
- toggle() {
1378
- this.openChange.emit(!this.open);
1850
+ set open(value) {
1851
+ this._open = !!value;
1852
+ this.cdr.markForCheck();
1379
1853
  }
1380
- selectPreset(value) {
1381
- this.valueChange.emit(value);
1854
+ get open() {
1855
+ return this._open;
1856
+ }
1857
+ set value(value) {
1858
+ this._value = this.normalizeDate(value);
1859
+ this.cdr.markForCheck();
1382
1860
  }
1383
- get monthLabel() {
1384
- return new Date(this.year, this.month - 1, 1).toLocaleString('en-US', { month: 'short' });
1861
+ get value() {
1862
+ return this._value;
1863
+ }
1864
+ set rangeValue(value) {
1865
+ this._rangeValue = value
1866
+ ? {
1867
+ start: this.normalizeDate(value.start),
1868
+ end: this.normalizeDate(value.end)
1869
+ }
1870
+ : null;
1871
+ this.cdr.markForCheck();
1872
+ }
1873
+ get rangeValue() {
1874
+ return this._rangeValue;
1875
+ }
1876
+ get resolvedVariant() {
1877
+ return this.variant === 'range' ? 'range' : 'single';
1878
+ }
1879
+ get triggerId() {
1880
+ return this.id || `${this.instanceId}-trigger`;
1881
+ }
1882
+ get panelId() {
1883
+ return `${this.id || this.instanceId}-panel`;
1884
+ }
1885
+ get hasSingleValue() {
1886
+ return this.resolvedVariant === 'single' && !!this._value;
1887
+ }
1888
+ get hasRangeValue() {
1889
+ return this.resolvedVariant === 'range' && !!this._rangeValue?.start;
1890
+ }
1891
+ get displayText() {
1892
+ if (this.resolvedVariant === 'single') {
1893
+ return this._value ? this.formatDate(this._value) : this.placeholder;
1894
+ }
1895
+ const start = this._rangeValue?.start ?? null;
1896
+ const end = this._rangeValue?.end ?? null;
1897
+ if (!start) {
1898
+ return this.rangePlaceholder;
1899
+ }
1900
+ if (!end) {
1901
+ return `${this.formatDate(start)} -`;
1902
+ }
1903
+ return `${this.formatDate(start)} - ${this.formatDate(end)}`;
1904
+ }
1905
+ get textClasses() {
1906
+ const hasValue = this.resolvedVariant === 'single' ? this.hasSingleValue : this.hasRangeValue;
1907
+ return [
1908
+ 'min-w-0 flex-1 truncate text-left text-sm leading-5',
1909
+ hasValue ? 'text-foreground' : 'text-muted-foreground'
1910
+ ];
1911
+ }
1912
+ get rootClasses() {
1913
+ return [
1914
+ 'grid gap-2',
1915
+ this.resolvedVariant === 'range' ? 'w-[280px]' : 'w-[197px]',
1916
+ this.className
1917
+ ];
1918
+ }
1919
+ get triggerClasses() {
1920
+ const focusStyle = this.open || this.triggerFocused;
1921
+ return [
1922
+ 'relative flex w-full items-center gap-2 overflow-hidden rounded-lg border px-3 py-[7.5px] text-left shadow-xs outline-none transition-colors',
1923
+ 'min-h-[36px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
1924
+ focusStyle
1925
+ ? 'bg-accent border-neutral-400 ring-3 ring-neutral-300'
1926
+ : 'bg-input border-input',
1927
+ this.invalid ? 'border-destructive ring-destructive/20' : '',
1928
+ this.triggerClassName
1929
+ ];
1930
+ }
1931
+ get panelClasses() {
1932
+ return [
1933
+ 'absolute left-0 top-full z-30 mt-2',
1934
+ this.panelClassName
1935
+ ];
1936
+ }
1937
+ toggleOpen() {
1938
+ if (this.disabled || this.readonly) {
1939
+ return;
1940
+ }
1941
+ this.setOpen(!this.open);
1942
+ }
1943
+ onTriggerFocus() {
1944
+ this.triggerFocused = true;
1945
+ this.cdr.markForCheck();
1946
+ }
1947
+ onTriggerBlur() {
1948
+ this.triggerFocused = false;
1949
+ this.cdr.markForCheck();
1950
+ }
1951
+ onCalendarValueChange(value) {
1952
+ this._value = this.normalizeDate(value);
1953
+ this.valueChange.emit(this._value ? this.cloneDate(this._value) : null);
1954
+ if (this.closeOnSelect && this._value) {
1955
+ this.setOpen(false);
1956
+ }
1957
+ else {
1958
+ this.cdr.markForCheck();
1959
+ }
1960
+ }
1961
+ onCalendarRangeValueChange(value) {
1962
+ this._rangeValue = value
1963
+ ? {
1964
+ start: this.normalizeDate(value.start),
1965
+ end: this.normalizeDate(value.end)
1966
+ }
1967
+ : null;
1968
+ this.rangeValueChange.emit(this._rangeValue
1969
+ ? {
1970
+ start: this._rangeValue.start ? this.cloneDate(this._rangeValue.start) : null,
1971
+ end: this._rangeValue.end ? this.cloneDate(this._rangeValue.end) : null
1972
+ }
1973
+ : null);
1974
+ if (this.closeOnSelect && this._rangeValue?.start && this._rangeValue?.end) {
1975
+ this.setOpen(false);
1976
+ return;
1977
+ }
1978
+ this.cdr.markForCheck();
1979
+ }
1980
+ onCalendarMonthChange(month) {
1981
+ this.monthChange.emit(this.cloneDate(month));
1982
+ }
1983
+ onEscape() {
1984
+ if (this.open) {
1985
+ this.setOpen(false);
1986
+ }
1987
+ }
1988
+ onDocumentClick(event) {
1989
+ if (!this.open) {
1990
+ return;
1991
+ }
1992
+ const target = event.target;
1993
+ if (target && !this.elementRef.nativeElement.contains(target)) {
1994
+ this.setOpen(false);
1995
+ }
1996
+ }
1997
+ setOpen(nextOpen) {
1998
+ if (this._open === nextOpen) {
1999
+ return;
2000
+ }
2001
+ this._open = nextOpen;
2002
+ this.openChange.emit(this._open);
2003
+ this.cdr.markForCheck();
2004
+ }
2005
+ formatDate(date) {
2006
+ try {
2007
+ return format(date, this.format || 'MMM d, yyyy');
2008
+ }
2009
+ catch {
2010
+ return format(date, 'MMM d, yyyy');
2011
+ }
2012
+ }
2013
+ normalizeDate(value) {
2014
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
2015
+ return null;
2016
+ }
2017
+ return new Date(value.getFullYear(), value.getMonth(), value.getDate());
2018
+ }
2019
+ cloneDate(date) {
2020
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
1385
2021
  }
1386
2022
  }
1387
- PdmDatePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDatePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1388
- PdmDatePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDatePickerComponent, selector: "pdm-date-picker", inputs: { variant: "variant", className: "className", open: "open", label: "label", value: "value", month: "month", year: "year", selectedDay: "selectedDay", time: "time", naturalLanguageValue: "naturalLanguageValue", naturalLanguageHint: "naturalLanguageHint" }, outputs: { openChange: "openChange", valueChange: "valueChange" }, ngImport: i0, template: "<section [ngClass]=\"['flex flex-col gap-3', className]\" class=\"w-full max-w-sm\">\n <label class=\"text-sm font-medium text-foreground\">{{ label }}</label>\n\n <div class=\"flex items-center gap-2\" *ngIf=\"variant === 'date-time'\">\n <button type=\"button\" class=\"flex h-9 flex-1 items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm\" (click)=\"toggle()\">\n <span class=\"truncate text-xs text-foreground\">{{ value }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>\n </button>\n <div class=\"flex h-9 w-24 items-center rounded-md border border-input bg-transparent px-3 py-1 text-xs text-foreground shadow-sm\">{{ time }}</div>\n </div>\n\n <div *ngIf=\"variant !== 'date-time'\" class=\"flex flex-col gap-2\">\n <button type=\"button\" class=\"flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm\" (click)=\"toggle()\">\n <span class=\"truncate text-sm text-foreground\">{{ variant === 'natural-language' ? naturalLanguageValue : value }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>\n </button>\n\n <p *ngIf=\"variant === 'natural-language'\" class=\"text-xs text-muted-foreground\">{{ naturalLanguageHint }}</p>\n </div>\n\n <div *ngIf=\"open\" class=\"w-full rounded-lg border border-border bg-background p-3 shadow-sm\">\n <div class=\"mb-4 flex items-center justify-between\">\n <button type=\"button\" class=\"h-8 w-8 rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u2039</button>\n <div class=\"flex items-center gap-1.5\">\n <button type=\"button\" class=\"inline-flex h-8 items-center gap-1 rounded-md border border-input px-2 text-sm font-medium text-foreground shadow-sm\">{{ monthLabel }} <span>\u02C5</span></button>\n <button type=\"button\" class=\"inline-flex h-8 items-center gap-1 rounded-md border border-input px-2 text-sm font-medium text-foreground shadow-sm\">{{ year }} <span>\u02C5</span></button>\n </div>\n <button type=\"button\" class=\"h-8 w-8 rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u203A</button>\n </div>\n\n <pdm-calendar [month]=\"month\" [year]=\"year\" [selectedDay]=\"selectedDay\" mode=\"single\"></pdm-calendar>\n\n <div *ngIf=\"variant === 'with-input' || variant === 'natural-language'\" class=\"mt-3 flex gap-2\">\n <button type=\"button\" class=\"h-8 rounded-md border border-input px-3 text-xs text-foreground\" (click)=\"selectPreset('Today')\">Today</button>\n <button type=\"button\" class=\"h-8 rounded-md border border-input px-3 text-xs text-foreground\" (click)=\"selectPreset('Tomorrow')\">Tomorrow</button>\n </div>\n </div>\n</section>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: ["mode", "month", "year", "selectedDay", "rangeStartDay", "rangeEndDay", "className"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2023
+ PdmDatePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDatePickerComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2024
+ PdmDatePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDatePickerComponent, selector: "pdm-date-picker", inputs: { id: "id", variant: "variant", label: "label", labelClassName: "labelClassName", className: "className", triggerClassName: "triggerClassName", panelClassName: "panelClassName", placeholder: "placeholder", rangePlaceholder: "rangePlaceholder", format: "format", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", allowSameDayRange: "allowSameDayRange", closeOnSelect: "closeOnSelect", minDate: "minDate", maxDate: "maxDate", disabledDates: "disabledDates", isDateDisabled: "isDateDisabled", open: "open", value: "value", rangeValue: "rangeValue" }, outputs: { valueChange: "valueChange", rangeValueChange: "rangeValueChange", openChange: "openChange", monthChange: "monthChange" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: "<div [ngClass]=\"rootClasses\">\n <pdm-label *ngIf=\"label\" [forId]=\"triggerId\" [required]=\"required\" [className]=\"labelClassName\">\n {{ label }}\n </pdm-label>\n\n <div class=\"relative inline-block w-full\">\n <button\n type=\"button\"\n [id]=\"triggerId\"\n [disabled]=\"disabled\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"invalid\"\n [ngClass]=\"triggerClasses\"\n [attr.title]=\"displayText\"\n (click)=\"toggleOpen()\"\n (focus)=\"onTriggerFocus()\"\n (blur)=\"onTriggerBlur()\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center p-0.5 text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\">\n <path d=\"M8 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M16 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"16.5\" rx=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></rect>\n <path d=\"M3 9.5h18\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </span>\n\n <span [ngClass]=\"textClasses\">{{ displayText }}</span>\n </button>\n\n <div *ngIf=\"open\" [id]=\"panelId\" [ngClass]=\"panelClasses\" role=\"dialog\" [attr.aria-labelledby]=\"label ? triggerId : null\">\n <pdm-calendar\n [variant]=\"resolvedVariant\"\n [value]=\"value\"\n [rangeValue]=\"rangeValue\"\n [readonly]=\"readonly\"\n [allowSameDayRange]=\"allowSameDayRange\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [disabledDates]=\"disabledDates\"\n [isDateDisabled]=\"isDateDisabled\"\n (valueChange)=\"onCalendarValueChange($event)\"\n (rangeValueChange)=\"onCalendarRangeValueChange($event)\"\n (monthChange)=\"onCalendarMonthChange($event)\"\n ></pdm-calendar>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: ["variant", "className", "disabledDates", "minDate", "maxDate", "isDateDisabled", "allowSameDayRange", "readonly", "value", "rangeValue", "month"], outputs: ["valueChange", "rangeValueChange", "monthChange", "dateClick", "disabledDateClick"] }, { kind: "component", type: PdmLabelComponent, selector: "pdm-label", inputs: ["forId", "required", "className"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1389
2025
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDatePickerComponent, decorators: [{
1390
2026
  type: Component,
1391
- args: [{ selector: 'pdm-date-picker', changeDetection: ChangeDetectionStrategy.OnPush, template: "<section [ngClass]=\"['flex flex-col gap-3', className]\" class=\"w-full max-w-sm\">\n <label class=\"text-sm font-medium text-foreground\">{{ label }}</label>\n\n <div class=\"flex items-center gap-2\" *ngIf=\"variant === 'date-time'\">\n <button type=\"button\" class=\"flex h-9 flex-1 items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm\" (click)=\"toggle()\">\n <span class=\"truncate text-xs text-foreground\">{{ value }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>\n </button>\n <div class=\"flex h-9 w-24 items-center rounded-md border border-input bg-transparent px-3 py-1 text-xs text-foreground shadow-sm\">{{ time }}</div>\n </div>\n\n <div *ngIf=\"variant !== 'date-time'\" class=\"flex flex-col gap-2\">\n <button type=\"button\" class=\"flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm\" (click)=\"toggle()\">\n <span class=\"truncate text-sm text-foreground\">{{ variant === 'natural-language' ? naturalLanguageValue : value }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>\n </button>\n\n <p *ngIf=\"variant === 'natural-language'\" class=\"text-xs text-muted-foreground\">{{ naturalLanguageHint }}</p>\n </div>\n\n <div *ngIf=\"open\" class=\"w-full rounded-lg border border-border bg-background p-3 shadow-sm\">\n <div class=\"mb-4 flex items-center justify-between\">\n <button type=\"button\" class=\"h-8 w-8 rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u2039</button>\n <div class=\"flex items-center gap-1.5\">\n <button type=\"button\" class=\"inline-flex h-8 items-center gap-1 rounded-md border border-input px-2 text-sm font-medium text-foreground shadow-sm\">{{ monthLabel }} <span>\u02C5</span></button>\n <button type=\"button\" class=\"inline-flex h-8 items-center gap-1 rounded-md border border-input px-2 text-sm font-medium text-foreground shadow-sm\">{{ year }} <span>\u02C5</span></button>\n </div>\n <button type=\"button\" class=\"h-8 w-8 rounded-md text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\">\u203A</button>\n </div>\n\n <pdm-calendar [month]=\"month\" [year]=\"year\" [selectedDay]=\"selectedDay\" mode=\"single\"></pdm-calendar>\n\n <div *ngIf=\"variant === 'with-input' || variant === 'natural-language'\" class=\"mt-3 flex gap-2\">\n <button type=\"button\" class=\"h-8 rounded-md border border-input px-3 text-xs text-foreground\" (click)=\"selectPreset('Today')\">Today</button>\n <button type=\"button\" class=\"h-8 rounded-md border border-input px-3 text-xs text-foreground\" (click)=\"selectPreset('Tomorrow')\">Tomorrow</button>\n </div>\n </div>\n</section>\n" }]
1392
- }], propDecorators: { variant: [{
2027
+ args: [{ selector: 'pdm-date-picker', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"rootClasses\">\n <pdm-label *ngIf=\"label\" [forId]=\"triggerId\" [required]=\"required\" [className]=\"labelClassName\">\n {{ label }}\n </pdm-label>\n\n <div class=\"relative inline-block w-full\">\n <button\n type=\"button\"\n [id]=\"triggerId\"\n [disabled]=\"disabled\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"invalid\"\n [ngClass]=\"triggerClasses\"\n [attr.title]=\"displayText\"\n (click)=\"toggleOpen()\"\n (focus)=\"onTriggerFocus()\"\n (blur)=\"onTriggerBlur()\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center p-0.5 text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\">\n <path d=\"M8 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M16 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"16.5\" rx=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></rect>\n <path d=\"M3 9.5h18\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </span>\n\n <span [ngClass]=\"textClasses\">{{ displayText }}</span>\n </button>\n\n <div *ngIf=\"open\" [id]=\"panelId\" [ngClass]=\"panelClasses\" role=\"dialog\" [attr.aria-labelledby]=\"label ? triggerId : null\">\n <pdm-calendar\n [variant]=\"resolvedVariant\"\n [value]=\"value\"\n [rangeValue]=\"rangeValue\"\n [readonly]=\"readonly\"\n [allowSameDayRange]=\"allowSameDayRange\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [disabledDates]=\"disabledDates\"\n [isDateDisabled]=\"isDateDisabled\"\n (valueChange)=\"onCalendarValueChange($event)\"\n (rangeValueChange)=\"onCalendarRangeValueChange($event)\"\n (monthChange)=\"onCalendarMonthChange($event)\"\n ></pdm-calendar>\n </div>\n </div>\n</div>\n" }]
2028
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { id: [{
2029
+ type: Input
2030
+ }], variant: [{
2031
+ type: Input
2032
+ }], label: [{
2033
+ type: Input
2034
+ }], labelClassName: [{
1393
2035
  type: Input
1394
2036
  }], className: [{
1395
2037
  type: Input
1396
- }], open: [{
2038
+ }], triggerClassName: [{
1397
2039
  type: Input
1398
- }], label: [{
2040
+ }], panelClassName: [{
1399
2041
  type: Input
1400
- }], value: [{
2042
+ }], placeholder: [{
1401
2043
  type: Input
1402
- }], month: [{
2044
+ }], rangePlaceholder: [{
2045
+ type: Input
2046
+ }], format: [{
2047
+ type: Input
2048
+ }], disabled: [{
2049
+ type: Input
2050
+ }], readonly: [{
2051
+ type: Input
2052
+ }], required: [{
1403
2053
  type: Input
1404
- }], year: [{
2054
+ }], invalid: [{
2055
+ type: Input
2056
+ }], allowSameDayRange: [{
1405
2057
  type: Input
1406
- }], selectedDay: [{
2058
+ }], closeOnSelect: [{
1407
2059
  type: Input
1408
- }], time: [{
2060
+ }], minDate: [{
1409
2061
  type: Input
1410
- }], naturalLanguageValue: [{
2062
+ }], maxDate: [{
1411
2063
  type: Input
1412
- }], naturalLanguageHint: [{
2064
+ }], disabledDates: [{
1413
2065
  type: Input
2066
+ }], isDateDisabled: [{
2067
+ type: Input
2068
+ }], valueChange: [{
2069
+ type: Output
2070
+ }], rangeValueChange: [{
2071
+ type: Output
1414
2072
  }], openChange: [{
1415
2073
  type: Output
1416
- }], valueChange: [{
2074
+ }], monthChange: [{
1417
2075
  type: Output
2076
+ }], open: [{
2077
+ type: Input
2078
+ }], value: [{
2079
+ type: Input
2080
+ }], rangeValue: [{
2081
+ type: Input
2082
+ }], onEscape: [{
2083
+ type: HostListener,
2084
+ args: ['document:keydown.escape']
2085
+ }], onDocumentClick: [{
2086
+ type: HostListener,
2087
+ args: ['document:click', ['$event']]
1418
2088
  }] } });
1419
2089
 
1420
2090
  class PdmDialogComponent {
@@ -2235,26 +2905,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2235
2905
  type: Input
2236
2906
  }] } });
2237
2907
 
2238
- class PdmLabelComponent {
2239
- constructor() {
2240
- this.forId = '';
2241
- this.required = false;
2242
- this.className = '';
2243
- }
2244
- }
2245
- PdmLabelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2246
- PdmLabelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmLabelComponent, selector: "pdm-label", inputs: { forId: "forId", required: "required", className: "className" }, ngImport: i0, template: "<label\n [attr.for]=\"forId\"\n [ngClass]=\"['text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className]\"\n>\n <ng-content></ng-content>\n <span *ngIf=\"required\" class=\"ml-1 text-destructive\">*</span>\n</label>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2247
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmLabelComponent, decorators: [{
2248
- type: Component,
2249
- args: [{ selector: 'pdm-label', changeDetection: ChangeDetectionStrategy.OnPush, template: "<label\n [attr.for]=\"forId\"\n [ngClass]=\"['text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className]\"\n>\n <ng-content></ng-content>\n <span *ngIf=\"required\" class=\"ml-1 text-destructive\">*</span>\n</label>\n" }]
2250
- }], propDecorators: { forId: [{
2251
- type: Input
2252
- }], required: [{
2253
- type: Input
2254
- }], className: [{
2255
- type: Input
2256
- }] } });
2257
-
2258
2908
  class PdmMenubarComponent {
2259
2909
  constructor() {
2260
2910
  this.menus = [];