{
  "name": "dropdown",
  "type": "registry:component",
  "files": [
    {
      "name": "dropdown.component.ts",
      "content": "import { Overlay, OverlayModule, OverlayPositionBuilder, type OverlayRef } from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n  booleanAttribute,\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  ElementRef,\n  inject,\n  input,\n  type OnDestroy,\n  output,\n  PLATFORM_ID,\n  signal,\n  type TemplateRef,\n  viewChild,\n  ViewContainerRef,\n  ViewEncapsulation,\n} from '@angular/core';\n\nimport type { ClassValue } from 'clsx';\n\nimport { ZardIdDirective } from '@/shared/core/directives/id.directive';\nimport { mergeClasses } from '@/shared/utils/merge-classes';\n\nimport { dropdownContentVariants } from './dropdown.variants';\n\n@Component({\n  selector: 'z-dropdown-menu',\n  imports: [OverlayModule, ZardIdDirective],\n  template: `\n    <!-- Dropdown Trigger -->\n    <div\n      #triggerContainer\n      zardId=\"dropdown-trigger\"\n      #zId=\"zardId\"\n      [id]=\"zId.id()\"\n      data-slot=\"dropdown-menu-trigger\"\n      (click)=\"toggle()\"\n      (keydown.{enter,space}.prevent)=\"toggle()\"\n      [attr.aria-haspopup]=\"'menu'\"\n      [attr.aria-expanded]=\"isOpen()\"\n      [attr.aria-disabled]=\"isDisabled()\"\n      tabindex=\"0\"\n    >\n      <ng-content select=\"[dropdown-trigger]\" />\n    </div>\n\n    <!-- Template for overlay content -->\n    <ng-template #dropdownTemplate>\n      <div\n        [class]=\"contentClasses()\"\n        role=\"menu\"\n        data-slot=\"dropdown-menu-content\"\n        [attr.data-state]=\"'open'\"\n        (click)=\"onDropdownClick($event)\"\n        (keydown.{arrowdown,arrowup,enter,space,escape,home,end}.prevent)=\"onDropdownKeydown($event)\"\n        tabindex=\"-1\"\n      >\n        <ng-content />\n      </div>\n    </ng-template>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    class: 'relative inline-block text-left',\n    'data-slot': 'dropdown-menu',\n    '[attr.data-state]': 'isOpen() ? \"open\" : \"closed\"',\n    '(document:click)': 'onDocumentClick($event)',\n  },\n  exportAs: 'zDropdownMenu',\n})\nexport class ZardDropdownMenuComponent implements OnDestroy {\n  private elementRef = inject(ElementRef);\n  private overlay = inject(Overlay);\n  private overlayPositionBuilder = inject(OverlayPositionBuilder);\n  private viewContainerRef = inject(ViewContainerRef);\n  private platformId = inject(PLATFORM_ID);\n\n  readonly dropdownTemplate = viewChild.required<TemplateRef<unknown>>('dropdownTemplate');\n  readonly triggerContainer = viewChild.required<ElementRef<HTMLElement>>('triggerContainer');\n\n  private overlayRef?: OverlayRef;\n  private portal?: TemplatePortal;\n\n  readonly class = input<ClassValue>('');\n  readonly disabled = input(false, { transform: booleanAttribute });\n  readonly zDisabled = input<boolean | undefined, unknown>(undefined, {\n    alias: 'zDisabled',\n    transform: value => (value === undefined ? undefined : booleanAttribute(value)),\n  });\n\n  readonly openChange = output<boolean>();\n\n  readonly isOpen = signal(false);\n  readonly focusedIndex = signal<number>(-1);\n\n  protected readonly isDisabled = computed(() => this.zDisabled() ?? this.disabled());\n  protected readonly contentClasses = computed(() => mergeClasses(dropdownContentVariants(), this.class()));\n\n  ngOnDestroy() {\n    this.destroyOverlay();\n  }\n\n  onDocumentClick(event: Event) {\n    if (!this.elementRef.nativeElement.contains(event.target as Node)) {\n      this.close();\n    }\n  }\n\n  onDropdownKeydown(e: Event) {\n    const items = this.getDropdownItems();\n    const { key } = e as KeyboardEvent;\n\n    switch (key) {\n      case 'ArrowDown':\n        this.navigateItems(1, items);\n        break;\n      case 'ArrowUp':\n        this.navigateItems(-1, items);\n        break;\n      case 'Enter':\n      case ' ':\n        this.selectFocusedItem(items);\n        break;\n      case 'Escape':\n        this.close();\n        this.focusTrigger();\n        break;\n      case 'Home':\n        this.focusFirstItem(items);\n        break;\n      case 'End':\n        this.focusLastItem(items);\n        break;\n    }\n  }\n\n  onDropdownClick(event: Event) {\n    const target = event.target as HTMLElement;\n    const item = target.closest<HTMLElement>(\n      'z-dropdown-menu-item, [z-dropdown-menu-item], z-dropdown-menu-checkbox-item, [z-dropdown-menu-checkbox-item], z-dropdown-menu-radio-item, [z-dropdown-menu-radio-item]',\n    );\n\n    if (!item || item.dataset['disabled'] !== undefined) {\n      return;\n    }\n\n    setTimeout(() => {\n      this.close();\n      this.focusTrigger();\n    }, 0);\n  }\n\n  toggle() {\n    if (this.isDisabled()) {\n      return;\n    }\n    if (this.isOpen()) {\n      this.close();\n    } else {\n      this.open();\n    }\n  }\n\n  open() {\n    if (this.isOpen()) {\n      return;\n    }\n\n    if (!this.overlayRef) {\n      this.createOverlay();\n    }\n\n    if (!this.overlayRef) {\n      return;\n    }\n\n    this.portal = new TemplatePortal(this.dropdownTemplate(), this.viewContainerRef);\n    this.overlayRef.attach(this.portal);\n    this.isOpen.set(true);\n    this.openChange.emit(true);\n\n    setTimeout(() => {\n      this.focusDropdown();\n    }, 0);\n  }\n\n  close() {\n    if (this.overlayRef?.hasAttached()) {\n      this.overlayRef.detach();\n    }\n    this.isOpen.set(false);\n    this.focusedIndex.set(-1);\n    this.openChange.emit(false);\n  }\n\n  private createOverlay() {\n    if (this.overlayRef) {\n      return;\n    }\n\n    if (isPlatformBrowser(this.platformId)) {\n      try {\n        const positionStrategy = this.overlayPositionBuilder\n          .flexibleConnectedTo(this.elementRef)\n          .withPositions([\n            {\n              originX: 'start',\n              originY: 'bottom',\n              overlayX: 'start',\n              overlayY: 'top',\n              offsetY: 4,\n            },\n            {\n              originX: 'start',\n              originY: 'top',\n              overlayX: 'start',\n              overlayY: 'bottom',\n              offsetY: -4,\n            },\n          ])\n          .withPush(false);\n\n        this.overlayRef = this.overlay.create({\n          positionStrategy,\n          hasBackdrop: false,\n          scrollStrategy: this.overlay.scrollStrategies.reposition(),\n          minWidth: 200,\n          maxHeight: 400,\n        });\n      } catch (error) {\n        console.error('Error creating overlay:', error);\n      }\n    }\n  }\n\n  private destroyOverlay() {\n    if (this.overlayRef) {\n      this.overlayRef.dispose();\n      this.overlayRef = undefined;\n    }\n  }\n\n  private getDropdownItems(): HTMLElement[] {\n    if (!this.overlayRef?.hasAttached()) {\n      return [];\n    }\n    const dropdownElement = this.overlayRef.overlayElement;\n    return Array.from(\n      dropdownElement.querySelectorAll<HTMLElement>(\n        'z-dropdown-menu-item, [z-dropdown-menu-item], z-dropdown-menu-checkbox-item, [z-dropdown-menu-checkbox-item], z-dropdown-menu-radio-item, [z-dropdown-menu-radio-item]',\n      ),\n    ).filter(item => item.dataset['disabled'] === undefined);\n  }\n\n  private navigateItems(direction: number, items: HTMLElement[]) {\n    if (items.length === 0) {\n      return;\n    }\n\n    const currentIndex = this.focusedIndex();\n    let nextIndex: number;\n\n    if (currentIndex === -1) {\n      nextIndex = direction > 0 ? 0 : items.length - 1;\n    } else {\n      nextIndex = currentIndex + direction;\n      if (nextIndex < 0) {\n        nextIndex = items.length - 1;\n      } else if (nextIndex >= items.length) {\n        nextIndex = 0;\n      }\n    }\n\n    this.focusedIndex.set(nextIndex);\n    this.updateItemFocus(items, nextIndex);\n  }\n\n  private selectFocusedItem(items: HTMLElement[]) {\n    const currentIndex = this.focusedIndex();\n    if (currentIndex >= 0 && currentIndex < items.length) {\n      const item = items[currentIndex];\n      item.click();\n    }\n  }\n\n  private focusFirstItem(items: HTMLElement[]) {\n    if (items.length > 0) {\n      this.focusedIndex.set(0);\n      this.updateItemFocus(items, 0);\n    }\n  }\n\n  private focusLastItem(items: HTMLElement[]) {\n    if (items.length > 0) {\n      const lastIndex = items.length - 1;\n      this.focusedIndex.set(lastIndex);\n      this.updateItemFocus(items, lastIndex);\n    }\n  }\n\n  private updateItemFocus(items: HTMLElement[], focusedIndex: number) {\n    items.forEach((item, index) => {\n      if (index === focusedIndex) {\n        item.focus();\n        item.setAttribute('data-highlighted', '');\n      } else {\n        item.removeAttribute('data-highlighted');\n      }\n    });\n  }\n\n  private focusDropdown() {\n    if (this.overlayRef?.hasAttached()) {\n      const dropdownElement = this.overlayRef.overlayElement.querySelector('[role=\"menu\"]') as HTMLElement;\n      if (dropdownElement) {\n        dropdownElement.focus();\n      }\n    }\n  }\n\n  private focusTrigger() {\n    this.triggerContainer().nativeElement.focus();\n  }\n}\n"
    },
    {
      "name": "dropdown-item.component.ts",
      "content": "import {\n  booleanAttribute,\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  inject,\n  input,\n  ViewEncapsulation,\n} from '@angular/core';\n\nimport type { ClassValue } from 'clsx';\n\nimport { mergeClasses } from '@/shared/utils/merge-classes';\n\nimport { ZardDropdownService } from './dropdown.service';\nimport { dropdownItemVariants, type ZardDropdownItemTypeVariants } from './dropdown.variants';\n\n@Component({\n  selector: 'z-dropdown-menu-item, [z-dropdown-menu-item]',\n  template: `\n    <ng-content />\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    '[class]': 'classes()',\n    'data-slot': 'dropdown-menu-item',\n    '[attr.data-disabled]': 'isDisabled() || null',\n    '[attr.data-variant]': 'itemVariant()',\n    '[attr.data-inset]': 'isInset() || null',\n    '[attr.aria-disabled]': 'isDisabled()',\n    '(click.prevent-with-stop)': 'onClick()',\n    role: 'menuitem',\n    tabindex: '-1',\n  },\n  exportAs: 'zDropdownMenuItem',\n})\nexport class ZardDropdownMenuItemComponent {\n  private readonly dropdownService = inject(ZardDropdownService);\n\n  readonly variant = input<ZardDropdownItemTypeVariants>('default');\n  readonly zType = input<ZardDropdownItemTypeVariants | undefined>(undefined, { alias: 'zType' });\n  readonly zVariant = input<ZardDropdownItemTypeVariants | undefined>(undefined, { alias: 'zVariant' });\n  readonly inset = input(false, { transform: booleanAttribute });\n  readonly zInset = input<boolean | undefined, unknown>(undefined, {\n    alias: 'zInset',\n    transform: value => (value === undefined ? undefined : booleanAttribute(value)),\n  });\n\n  readonly disabled = input(false, { transform: booleanAttribute });\n  readonly zDisabled = input<boolean | undefined, unknown>(undefined, {\n    alias: 'zDisabled',\n    transform: value => (value === undefined ? undefined : booleanAttribute(value)),\n  });\n\n  readonly class = input<ClassValue>('');\n\n  onClick() {\n    if (this.isDisabled()) {\n      return;\n    }\n\n    setTimeout(() => {\n      this.dropdownService.closeAndFocusTrigger();\n    }, 0);\n  }\n\n  protected readonly isDisabled = computed(() => this.zDisabled() ?? this.disabled());\n  protected readonly itemVariant = computed(() => this.zType() ?? this.zVariant() ?? this.variant());\n  protected readonly isInset = computed(() => this.zInset() ?? this.inset());\n\n  protected readonly classes = computed(() =>\n    mergeClasses(\n      dropdownItemVariants({\n        variant: this.itemVariant(),\n        inset: this.isInset(),\n      }),\n      this.class(),\n    ),\n  );\n}\n"
    },
    {
      "name": "dropdown-menu-content.component.ts",
      "content": "import {\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  input,\n  type TemplateRef,\n  viewChild,\n  ViewEncapsulation,\n} from '@angular/core';\n\nimport type { ClassValue } from 'clsx';\n\nimport { dropdownContentVariants } from '@/shared/components/dropdown/dropdown.variants';\nimport { mergeClasses } from '@/shared/utils/merge-classes';\n\n@Component({\n  selector: 'z-dropdown-menu-content',\n  template: `\n    <ng-template #contentTemplate>\n      <div\n        [class]=\"contentClasses()\"\n        role=\"menu\"\n        data-slot=\"dropdown-menu-content\"\n        data-state=\"open\"\n        tabindex=\"-1\"\n        aria-orientation=\"vertical\"\n      >\n        <ng-content />\n      </div>\n    </ng-template>\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    '[style.display]': '\"none\"',\n  },\n  exportAs: 'zDropdownMenuContent',\n})\nexport class ZardDropdownMenuContentComponent {\n  readonly contentTemplate = viewChild.required<TemplateRef<unknown>>('contentTemplate');\n\n  readonly class = input<ClassValue>('');\n\n  protected readonly contentClasses = computed(() => mergeClasses(dropdownContentVariants(), this.class()));\n}\n"
    },
    {
      "name": "dropdown-primitives.component.ts",
      "content": "import {\n  booleanAttribute,\n  ChangeDetectionStrategy,\n  Component,\n  computed,\n  forwardRef,\n  inject,\n  InjectionToken,\n  input,\n  model,\n  ViewEncapsulation,\n} from '@angular/core';\n\nimport type { ClassValue } from 'clsx';\n\nimport { mergeClasses } from '@/shared/utils/merge-classes';\n\nimport { ZardDropdownService } from './dropdown.service';\nimport { dropdownItemVariants, type ZardDropdownItemTypeVariants } from './dropdown.variants';\n\ninterface ZardDropdownRadioGroup {\n  zValue(): string | undefined;\n  select(value: string): void;\n}\n\nconst ZARD_DROPDOWN_RADIO_GROUP = new InjectionToken<ZardDropdownRadioGroup>('ZARD_DROPDOWN_RADIO_GROUP');\n\nconst optionalBooleanAttribute = (value: unknown) => (value === undefined ? undefined : booleanAttribute(value));\n\n@Component({\n  selector: 'z-dropdown-menu-group, [z-dropdown-menu-group]',\n  template: `\n    <ng-content />\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    role: 'group',\n    'data-slot': 'dropdown-menu-group',\n    '[class]': 'classes()',\n  },\n  exportAs: 'zDropdownMenuGroup',\n})\nexport class ZardDropdownMenuGroupComponent {\n  readonly class = input<ClassValue>('');\n\n  protected readonly classes = computed(() => mergeClasses(this.class()));\n}\n\n@Component({\n  selector: 'z-dropdown-menu-separator, [z-dropdown-menu-separator]',\n  template: ``,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    role: 'separator',\n    'aria-orientation': 'horizontal',\n    'data-slot': 'dropdown-menu-separator',\n    '[class]': 'classes()',\n  },\n  exportAs: 'zDropdownMenuSeparator',\n})\nexport class ZardDropdownMenuSeparatorComponent {\n  readonly class = input<ClassValue>('');\n\n  protected readonly classes = computed(() => mergeClasses('bg-border -mx-1 my-1 h-px', this.class()));\n}\n\n@Component({\n  selector: 'z-dropdown-menu-shortcut, [z-dropdown-menu-shortcut]',\n  template: `\n    <ng-content />\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    'aria-hidden': 'true',\n    'data-slot': 'dropdown-menu-shortcut',\n    '[class]': 'classes()',\n  },\n  exportAs: 'zDropdownMenuShortcut',\n})\nexport class ZardDropdownMenuShortcutComponent {\n  readonly class = input<ClassValue>('');\n\n  protected readonly classes = computed(() =>\n    mergeClasses('text-muted-foreground ml-auto text-xs tracking-widest', this.class()),\n  );\n}\n\n@Component({\n  selector: 'z-dropdown-menu-checkbox-item, [z-dropdown-menu-checkbox-item]',\n  template: `\n    <span class=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n      @if (zChecked()) {\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" class=\"size-4\">\n          <path d=\"M20 6 9 17l-5-5\" />\n        </svg>\n      }\n    </span>\n    <ng-content />\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    '[class]': 'classes()',\n    role: 'menuitemcheckbox',\n    tabindex: '-1',\n    'data-slot': 'dropdown-menu-checkbox-item',\n    '[attr.aria-checked]': 'zChecked()',\n    '[attr.aria-disabled]': 'isDisabled()',\n    '[attr.data-state]': 'zChecked() ? \"checked\" : \"unchecked\"',\n    '[attr.data-disabled]': 'isDisabled() || null',\n    '[attr.data-variant]': 'itemVariant()',\n    '(click.prevent-with-stop)': 'onClick()',\n  },\n  exportAs: 'zDropdownMenuCheckboxItem',\n})\nexport class ZardDropdownMenuCheckboxItemComponent {\n  private readonly dropdownService = inject(ZardDropdownService);\n\n  readonly zChecked = model(false);\n  readonly disabled = input(false, { transform: booleanAttribute });\n  readonly zDisabled = input<boolean | undefined, unknown>(undefined, {\n    alias: 'zDisabled',\n    transform: optionalBooleanAttribute,\n  });\n\n  readonly variant = input<ZardDropdownItemTypeVariants>('default');\n  readonly zType = input<ZardDropdownItemTypeVariants | undefined>(undefined, { alias: 'zType' });\n  readonly zVariant = input<ZardDropdownItemTypeVariants | undefined>(undefined, { alias: 'zVariant' });\n  readonly class = input<ClassValue>('');\n\n  protected readonly isDisabled = computed(() => this.zDisabled() ?? this.disabled());\n  protected readonly itemVariant = computed(() => this.zType() ?? this.zVariant() ?? this.variant());\n  protected readonly classes = computed(() =>\n    mergeClasses(dropdownItemVariants({ variant: this.itemVariant(), inset: true }), this.class()),\n  );\n\n  protected onClick() {\n    if (this.isDisabled()) {\n      return;\n    }\n\n    this.zChecked.set(!this.zChecked());\n    setTimeout(() => this.dropdownService.closeAndFocusTrigger(), 0);\n  }\n}\n\n@Component({\n  selector: 'z-dropdown-menu-radio-group, [z-dropdown-menu-radio-group]',\n  template: `\n    <ng-content />\n  `,\n  providers: [\n    { provide: ZARD_DROPDOWN_RADIO_GROUP, useExisting: forwardRef(() => ZardDropdownMenuRadioGroupComponent) },\n  ],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    role: 'group',\n    'data-slot': 'dropdown-menu-radio-group',\n    '[class]': 'classes()',\n  },\n  exportAs: 'zDropdownMenuRadioGroup',\n})\nexport class ZardDropdownMenuRadioGroupComponent implements ZardDropdownRadioGroup {\n  readonly zValue = model<string | undefined>(undefined);\n  readonly class = input<ClassValue>('');\n\n  protected readonly classes = computed(() => mergeClasses(this.class()));\n\n  select(value: string) {\n    this.zValue.set(value);\n  }\n}\n\n@Component({\n  selector: 'z-dropdown-menu-radio-item, [z-dropdown-menu-radio-item]',\n  template: `\n    <span class=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n      @if (isChecked()) {\n        <span class=\"size-2 rounded-full bg-current\"></span>\n      }\n    </span>\n    <ng-content />\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  encapsulation: ViewEncapsulation.None,\n  host: {\n    '[class]': 'classes()',\n    role: 'menuitemradio',\n    tabindex: '-1',\n    'data-slot': 'dropdown-menu-radio-item',\n    '[attr.aria-checked]': 'isChecked()',\n    '[attr.aria-disabled]': 'isDisabled()',\n    '[attr.data-state]': 'isChecked() ? \"checked\" : \"unchecked\"',\n    '[attr.data-disabled]': 'isDisabled() || null',\n    '[attr.data-variant]': 'itemVariant()',\n    '(click.prevent-with-stop)': 'onClick()',\n  },\n})\nexport class ZardDropdownMenuRadioItemComponent {\n  private readonly dropdownService = inject(ZardDropdownService);\n  private readonly radioGroup = inject(ZARD_DROPDOWN_RADIO_GROUP, { optional: true });\n\n  readonly zValue = input.required<string>();\n  readonly disabled = input(false, { transform: booleanAttribute });\n  readonly zDisabled = input<boolean | undefined, unknown>(undefined, {\n    alias: 'zDisabled',\n    transform: optionalBooleanAttribute,\n  });\n\n  readonly variant = input<ZardDropdownItemTypeVariants>('default');\n  readonly zType = input<ZardDropdownItemTypeVariants | undefined>(undefined, { alias: 'zType' });\n  readonly zVariant = input<ZardDropdownItemTypeVariants | undefined>(undefined, { alias: 'zVariant' });\n  readonly class = input<ClassValue>('');\n\n  protected readonly isDisabled = computed(() => this.zDisabled() ?? this.disabled());\n  protected readonly itemVariant = computed(() => this.zType() ?? this.zVariant() ?? this.variant());\n  protected readonly isChecked = computed(() => this.radioGroup?.zValue() === this.zValue());\n  protected readonly classes = computed(() =>\n    mergeClasses(dropdownItemVariants({ variant: this.itemVariant(), inset: true }), this.class()),\n  );\n\n  protected onClick() {\n    if (this.isDisabled()) {\n      return;\n    }\n\n    this.radioGroup?.select(this.zValue());\n    setTimeout(() => this.dropdownService.closeAndFocusTrigger(), 0);\n  }\n}\n"
    },
    {
      "name": "dropdown-trigger.directive.ts",
      "content": "import {\n  booleanAttribute,\n  computed,\n  Directive,\n  ElementRef,\n  inject,\n  input,\n  type OnInit,\n  ViewContainerRef,\n} from '@angular/core';\n\nimport type { ZardDropdownMenuContentComponent } from './dropdown-menu-content.component';\nimport { ZardDropdownService } from './dropdown.service';\n\n@Directive({\n  selector: '[z-dropdown], [zDropdown]',\n  host: {\n    'data-slot': 'dropdown-menu-trigger',\n    '[attr.tabindex]': '0',\n    '[attr.role]': '\"button\"',\n    '[attr.aria-haspopup]': '\"menu\"',\n    '[attr.aria-expanded]': 'isThisDropdownOpen()',\n    '[attr.aria-disabled]': 'zDisabled()',\n    '[attr.data-state]': 'isThisDropdownOpen() ? \"open\" : \"closed\"',\n    '[attr.data-disabled]': 'zDisabled() || null',\n    '(click.prevent-with-stop)': 'onClick()',\n    '(mouseenter)': 'onHoverToggle($event)',\n    '(mouseleave)': 'onHoverToggle($event)',\n    '(keydown.{enter,space}.prevent-with-stop)': 'toggleDropdown()',\n    '(keydown.arrowdown.prevent)': 'openDropdown()',\n  },\n  exportAs: 'zDropdown',\n})\nexport class ZardDropdownDirective implements OnInit {\n  private readonly elementRef = inject(ElementRef);\n  private readonly viewContainerRef = inject(ViewContainerRef);\n  protected readonly dropdownService = inject(ZardDropdownService);\n\n  protected readonly isThisDropdownOpen = computed(\n    () => this.dropdownService.isOpen() && this.dropdownService.getTriggerElement() === this.elementRef,\n  );\n\n  readonly zDropdownMenu = input<ZardDropdownMenuContentComponent>();\n  readonly zTrigger = input<'click' | 'hover'>('click');\n  readonly zDisabled = input(false, { transform: booleanAttribute });\n\n  ngOnInit() {\n    // Ensure button has proper accessibility attributes\n    const element = this.elementRef.nativeElement;\n    if (!element.hasAttribute('aria-label') && !element.hasAttribute('aria-labelledby')) {\n      const label = element.textContent?.trim();\n      element.setAttribute('aria-label', label?.length ? label : 'Open menu');\n    }\n  }\n\n  protected onClick() {\n    if (this.zTrigger() !== 'click') {\n      return;\n    }\n\n    this.toggleDropdown();\n  }\n\n  protected onHoverToggle(event: MouseEvent) {\n    if (this.zTrigger() !== 'hover' || this.zDisabled()) {\n      return;\n    }\n\n    if (event.type === 'mouseenter') {\n      this.openDropdown();\n    } else if (event.type === 'mouseleave') {\n      this.closeDropdown();\n    }\n  }\n\n  protected toggleDropdown() {\n    if (this.zDisabled()) {\n      return;\n    }\n\n    const menuContent = this.zDropdownMenu();\n    if (menuContent) {\n      this.dropdownService.toggle(this.elementRef, menuContent.contentTemplate(), this.viewContainerRef);\n    }\n  }\n\n  protected openDropdown() {\n    if (this.zDisabled()) {\n      return;\n    }\n\n    const menuContent = this.zDropdownMenu();\n    if (menuContent && !this.dropdownService.isOpen()) {\n      this.dropdownService.toggle(this.elementRef, menuContent.contentTemplate(), this.viewContainerRef);\n    }\n  }\n\n  protected closeDropdown() {\n    this.dropdownService.close();\n  }\n}\n"
    },
    {
      "name": "dropdown.imports.ts",
      "content": "import { ZardDropdownMenuItemComponent } from '@/shared/components/dropdown/dropdown-item.component';\nimport { ZardDropdownMenuContentComponent } from '@/shared/components/dropdown/dropdown-menu-content.component';\nimport {\n  ZardDropdownMenuCheckboxItemComponent,\n  ZardDropdownMenuGroupComponent,\n  ZardDropdownMenuRadioGroupComponent,\n  ZardDropdownMenuRadioItemComponent,\n  ZardDropdownMenuSeparatorComponent,\n  ZardDropdownMenuShortcutComponent,\n} from '@/shared/components/dropdown/dropdown-primitives.component';\nimport { ZardDropdownDirective } from '@/shared/components/dropdown/dropdown-trigger.directive';\nimport { ZardDropdownMenuComponent } from '@/shared/components/dropdown/dropdown.component';\nimport { ZardMenuLabelComponent } from '@/shared/components/menu/menu-label.component';\nimport { ZardMenuShortcutComponent } from '@/shared/components/menu/menu-shortcut.component';\n\nexport const ZardDropdownImports = [\n  ZardDropdownMenuComponent,\n  ZardDropdownMenuItemComponent,\n  ZardDropdownMenuContentComponent,\n  ZardDropdownMenuGroupComponent,\n  ZardDropdownMenuSeparatorComponent,\n  ZardDropdownMenuShortcutComponent,\n  ZardDropdownMenuCheckboxItemComponent,\n  ZardDropdownMenuRadioGroupComponent,\n  ZardDropdownMenuRadioItemComponent,\n  ZardMenuLabelComponent,\n  ZardMenuShortcutComponent,\n  ZardDropdownDirective,\n] as const;\n"
    },
    {
      "name": "dropdown.service.ts",
      "content": "import { Overlay, OverlayPositionBuilder, type OverlayRef } from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n  type ElementRef,\n  inject,\n  Injectable,\n  PLATFORM_ID,\n  type Renderer2,\n  RendererFactory2,\n  signal,\n  type TemplateRef,\n  type ViewContainerRef,\n} from '@angular/core';\n\nimport { filter, type Subscription } from 'rxjs';\n\nimport { noopFn } from '@/shared/utils/merge-classes';\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class ZardDropdownService {\n  private readonly overlay = inject(Overlay);\n  private readonly overlayPositionBuilder = inject(OverlayPositionBuilder);\n  private readonly platformId = inject(PLATFORM_ID);\n  private readonly rendererFactory = inject(RendererFactory2);\n\n  private overlayRef?: OverlayRef;\n  private portal?: TemplatePortal;\n  private triggerElement?: ElementRef;\n  private renderer!: Renderer2;\n  private readonly focusedIndex = signal<number>(-1);\n  private outsideClickSubscription!: Subscription;\n  private unlisten: () => void = noopFn;\n\n  readonly isOpen = signal(false);\n\n  constructor() {\n    this.renderer = this.rendererFactory.createRenderer(null, null);\n  }\n\n  toggle(triggerElement: ElementRef, template: TemplateRef<unknown>, viewContainerRef: ViewContainerRef) {\n    if (this.isOpen()) {\n      this.close();\n    } else {\n      this.open(triggerElement, template, viewContainerRef);\n    }\n  }\n\n  private open(triggerElement: ElementRef, template: TemplateRef<unknown>, viewContainerRef: ViewContainerRef) {\n    if (this.isOpen()) {\n      this.close();\n    }\n\n    this.triggerElement = triggerElement;\n    this.createOverlay(triggerElement);\n\n    if (!this.overlayRef) {\n      return;\n    }\n\n    this.portal = new TemplatePortal(template, viewContainerRef);\n    this.overlayRef.attach(this.portal);\n\n    // Setup keyboard navigation\n    setTimeout(() => {\n      this.setupKeyboardNavigation();\n    }, 0);\n\n    // Close on outside click\n    this.outsideClickSubscription = this.overlayRef\n      .outsidePointerEvents()\n      .pipe(filter(event => !triggerElement.nativeElement.contains(event.target)))\n      .subscribe(() => {\n        this.close();\n      });\n    this.isOpen.set(true);\n  }\n\n  getTriggerElement(): ElementRef | undefined {\n    return this.triggerElement;\n  }\n\n  close() {\n    if (this.overlayRef?.hasAttached()) {\n      this.overlayRef.detach();\n    }\n    this.focusedIndex.set(-1);\n    this.unlisten();\n    this.destroyOverlay();\n    this.isOpen.set(false);\n    this.triggerElement = undefined;\n  }\n\n  closeAndReturnTrigger(): ElementRef | undefined {\n    const trigger = this.triggerElement;\n    this.close();\n    return trigger;\n  }\n\n  closeAndFocusTrigger() {\n    const trigger = this.closeAndReturnTrigger();\n    trigger?.nativeElement.focus();\n  }\n\n  private createOverlay(triggerElement: ElementRef) {\n    if (this.overlayRef) {\n      this.destroyOverlay();\n    }\n\n    const positionStrategy = this.overlayPositionBuilder\n      .flexibleConnectedTo(triggerElement)\n      .withPositions([\n        {\n          originX: 'start',\n          originY: 'bottom',\n          overlayX: 'start',\n          overlayY: 'top',\n          offsetY: 4,\n        },\n        {\n          originX: 'start',\n          originY: 'top',\n          overlayX: 'start',\n          overlayY: 'bottom',\n          offsetY: -4,\n        },\n      ])\n      .withPush(false);\n\n    this.overlayRef = this.overlay.create({\n      positionStrategy,\n      hasBackdrop: false,\n      scrollStrategy: this.overlay.scrollStrategies.reposition(),\n      minWidth: 200,\n      maxHeight: 400,\n    });\n  }\n\n  private destroyOverlay() {\n    this.overlayRef?.dispose();\n    this.overlayRef = undefined;\n    this.outsideClickSubscription?.unsubscribe();\n  }\n\n  private setupKeyboardNavigation() {\n    if (!this.overlayRef?.hasAttached() || !isPlatformBrowser(this.platformId)) {\n      return;\n    }\n\n    const dropdownElement = this.overlayRef.overlayElement.querySelector('[role=\"menu\"]') as HTMLElement;\n    if (!dropdownElement) {\n      return;\n    }\n\n    this.unlisten = this.renderer.listen(\n      dropdownElement,\n      'keydown.{arrowdown,arrowup,enter,space,escape,home,end}.prevent',\n      (event: KeyboardEvent) => {\n        const items = this.getDropdownItems();\n\n        switch (event.key) {\n          case 'ArrowDown':\n            this.navigateItems(1, items);\n            break;\n          case 'ArrowUp':\n            this.navigateItems(-1, items);\n            break;\n          case 'Enter':\n          case ' ':\n            this.selectFocusedItem(items);\n            break;\n          case 'Escape': {\n            const triggerToFocus = this.closeAndReturnTrigger();\n            triggerToFocus?.nativeElement.focus();\n            break;\n          }\n          case 'Home':\n            this.focusItemAtIndex(items, 0);\n            break;\n          case 'End':\n            this.focusItemAtIndex(items, items.length - 1);\n            break;\n        }\n      },\n    );\n\n    // Focus dropdown container\n    dropdownElement.focus();\n  }\n\n  private getDropdownItems(): HTMLElement[] {\n    if (!this.overlayRef?.hasAttached()) {\n      return [];\n    }\n    const dropdownElement = this.overlayRef.overlayElement;\n    return Array.from(\n      dropdownElement.querySelectorAll<HTMLElement>(\n        'z-dropdown-menu-item, [z-dropdown-menu-item], z-dropdown-menu-checkbox-item, [z-dropdown-menu-checkbox-item], z-dropdown-menu-radio-item, [z-dropdown-menu-radio-item]',\n      ),\n    ).filter(item => item.dataset['disabled'] === undefined);\n  }\n\n  private navigateItems(direction: number, items: HTMLElement[]) {\n    if (items.length === 0) {\n      return;\n    }\n\n    const currentIndex = this.focusedIndex();\n    let nextIndex: number;\n\n    if (currentIndex === -1) {\n      // No item focused yet — start from first or last depending on direction\n      nextIndex = direction > 0 ? 0 : items.length - 1;\n    } else {\n      nextIndex = currentIndex + direction;\n      if (nextIndex < 0) {\n        nextIndex = items.length - 1;\n      } else if (nextIndex >= items.length) {\n        nextIndex = 0;\n      }\n    }\n\n    this.focusItemAtIndex(items, nextIndex);\n  }\n\n  private focusItemAtIndex(items: HTMLElement[], index: number) {\n    if (index >= 0 && index < items.length) {\n      this.focusedIndex.set(index);\n      this.updateItemFocus(items, index);\n    }\n  }\n\n  private focusFirstItem() {\n    const items = this.getDropdownItems();\n    if (items.length > 0) {\n      this.focusItemAtIndex(items, 0);\n    }\n  }\n\n  private selectFocusedItem(items: HTMLElement[]) {\n    const currentIndex = this.focusedIndex();\n    if (currentIndex >= 0 && currentIndex < items.length) {\n      const item = items[currentIndex];\n      item.click();\n    }\n  }\n\n  private updateItemFocus(items: HTMLElement[], focusedIndex: number) {\n    for (let index = 0; index < items.length; index++) {\n      const item = items[index];\n      if (index === focusedIndex) {\n        item.focus();\n        item.dataset['highlighted'] = '';\n      } else {\n        delete item.dataset['highlighted'];\n      }\n    }\n  }\n}\n"
    },
    {
      "name": "dropdown.variants.ts",
      "content": "import { cva, type VariantProps } from 'class-variance-authority';\n\nexport const dropdownContentVariants = cva([\n  'z-50 min-w-32 max-h-96 overflow-x-hidden overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground',\n  'shadow-md outline-none animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n]);\n\nexport const dropdownItemVariants = cva(\n  'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-disabled:cursor-not-allowed [&_svg:not([class*=size-])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0',\n  {\n    variants: {\n      variant: {\n        default: '',\n        destructive:\n          'text-destructive hover:bg-destructive/10 focus:bg-destructive/10 dark:hover:bg-destructive/20 dark:focus:bg-destructive/20 focus:text-destructive',\n      },\n      inset: {\n        true: 'pl-8',\n        false: '',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      inset: false,\n    },\n  },\n);\n\nexport type ZardDropdownItemVariants = VariantProps<typeof dropdownItemVariants>;\nexport type ZardDropdownItemTypeVariants = NonNullable<ZardDropdownItemVariants['variant']>;\n"
    },
    {
      "name": "index.ts",
      "content": "export * from './dropdown.component';\nexport * from './dropdown-item.component';\nexport * from './dropdown-menu-content.component';\nexport * from './dropdown-primitives.component';\nexport * from './dropdown-trigger.directive';\nexport * from './dropdown.service';\nexport * from './dropdown.imports';\nexport * from './dropdown.variants';\n"
    }
  ],
  "demos": [
    {
      "name": "avatar.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardAvatarComponent } from '@/shared/components/avatar/avatar.component';\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-avatar-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent, ZardAvatarComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"ghost\" class=\"size-10 rounded-full p-0\" z-dropdown [zDropdownMenu]=\"menu\">\n      <z-avatar zSrc=\"/images/avatar/imgs/avatar_image.jpg\" zFallback=\"ZA\" zAlt=\"User avatar\" />\n    </button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-label>\n        <div class=\"flex flex-col space-y-1\">\n          <p class=\"text-sm leading-none font-medium\">Zard User</p>\n          <p class=\"text-muted-foreground text-xs leading-none\">user@zardui.com</p>\n        </div>\n      </z-dropdown-menu-label>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item (click)=\"log('Profile')\">Profile</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Billing')\">Billing</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Settings')\">Settings</z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item (click)=\"log('Log out')\">Log out</z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownAvatarDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    },
    {
      "name": "checkboxes.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-checkboxes-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">View options</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-checkbox-item [(zChecked)]=\"statusBar\">Status Bar</z-dropdown-menu-checkbox-item>\n      <z-dropdown-menu-checkbox-item [(zChecked)]=\"activityBar\">Activity Bar</z-dropdown-menu-checkbox-item>\n      <z-dropdown-menu-checkbox-item [(zChecked)]=\"panel\">Panel</z-dropdown-menu-checkbox-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownCheckboxesDemoComponent {\n  statusBar = true;\n  activityBar = false;\n  panel = false;\n}\n"
    },
    {
      "name": "complex.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-complex-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Open</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-label>My Account</z-dropdown-menu-label>\n      <z-dropdown-menu-item (click)=\"log('Profile')\">\n        Profile\n        <z-dropdown-menu-shortcut>⇧⌘P</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Billing')\">\n        Billing\n        <z-dropdown-menu-shortcut>⌘B</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Settings')\">\n        Settings\n        <z-dropdown-menu-shortcut>⌘S</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Keyboard shortcuts')\">\n        Keyboard shortcuts\n        <z-dropdown-menu-shortcut>⌘K</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item (click)=\"log('Team')\">Team</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('New Team')\">\n        New Team\n        <z-dropdown-menu-shortcut>⌘+T</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item (click)=\"log('GitHub')\">GitHub</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Support')\">Support</z-dropdown-menu-item>\n      <z-dropdown-menu-item [disabled]=\"true\">API</z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item (click)=\"log('Log out')\">\n        Log out\n        <z-dropdown-menu-shortcut>⇧⌘Q</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownComplexDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    },
    {
      "name": "default.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Open menu</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-48\">\n      <z-dropdown-menu-item (click)=\"log('Profile')\">Profile</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Billing')\">Billing</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Team')\">Team</z-dropdown-menu-item>\n      <z-dropdown-menu-item [disabled]=\"true\">Subscription</z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    },
    {
      "name": "destructive.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-destructive-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Project</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-48\">\n      <z-dropdown-menu-item (click)=\"log('Rename')\">Rename</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Duplicate')\">Duplicate</z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item zType=\"destructive\" (click)=\"log('Delete')\">Delete</z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownDestructiveDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    },
    {
      "name": "hover.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-hover-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" zTrigger=\"hover\" z-dropdown [zDropdownMenu]=\"menu\">Open</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-label>My Account</z-dropdown-menu-label>\n\n      <z-dropdown-menu-item (click)=\"onProfile()\">\n        Profile\n        <z-dropdown-menu-shortcut>⇧⌘P</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n\n      <z-dropdown-menu-item (click)=\"onBilling()\">\n        Billing\n        <z-dropdown-menu-shortcut>⌘B</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n\n      <z-dropdown-menu-item (click)=\"onSettings()\">\n        Settings\n        <z-dropdown-menu-shortcut>⌘S</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n\n      <z-dropdown-menu-item (click)=\"onKeyboardShortcuts()\">\n        Keyboard shortcuts\n        <z-dropdown-menu-shortcut>⌘K</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n\n      <z-dropdown-menu-separator />\n\n      <z-dropdown-menu-item (click)=\"onTeam()\">Team</z-dropdown-menu-item>\n\n      <z-dropdown-menu-item (click)=\"onNewTeam()\">\n        New Team\n        <z-dropdown-menu-shortcut>⌘+T</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n\n      <z-dropdown-menu-separator />\n\n      <z-dropdown-menu-item (click)=\"onGitHub()\">GitHub</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"onSupport()\">Support</z-dropdown-menu-item>\n      <z-dropdown-menu-item [disabled]=\"true\">API</z-dropdown-menu-item>\n\n      <z-dropdown-menu-separator />\n\n      <z-dropdown-menu-item (click)=\"onLogout()\">\n        Log out\n        <z-dropdown-menu-shortcut>⇧⌘Q</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownHoverDemoComponent {\n  onProfile() {\n    console.log('Profile clicked');\n  }\n\n  onBilling() {\n    console.log('Billing clicked');\n  }\n\n  onSettings() {\n    console.log('Settings clicked');\n  }\n\n  onKeyboardShortcuts() {\n    console.log('Keyboard shortcuts clicked');\n  }\n\n  onTeam() {\n    console.log('Team clicked');\n  }\n\n  onNewTeam() {\n    console.log('New Team clicked');\n  }\n\n  onGitHub() {\n    console.log('GitHub clicked');\n  }\n\n  onSupport() {\n    console.log('Support clicked');\n  }\n\n  onLogout() {\n    console.log('Log out clicked');\n  }\n}\n"
    },
    {
      "name": "icons.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { lucideCreditCard, lucideKeyboard, lucideSettings, lucideUser } from '@ng-icons/lucide';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-icons-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent, NgIcon],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Open</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-item (click)=\"log('Profile')\">\n        <ng-icon name=\"lucideUser\" class=\"mr-2 size-4\" />\n        Profile\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Billing')\">\n        <ng-icon name=\"lucideCreditCard\" class=\"mr-2 size-4\" />\n        Billing\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Settings')\">\n        <ng-icon name=\"lucideSettings\" class=\"mr-2 size-4\" />\n        Settings\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Keyboard shortcuts')\">\n        <ng-icon name=\"lucideKeyboard\" class=\"mr-2 size-4\" />\n        Keyboard shortcuts\n      </z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n  viewProviders: [provideIcons({ lucideUser, lucideCreditCard, lucideSettings, lucideKeyboard })],\n})\nexport class ZardDropdownIconsDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    },
    {
      "name": "radio-group.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-radio-group-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Panel position</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-label>Panel Position</z-dropdown-menu-label>\n      <z-dropdown-menu-radio-group [(zValue)]=\"selected\">\n        @for (position of positions; track position.value) {\n          <z-dropdown-menu-radio-item [zValue]=\"position.value\">\n            {{ position.label }}\n          </z-dropdown-menu-radio-item>\n        }\n      </z-dropdown-menu-radio-group>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownRadioGroupDemoComponent {\n  selected = 'bottom';\n  positions = [\n    { value: 'top', label: 'Top' },\n    { value: 'bottom', label: 'Bottom' },\n    { value: 'right', label: 'Right' },\n  ];\n}\n"
    },
    {
      "name": "shortcuts.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\n\n@Component({\n  selector: 'z-dropdown-shortcuts-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Account</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-label>My Account</z-dropdown-menu-label>\n      <z-dropdown-menu-item (click)=\"log('Profile')\">\n        Profile\n        <z-dropdown-menu-shortcut>⇧⌘P</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Billing')\">\n        Billing\n        <z-dropdown-menu-shortcut>⌘B</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Settings')\">\n        Settings\n        <z-dropdown-menu-shortcut>⌘S</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <z-dropdown-menu-item (click)=\"log('Log out')\">\n        Log out\n        <z-dropdown-menu-shortcut>⇧⌘Q</z-dropdown-menu-shortcut>\n      </z-dropdown-menu-item>\n    </z-dropdown-menu-content>\n  `,\n})\nexport class ZardDropdownShortcutsDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    },
    {
      "name": "submenu.ts",
      "content": "import { Component } from '@angular/core';\n\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { lucideChevronRight } from '@ng-icons/lucide';\n\nimport { ZardButtonComponent } from '@/shared/components/button';\nimport { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';\nimport { ZardMenuImports } from '@/shared/components/menu';\n\n@Component({\n  selector: 'z-dropdown-submenu-demo',\n  imports: [ZardDropdownImports, ZardButtonComponent, ZardMenuImports, NgIcon],\n  template: `\n    <button type=\"button\" z-button zType=\"outline\" z-dropdown [zDropdownMenu]=\"menu\">Open</button>\n\n    <z-dropdown-menu-content #menu=\"zDropdownMenuContent\" class=\"w-56\">\n      <z-dropdown-menu-item (click)=\"log('Back')\">Back</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Forward')\">Forward</z-dropdown-menu-item>\n      <z-dropdown-menu-item (click)=\"log('Reload')\">Reload</z-dropdown-menu-item>\n      <z-dropdown-menu-separator />\n      <button type=\"button\" z-menu-item z-menu [zMenuTriggerFor]=\"moreToolsMenu\" zPlacement=\"rightTop\">\n        More Tools\n        <ng-icon name=\"lucideChevronRight\" class=\"ml-auto size-4\" />\n      </button>\n    </z-dropdown-menu-content>\n\n    <ng-template #moreToolsMenu>\n      <div z-menu-content class=\"w-48\">\n        <button type=\"button\" z-menu-item (click)=\"log('Save Page As')\">Save Page As...</button>\n        <button type=\"button\" z-menu-item (click)=\"log('Create Shortcut')\">Create Shortcut...</button>\n        <button type=\"button\" z-menu-item (click)=\"log('Developer Tools')\">Developer Tools</button>\n      </div>\n    </ng-template>\n  `,\n  viewProviders: [provideIcons({ lucideChevronRight })],\n})\nexport class ZardDropdownSubmenuDemoComponent {\n  log(item: string) {\n    console.log(`${item} clicked`);\n  }\n}\n"
    }
  ]
}
