{
  "name": "date-picker",
  "type": "registry:component",
  "files": [
    {
      "name": "date-picker.component.ts",
      "content": "import { DatePipe } from '@angular/common';\nimport {\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  forwardRef,\n  inject,\n  input,\n  model,\n  output,\n  viewChild,\n  ViewEncapsulation,\n  type TemplateRef,\n} from '@angular/core';\nimport { NG_VALUE_ACCESSOR, type ControlValueAccessor } from '@angular/forms';\n\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { lucideCalendar } from '@ng-icons/lucide';\nimport type { ClassValue } from 'clsx';\n\nimport { ZardButtonComponent, type ZardButtonTypeVariants } from '@/shared/components/button';\nimport { ZardCalendarComponent } from '@/shared/components/calendar';\nimport type { ZardDatePickerSizeVariants } from '@/shared/components/date-picker/date-picker.variants';\nimport { ZardPopoverComponent, ZardPopoverDirective } from '@/shared/components/popover';\nimport { mergeClasses, noopFn } from '@/shared/utils/merge-classes';\n\n/**\n * Height overrides for date-picker sizes.\n *\n * These heights intentionally differ from button size variants to accommodate\n * the date-picker UI:\n * - default: h-9 (vs button h-8)\n * - lg: h-11 (vs button h-9)\n *\n * The `mergeClasses` utility (tailwind-merge) resolves class conflicts,\n * allowing these values to override the base button heights defined in\n * `ZardDatePickerSizeVariants`.\n */\nconst HEIGHT_BY_SIZE: Record<ZardDatePickerSizeVariants, string> = {\n  xs: 'h-7',\n  sm: 'h-8',\n  default: 'h-9',\n  lg: 'h-11',\n};\n\n@Component({\n  selector: 'z-date-picker, [z-date-picker]',\n  imports: [NgIcon, ZardButtonComponent, ZardCalendarComponent, ZardPopoverComponent, ZardPopoverDirective],\n  template: `\n    <button\n      z-button\n      type=\"button\"\n      [zType]=\"zType()\"\n      [zSize]=\"zSize()\"\n      [disabled]=\"disabled()\"\n      [class]=\"buttonClasses()\"\n      zPopover\n      #popoverDirective=\"zPopover\"\n      [zContent]=\"calendarTemplate\"\n      zTrigger=\"click\"\n      (zVisibleChange)=\"onPopoverVisibilityChange($event)\"\n      [attr.aria-expanded]=\"false\"\n      [attr.aria-haspopup]=\"true\"\n      aria-label=\"Choose date\"\n    >\n      <ng-icon name=\"lucideCalendar\" class=\"size-4!\" />\n      <span [class]=\"textClasses()\">\n        {{ displayText() }}\n      </span>\n    </button>\n\n    <ng-template #calendarTemplate>\n      <z-popover [class]=\"popoverClasses()\">\n        <z-calendar\n          #calendar\n          class=\"border-0\"\n          [value]=\"value()\"\n          [minDate]=\"minDate()\"\n          [maxDate]=\"maxDate()\"\n          [disabled]=\"disabled()\"\n          (dateChange)=\"onDateChange($event)\"\n        />\n      </z-popover>\n    </ng-template>\n  `,\n  providers: [\n    DatePipe,\n    {\n      provide: NG_VALUE_ACCESSOR,\n      useExisting: forwardRef(() => ZardDatePickerComponent),\n      multi: true,\n    },\n  ],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  viewProviders: [provideIcons({ lucideCalendar })],\n  host: {\n    '[class]': 'class()',\n  },\n  exportAs: 'zDatePicker',\n})\nexport class ZardDatePickerComponent implements ControlValueAccessor {\n  private readonly datePipe = inject(DatePipe);\n\n  readonly calendarTemplate = viewChild.required<TemplateRef<unknown>>('calendarTemplate');\n  readonly popoverDirective = viewChild.required<ZardPopoverDirective>('popoverDirective');\n  readonly calendar = viewChild.required<ZardCalendarComponent>('calendar');\n\n  readonly class = input<ClassValue>('');\n  readonly zType = input<ZardButtonTypeVariants>('outline');\n  readonly zSize = input<ZardDatePickerSizeVariants>('default');\n  readonly value = model<Date | null>(null);\n  readonly placeholder = input<string>('Pick a date');\n  readonly zFormat = input<string>('MMMM d, yyyy');\n  readonly minDate = input<Date | null>(null);\n  readonly maxDate = input<Date | null>(null);\n  readonly disabled = model<boolean>(false);\n\n  readonly dateChange = output<Date | null>();\n\n  private onChange: (value: Date | null) => void = noopFn;\n  private onTouched: () => void = noopFn;\n\n  protected readonly buttonClasses = computed(() => {\n    const hasValue = !!this.value();\n    const size = this.zSize();\n    const height = HEIGHT_BY_SIZE[size];\n    return mergeClasses(\n      'justify-start text-left font-normal',\n      !hasValue && 'text-muted-foreground',\n      height,\n      'min-w-[240px]',\n    );\n  });\n\n  protected readonly textClasses = computed(() => {\n    const hasValue = !!this.value();\n    return mergeClasses(!hasValue && 'text-muted-foreground');\n  });\n\n  protected readonly popoverClasses = computed(() => mergeClasses('w-auto p-0'));\n\n  protected readonly displayText = computed(() => {\n    const date = this.value();\n    if (!date) {\n      return this.placeholder();\n    }\n    return this.formatDate(date, this.zFormat());\n  });\n\n  protected onDateChange(date: Date | Date[]): void {\n    // Date picker always uses single mode, so we can safely cast\n    const singleDate = Array.isArray(date) ? (date[0] ?? null) : date;\n    this.value.set(singleDate);\n    this.onChange(singleDate);\n    this.onTouched();\n    this.dateChange.emit(singleDate);\n\n    this.popoverDirective().hide();\n  }\n\n  protected onPopoverVisibilityChange(visible: boolean): void {\n    if (visible) {\n      setTimeout(() => {\n        if (this.calendar()) {\n          this.calendar().resetNavigation();\n        }\n      });\n    }\n  }\n\n  private formatDate(date: Date, format: string): string {\n    return this.datePipe.transform(date, format) ?? '';\n  }\n\n  writeValue(value: Date | null): void {\n    this.value.set(value);\n  }\n\n  registerOnChange(fn: (value: Date | null) => void): void {\n    this.onChange = fn;\n  }\n\n  registerOnTouched(fn: () => void): void {\n    this.onTouched = fn;\n  }\n\n  setDisabledState(isDisabled: boolean): void {\n    this.disabled.set(isDisabled);\n  }\n}\n"
    },
    {
      "name": "date-picker.variants.ts",
      "content": "import { cva, type VariantProps } from 'class-variance-authority';\n\nexport const datePickerVariants = cva('', {\n  variants: {\n    zSize: {\n      xs: '',\n      sm: '',\n      default: '',\n      lg: '',\n    },\n    zType: {\n      default: '',\n      outline: '',\n      ghost: '',\n    },\n  },\n  defaultVariants: {\n    zSize: 'default',\n    zType: 'outline',\n  },\n});\n\nexport type ZardDatePickerSizeVariants = NonNullable<VariantProps<typeof datePickerVariants>['zSize']>;\n"
    },
    {
      "name": "index.ts",
      "content": "export * from './date-picker.component';\nexport * from './date-picker.variants';\n"
    }
  ],
  "registryDependencies": [
    "button",
    "calendar",
    "popover",
    "input"
  ],
  "demos": [
    {
      "name": "default.ts",
      "content": "import { ChangeDetectionStrategy, Component, signal } from '@angular/core';\n\nimport { ZardDatePickerComponent } from '../date-picker.component';\n\n@Component({\n  selector: 'zard-demo-date-picker-default',\n  imports: [ZardDatePickerComponent],\n  standalone: true,\n  template: `\n    <z-date-picker [value]=\"selectedDate()\" placeholder=\"Pick a date\" (dateChange)=\"onDateChange($event)\" />\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoDatePickerDefaultComponent {\n  readonly selectedDate = signal<Date | null>(null);\n\n  onDateChange(date: Date | null) {\n    this.selectedDate.set(date);\n    console.log('Selected date:', date);\n  }\n}\n"
    },
    {
      "name": "formats.ts",
      "content": "import { ChangeDetectionStrategy, Component } from '@angular/core';\n\nimport { ZardDatePickerComponent } from '../date-picker.component';\n\n@Component({\n  selector: 'z-date-picker-formats-demo',\n  imports: [ZardDatePickerComponent],\n  standalone: true,\n  template: `\n    <div class=\"flex flex-col gap-4\">\n      <div class=\"flex flex-col gap-2\">\n        <label class=\"text-sm font-medium\">Default Format (MMMM d, yyyy)</label>\n        <z-date-picker [value]=\"selectedDate\" (dateChange)=\"selectedDate = $event\" />\n      </div>\n\n      <div class=\"flex flex-col gap-2\">\n        <label class=\"text-sm font-medium\">US Format (MM/dd/yyyy)</label>\n        <z-date-picker [value]=\"selectedDate\" (dateChange)=\"selectedDate = $event\" zFormat=\"MM/dd/yyyy\" />\n      </div>\n\n      <div class=\"flex flex-col gap-2\">\n        <label class=\"text-sm font-medium\">European Format (dd-MM-yyyy)</label>\n        <z-date-picker [value]=\"selectedDate\" (dateChange)=\"selectedDate = $event\" zFormat=\"dd-MM-yyyy\" />\n      </div>\n\n      <div class=\"flex flex-col gap-2\">\n        <label class=\"text-sm font-medium\">Short Format (MMM d, yy)</label>\n        <z-date-picker [value]=\"selectedDate\" (dateChange)=\"selectedDate = $event\" zFormat=\"MMM d, yy\" />\n      </div>\n\n      <div class=\"flex flex-col gap-2\">\n        <label class=\"text-sm font-medium\">With Day Name (EEE, MMMM d)</label>\n        <z-date-picker [value]=\"selectedDate\" (dateChange)=\"selectedDate = $event\" zFormat=\"EEE, MMMM d\" />\n      </div>\n\n      <div class=\"flex flex-col gap-2\">\n        <label class=\"text-sm font-medium\">ISO Format (yyyy-MM-dd)</label>\n        <z-date-picker [value]=\"selectedDate\" (dateChange)=\"selectedDate = $event\" zFormat=\"yyyy-MM-dd\" />\n      </div>\n    </div>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDatePickerFormatsComponent {\n  selectedDate: Date | null = new Date();\n}\n\nexport default ZardDatePickerFormatsComponent;\n"
    },
    {
      "name": "sizes.ts",
      "content": "import { ChangeDetectionStrategy, Component, signal } from '@angular/core';\n\nimport { ZardDatePickerComponent } from '../date-picker.component';\n\n@Component({\n  selector: 'zard-demo-date-picker-sizes',\n  imports: [ZardDatePickerComponent],\n  standalone: true,\n  template: `\n    <div class=\"flex flex-col gap-4\">\n      <div class=\"space-y-2\">\n        <h4 class=\"text-sm font-medium\">Small</h4>\n        <z-date-picker\n          zSize=\"sm\"\n          [value]=\"selectedDateSm()\"\n          placeholder=\"Pick a date\"\n          (dateChange)=\"onDateChangeSm($event)\"\n        />\n      </div>\n\n      <div class=\"space-y-2\">\n        <h4 class=\"text-sm font-medium\">Default</h4>\n        <z-date-picker\n          zSize=\"default\"\n          [value]=\"selectedDateDefault()\"\n          placeholder=\"Pick a date\"\n          (dateChange)=\"onDateChangeDefault($event)\"\n        />\n      </div>\n\n      <div class=\"space-y-2\">\n        <h4 class=\"text-sm font-medium\">Large</h4>\n        <z-date-picker\n          zSize=\"lg\"\n          [value]=\"selectedDateLg()\"\n          placeholder=\"Pick a date\"\n          (dateChange)=\"onDateChangeLg($event)\"\n        />\n      </div>\n    </div>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ZardDemoDatePickerSizesComponent {\n  readonly selectedDateSm = signal<Date | null>(null);\n  readonly selectedDateDefault = signal<Date | null>(null);\n  readonly selectedDateLg = signal<Date | null>(null);\n\n  onDateChangeSm(date: Date | null) {\n    this.selectedDateSm.set(date);\n    console.log('Selected date (sm):', date);\n  }\n\n  onDateChangeDefault(date: Date | null) {\n    this.selectedDateDefault.set(date);\n    console.log('Selected date (default):', date);\n  }\n\n  onDateChangeLg(date: Date | null) {\n    this.selectedDateLg.set(date);\n    console.log('Selected date (lg):', date);\n  }\n}\n"
    }
  ]
}
