UNPKG

@ngx-headless/ui

Version:

A library of unstyled, accessible, and composable UI primitives for Angular with full styling freedom

1,073 lines (1,046 loc) 82 kB
import * as i0 from '@angular/core'; import { Injectable, forwardRef, HostBinding, Input, Component, HostListener, signal, inject, EventEmitter, effect, Output, ChangeDetectionStrategy, ElementRef, computed, booleanAttribute, Directive } from '@angular/core'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; class DisclosureContextService { _open = false; isOpen() { return this._open; } open() { this._open = true; } close() { this._open = false; } toggle() { this._open = !this._open; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureContextService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureContextService, decorators: [{ type: Injectable }] }); class DisclosureComponent { context; class = ''; defaultOpen = false; get hostClass() { return this.class; } constructor(context) { this.context = context; } ngOnInit() { if (this.defaultOpen) { this.context.open(); } } isOpen() { return this.context.isOpen(); } toggle() { this.context.toggle(); } open() { this.context.open(); } close() { this.context.close(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureComponent, deps: [{ token: DisclosureContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: DisclosureComponent, isStandalone: true, selector: "Disclosure, [ngxDisclosure], ngx-headlessui-disclosure", inputs: { class: "class", defaultOpen: "defaultOpen" }, host: { properties: { "class": "this.hostClass" } }, providers: [ DisclosureContextService, { provide: 'ngxDisclosure', useExisting: forwardRef(() => DisclosureComponent) } ], exportAs: ["ngxDisclosure"], ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureComponent, decorators: [{ type: Component, args: [{ selector: 'Disclosure, [ngxDisclosure], ngx-headlessui-disclosure', standalone: true, template: `<ng-content />`, providers: [ DisclosureContextService, { provide: 'ngxDisclosure', useExisting: forwardRef(() => DisclosureComponent) } ], exportAs: 'ngxDisclosure' }] }], ctorParameters: () => [{ type: DisclosureContextService }], propDecorators: { class: [{ type: Input }], defaultOpen: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }] } }); class DisclosureButtonComponent { context; class = ''; get hostClass() { return this.class; } get ariaExpanded() { return this.context.isOpen(); } onClick() { this.context.toggle(); } constructor(context) { this.context = context; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureButtonComponent, deps: [{ token: DisclosureContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: DisclosureButtonComponent, isStandalone: true, selector: "DisclosureButton", inputs: { class: "class" }, host: { listeners: { "click": "onClick()" }, properties: { "class": "this.hostClass", "attr.aria-expanded": "this.ariaExpanded" } }, ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosureButtonComponent, decorators: [{ type: Component, args: [{ selector: 'DisclosureButton', standalone: true, template: `<ng-content />` }] }], ctorParameters: () => [{ type: DisclosureContextService }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], ariaExpanded: [{ type: HostBinding, args: ['attr.aria-expanded'] }], onClick: [{ type: HostListener, args: ['click'] }] } }); class DisclosurePanelComponent { context; class = ''; get hostClass() { return this.class; } constructor(context) { this.context = context; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosurePanelComponent, deps: [{ token: DisclosureContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: DisclosurePanelComponent, isStandalone: true, selector: "DisclosurePanel", inputs: { class: "class" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: `<ng-content *ngIf="context.isOpen()" />`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: DisclosurePanelComponent, decorators: [{ type: Component, args: [{ selector: 'DisclosurePanel', standalone: true, imports: [CommonModule], template: `<ng-content *ngIf="context.isOpen()" />` }] }], ctorParameters: () => [{ type: DisclosureContextService }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }] } }); // radio-group-context.service.ts class RadioGroupContextService { _selected = signal(null); selected = this._selected.asReadonly(); _setSelected = (val) => this._selected.set(val); setSelected = this._setSelected; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupContextService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupContextService, decorators: [{ type: Injectable }] }); class RadioGroupComponent { ctx = inject(RadioGroupContextService); modelValue; defaultValue; class = ''; modelValueChange = new EventEmitter(); get hostClasses() { return this.class; } ngOnInit() { if (this.defaultValue !== undefined && (this.modelValue === undefined || this.modelValue === null)) { this.ctx.setSelected(this.defaultValue); } } ngOnChanges() { this.ctx.setSelected(this.modelValue); } constructor() { effect(() => { const selected = this.ctx.selected(); if (selected !== this.modelValue) { this.modelValueChange.emit(selected); } }); } // ✅ Public API select(value) { this.ctx.setSelected(value); } clear() { this.ctx.setSelected(null); } isSelected(value) { return this.ctx.selected() === value; } getSelected() { return this.ctx.selected(); } toggle(value) { this.isSelected(value) ? this.clear() : this.select(value); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: RadioGroupComponent, isStandalone: true, selector: "RadioGroup, [ngxRadioGroup], ngx-headlessui-radiogroup", inputs: { modelValue: "modelValue", defaultValue: "defaultValue", class: "class" }, outputs: { modelValueChange: "modelValueChange" }, host: { attributes: { "role": "radiogroup" }, properties: { "class": "this.hostClasses" } }, providers: [RadioGroupContextService], exportAs: ["ngxRadioGroup"], usesOnChanges: true, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'RadioGroup, [ngxRadioGroup], ngx-headlessui-radiogroup', template: `<ng-content></ng-content>`, providers: [RadioGroupContextService], imports: [CommonModule], exportAs: 'ngxRadioGroup', changeDetection: ChangeDetectionStrategy.OnPush, host: { role: 'radiogroup', }, }] }], ctorParameters: () => [], propDecorators: { modelValue: [{ type: Input }], defaultValue: [{ type: Input }], class: [{ type: Input }], modelValueChange: [{ type: Output }], hostClasses: [{ type: HostBinding, args: ['class'] }] } }); // radio-group-label.component.ts let nextId = 0; class RadioGroupLabelComponent { el = inject((ElementRef)); id = typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : `radio-group-label-${Math.random().toString(36).slice(2, 10)}`; class = ''; get hostClass() { return this.class; } ngAfterViewInit() { const parent = this.el.nativeElement.closest('[role="radio"], [role="radiogroup"]'); if (parent) { const existing = parent.getAttribute('aria-describedby'); const updated = existing ? `${existing} ${this.id}` : this.id; parent.setAttribute('aria-describedby', updated); this.el.nativeElement.setAttribute('id', this.id); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: RadioGroupLabelComponent, isStandalone: true, selector: "RadioGroupLabel, [ngxRadioGroupLabel], ngx-headlessui-radiogroup-label", inputs: { class: "class" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupLabelComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'RadioGroupLabel, [ngxRadioGroupLabel], ngx-headlessui-radiogroup-label', template: `<ng-content></ng-content>`, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, }] }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }] } }); class RadioGroupOptionComponent { ctx = inject(RadioGroupContextService); el = inject((ElementRef)); value; class = ''; get hostClass() { return this.class; } role = 'radio'; get selected() { return this.ctx.selected() === this.value; } get checked() { return this.selected; } get tabIndex() { return this.selected ? 0 : -1; } onClick() { this.ctx.setSelected(this.value); } onKeyDown(event) { const keys = ['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp']; if (!keys.includes(event.key)) return; event.preventDefault(); const parent = this.el.nativeElement.closest('[role="radiogroup"]'); if (!parent) return; const options = Array.from(parent.querySelectorAll('[role="radio"]')); const currentIndex = options.indexOf(this.el.nativeElement); if (currentIndex === -1) return; const delta = event.key === 'ArrowLeft' || event.key === 'ArrowUp' ? -1 : 1; const nextIndex = (currentIndex + delta + options.length) % options.length; options[nextIndex]?.focus(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: RadioGroupOptionComponent, isStandalone: true, selector: "RadioGroupOption, [ngxRadioGroupOption], ngx-headlessui-radiogroup-option", inputs: { value: "value", class: "class" }, host: { listeners: { "click": "onClick()", "keydown": "onKeyDown($event)" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.aria-checked": "this.checked", "attr.tabindex": "this.tabIndex" } }, exportAs: ["ngxRadioGroupOption"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupOptionComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'RadioGroupOption, [ngxRadioGroupOption], ngx-headlessui-radiogroup-option', template: `<ng-content></ng-content>`, imports: [CommonModule], exportAs: 'ngxRadioGroupOption', changeDetection: ChangeDetectionStrategy.OnPush, }] }], propDecorators: { value: [{ type: Input }], class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], checked: [{ type: HostBinding, args: ['attr.aria-checked'] }], tabIndex: [{ type: HostBinding, args: ['attr.tabindex'] }], onClick: [{ type: HostListener, args: ['click'] }], onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); // radio-group-description.component.ts let nextDescId = 0; class RadioGroupDescriptionComponent { el = inject((ElementRef)); id = typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : `radio-group-description-${Math.random().toString(36).slice(2, 10)}`; class = ''; get hostClass() { return this.class; } ngAfterViewInit() { const parent = this.el.nativeElement.closest('[role="radio"], [role="radiogroup"]'); if (parent) { const existing = parent.getAttribute('aria-describedby'); const updated = existing ? `${existing} ${this.id}` : this.id; parent.setAttribute('aria-describedby', updated); this.el.nativeElement.setAttribute('id', this.id); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupDescriptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: RadioGroupDescriptionComponent, isStandalone: true, selector: "RadioGroupDescription, [ngxRadioGroupDescription], ngx-headlessui-radiogroup-description", inputs: { class: "class" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: RadioGroupDescriptionComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'RadioGroupDescription, [ngxRadioGroupDescription], ngx-headlessui-radiogroup-description', template: `<ng-content></ng-content>`, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, }] }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }] } }); class TabsContextService { _selectedIndex = signal(null); get selectedIndex() { return this._selectedIndex.asReadonly(); } selectTab(index) { this._selectedIndex.set(index); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabsContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabsContextService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabsContextService, decorators: [{ type: Injectable }] }); class TabGroupComponent { selectedIndex = null; defaultIndex = 0; selectedIndexChange = new EventEmitter(); tabsContext = inject(TabsContextService); constructor() { const initialIndex = this.selectedIndex !== null ? this.selectedIndex : this.defaultIndex; this.tabsContext.selectTab(initialIndex); effect(() => { const currentIndex = this.tabsContext.selectedIndex(); if (currentIndex !== null && currentIndex !== this.selectedIndex) { this.selectedIndexChange.emit(currentIndex); } }); } getSelectedIndex() { return this.tabsContext.selectedIndex(); } selectTab(index) { this.tabsContext.selectTab(index); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: TabGroupComponent, isStandalone: true, selector: "TabGroup, [ngxTabGroup], ngx-headlessui-tab-group", inputs: { selectedIndex: "selectedIndex", defaultIndex: "defaultIndex" }, outputs: { selectedIndexChange: "selectedIndexChange" }, providers: [TabsContextService], exportAs: ["ngxTabGroup"], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabGroupComponent, decorators: [{ type: Component, args: [{ selector: 'TabGroup, [ngxTabGroup], ngx-headlessui-tab-group', standalone: true, exportAs: 'ngxTabGroup', providers: [TabsContextService], template: `<ng-content></ng-content>`, }] }], ctorParameters: () => [], propDecorators: { selectedIndex: [{ type: Input }], defaultIndex: [{ type: Input }], selectedIndexChange: [{ type: Output }] } }); class TabListComponent { role = 'tablist'; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: TabListComponent, isStandalone: true, selector: "TabList, [ngxTabList], ngx-headlessui-tab-list", host: { properties: { "attr.role": "this.role" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabListComponent, decorators: [{ type: Component, args: [{ selector: 'TabList, [ngxTabList], ngx-headlessui-tab-list', standalone: true, template: `<ng-content></ng-content>`, }] }], propDecorators: { role: [{ type: HostBinding, args: ['attr.role'] }] } }); class TabComponent { index; disabled = false; tabsContext = inject(TabsContextService); role = 'tab'; get ariaSelected() { return this.tabsContext.selectedIndex() === this.index; } get ariaDisabled() { return this.disabled; } get tabindex() { return this.tabsContext.selectedIndex() === this.index ? 0 : -1; } onClick() { if (!this.disabled) { this.tabsContext.selectTab(this.index); } } onKeyDown(event) { if (this.disabled) { return; } switch (event.key) { case 'Enter': case ' ': event.preventDefault(); this.tabsContext.selectTab(this.index); break; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: TabComponent, isStandalone: true, selector: "Tab, [ngxTab], ngx-headlessui-tab", inputs: { index: "index", disabled: "disabled" }, host: { listeners: { "click": "onClick()", "keydown": "onKeyDown($event)" }, properties: { "attr.role": "this.role", "attr.aria-selected": "this.ariaSelected", "attr.aria-disabled": "this.ariaDisabled", "attr.tabindex": "this.tabindex" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabComponent, decorators: [{ type: Component, args: [{ selector: 'Tab, [ngxTab], ngx-headlessui-tab', standalone: true, template: `<ng-content></ng-content>`, }] }], propDecorators: { index: [{ type: Input }], disabled: [{ type: Input }], role: [{ type: HostBinding, args: ['attr.role'] }], ariaSelected: [{ type: HostBinding, args: ['attr.aria-selected'] }], ariaDisabled: [{ type: HostBinding, args: ['attr.aria-disabled'] }], tabindex: [{ type: HostBinding, args: ['attr.tabindex'] }], onClick: [{ type: HostListener, args: ['click'] }], onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); class TabPanelComponent { index; tabsContext = inject(TabsContextService); role = 'tabpanel'; get ariaLabelledBy() { return `tab-${this.index}`; } get hidden() { return this.tabsContext.selectedIndex() !== this.index; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: TabPanelComponent, isStandalone: true, selector: "TabPanel, [ngxTabPanel], ngx-headlessui-tab-panel", inputs: { index: "index" }, host: { properties: { "attr.role": "this.role", "attr.aria-labelledby": "this.ariaLabelledBy", "hidden": "this.hidden" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: TabPanelComponent, decorators: [{ type: Component, args: [{ selector: 'TabPanel, [ngxTabPanel], ngx-headlessui-tab-panel', standalone: true, template: `<ng-content></ng-content>`, }] }], propDecorators: { index: [{ type: Input }], role: [{ type: HostBinding, args: ['attr.role'] }], ariaLabelledBy: [{ type: HostBinding, args: ['attr.aria-labelledby'] }], hidden: [{ type: HostBinding, args: ['hidden'] }] } }); class MenuContextService { _openState = signal(false); isOpen = computed(() => this._openState()); toggle = () => this._openState.update(v => !v); close = () => this._openState.set(false); open = () => this._openState.set(true); static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuContextService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuContextService, decorators: [{ type: Injectable }] }); class MenuComponent { ctx = inject(MenuContextService); constructor() { } class = ''; get hostClass() { return this.class; } role = 'menu'; orientation = 'vertical'; get expanded() { return this.ctx.isOpen() ? true : undefined; } el = inject((ElementRef)); handleClickOutside(event) { if (!this.el.nativeElement.contains(event.target)) { this.ctx.close(); } } isOpen() { return this.ctx.isOpen(); } toggle() { this.ctx.toggle(); } close() { this.ctx.close(); } open() { this.ctx.open(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: MenuComponent, isStandalone: true, selector: "Menu, [ngxMenu], ngx-headlessui-menu", inputs: { class: "class" }, host: { listeners: { "document:click": "handleClickOutside($event)" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.aria-orientation": "this.orientation", "attr.aria-expanded": "this.expanded" } }, providers: [ MenuContextService ], exportAs: ["ngxMenu"], ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuComponent, decorators: [{ type: Component, args: [{ selector: 'Menu, [ngxMenu], ngx-headlessui-menu', standalone: true, providers: [ MenuContextService ], exportAs: 'ngxMenu', template: `<ng-content />` }] }], ctorParameters: () => [], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], orientation: [{ type: HostBinding, args: ['attr.aria-orientation'] }], expanded: [{ type: HostBinding, args: ['attr.aria-expanded'] }], handleClickOutside: [{ type: HostListener, args: ['document:click', ['$event']] }] } }); class MenuButtonComponent { ctx; constructor(ctx) { this.ctx = ctx; } class = ''; get hostClass() { return this.class; } role = 'button'; hasPopup = 'menu'; get expanded() { return this.ctx.isOpen(); } tabindex = 0; // protected ctx = inject(MenuContextService); onClick() { console.log('MenuButton clicked'); this.ctx.toggle(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuButtonComponent, deps: [{ token: MenuContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: MenuButtonComponent, isStandalone: true, selector: "MenuButton, [ngxMenuButton], ngx-headlessui-menu-button", inputs: { class: "class" }, host: { listeners: { "click": "onClick()" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.aria-haspopup": "this.hasPopup", "attr.aria-expanded": "this.expanded", "attr.tabindex": "this.tabindex" } }, ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuButtonComponent, decorators: [{ type: Component, args: [{ selector: 'MenuButton, [ngxMenuButton], ngx-headlessui-menu-button', standalone: true, template: `<ng-content />` }] }], ctorParameters: () => [{ type: MenuContextService }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], hasPopup: [{ type: HostBinding, args: ['attr.aria-haspopup'] }], expanded: [{ type: HostBinding, args: ['attr.aria-expanded'] }], tabindex: [{ type: HostBinding, args: ['attr.tabindex'] }], onClick: [{ type: HostListener, args: ['click'] }] } }); class MenuItemsComponent { ctx; constructor(ctx) { this.ctx = ctx; } class = ''; get hostClass() { return this.class; } role = 'menu'; get isHidden() { return !this.ctx.isOpen(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuItemsComponent, deps: [{ token: MenuContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: MenuItemsComponent, isStandalone: true, selector: "MenuItems, [ngxMenuItems], ngx-headlessui-menu-items", inputs: { class: "class" }, host: { properties: { "class": "this.hostClass", "attr.role": "this.role", "hidden": "this.isHidden" } }, ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuItemsComponent, decorators: [{ type: Component, args: [{ selector: 'MenuItems, [ngxMenuItems], ngx-headlessui-menu-items', standalone: true, template: `<ng-content />` }] }], ctorParameters: () => [{ type: MenuContextService }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], isHidden: [{ type: HostBinding, args: ['hidden'] }] } }); class MenuItemComponent { ctx; constructor(ctx) { this.ctx = ctx; } class = ''; get hostClass() { return this.class; } disabled = false; selected = new EventEmitter(); role = 'menuitem'; tabindex = -1; get ariaDisabled() { return this.disabled || null; } onSelect() { if (!this.disabled) { this.selected.emit(); this.ctx.close(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuItemComponent, deps: [{ token: MenuContextService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: MenuItemComponent, isStandalone: true, selector: "MenuItem, [ngxMenuItem], ngx-headlessui-menu-item", inputs: { class: "class", disabled: "disabled" }, outputs: { selected: "selected" }, host: { listeners: { "click": "onSelect()" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.tabindex": "this.tabindex", "attr.aria-disabled": "this.ariaDisabled" } }, ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: MenuItemComponent, decorators: [{ type: Component, args: [{ selector: 'MenuItem, [ngxMenuItem], ngx-headlessui-menu-item', standalone: true, template: `<ng-content />` }] }], ctorParameters: () => [{ type: MenuContextService }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], disabled: [{ type: Input }], selected: [{ type: Output }], role: [{ type: HostBinding, args: ['attr.role'] }], tabindex: [{ type: HostBinding, args: ['attr.tabindex'] }], ariaDisabled: [{ type: HostBinding, args: ['attr.aria-disabled'] }], onSelect: [{ type: HostListener, args: ['click'] }] } }); class SwitchComponent { checked = false; disabled = false; checkedChange = new EventEmitter(); role = 'switch'; get ariaChecked() { return this.checked; } get ariaDisabled() { return this.disabled || null; } get tabindex() { return this.disabled ? -1 : 0; } onClick() { if (this.disabled) return; this.checked = !this.checked; this.checkedChange.emit(this.checked); } onKeyDown(event) { event.preventDefault(); this.onClick(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: SwitchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.2.11", type: SwitchComponent, isStandalone: true, selector: "Switch, [ngxSwitch], ngx-headlessui-switch", inputs: { checked: ["checked", "checked", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute] }, outputs: { checkedChange: "checkedChange" }, host: { listeners: { "click": "onClick()", "keydown.space": "onKeyDown($event)" }, properties: { "attr.role": "this.role", "attr.aria-checked": "this.ariaChecked", "attr.aria-disabled": "this.ariaDisabled", "tabindex": "this.tabindex" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: SwitchComponent, decorators: [{ type: Component, args: [{ selector: 'Switch, [ngxSwitch], ngx-headlessui-switch', standalone: true, template: '<ng-content></ng-content>', }] }], propDecorators: { checked: [{ type: Input, args: [{ transform: booleanAttribute }] }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], checkedChange: [{ type: Output }], role: [{ type: HostBinding, args: ['attr.role'] }], ariaChecked: [{ type: HostBinding, args: ['attr.aria-checked'] }], ariaDisabled: [{ type: HostBinding, args: ['attr.aria-disabled'] }], tabindex: [{ type: HostBinding, args: ['tabindex'] }], onClick: [{ type: HostListener, args: ['click'] }], onKeyDown: [{ type: HostListener, args: ['keydown.space', ['$event']] }] } }); class SwitchGroup { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: SwitchGroup, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: SwitchGroup, isStandalone: true, selector: "SwitchGroup, [ngxSwitchGroup], ngx-headlessui-switch-group", ngImport: i0, template: '<ng-content></ng-content>', isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: SwitchGroup, decorators: [{ type: Component, args: [{ selector: 'SwitchGroup, [ngxSwitchGroup], ngx-headlessui-switch-group', standalone: true, template: '<ng-content></ng-content>', }] }] }); class SwitchLabel { constructor() { } onClick(event) { event.preventDefault(); // Let users handle toggle logic via [(checked)] binding } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: SwitchLabel, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.11", type: SwitchLabel, isStandalone: true, selector: "SwitchLabel, [ngxSwitchLabel], ngx-headlessui-switch-label", host: { listeners: { "click": "onClick($event)" } }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: SwitchLabel, decorators: [{ type: Directive, args: [{ selector: 'SwitchLabel, [ngxSwitchLabel], ngx-headlessui-switch-label', standalone: true, }] }], ctorParameters: () => [], propDecorators: { onClick: [{ type: HostListener, args: ['click', ['$event']] }] } }); class ListboxContextService { _openState = signal(false); _selectedValue = signal(null); _options = signal([]); isOpen = computed(() => this._openState()); selectedValue = computed(() => this._selectedValue()); options = computed(() => this._options()); toggle = () => this._openState.update(v => !v); close = () => this._openState.set(false); open = () => this._openState.set(true); selectValue = (value) => { this._selectedValue.set(value); this.close(); }; setOptions = (options) => this._options.set(options); static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxContextService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxContextService, decorators: [{ type: Injectable }] }); class ListboxComponent { ctx = inject(ListboxContextService); constructor() { } class = ''; modelValue = null; modelValueChange = new EventEmitter(); get hostClass() { return this.class; } role = 'listbox'; get expanded() { return this.ctx.isOpen() ? true : undefined; } el = inject((ElementRef)); handleClickOutside(event) { if (!this.el.nativeElement.contains(event.target)) { this.ctx.close(); } } isOpen() { return this.ctx.isOpen(); } toggle() { this.ctx.toggle(); } close() { this.ctx.close(); } open() { this.ctx.open(); } selectValue(value) { this.ctx.selectValue(value); this.modelValueChange.emit(value); } getSelectedValue() { return this.ctx.selectedValue(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: ListboxComponent, isStandalone: true, selector: "Listbox, [ngxListbox], ngx-headlessui-listbox", inputs: { class: "class", modelValue: "modelValue" }, outputs: { modelValueChange: "modelValueChange" }, host: { listeners: { "document:click": "handleClickOutside($event)" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.aria-expanded": "this.expanded" } }, providers: [ ListboxContextService ], exportAs: ["ngxListbox"], ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxComponent, decorators: [{ type: Component, args: [{ selector: 'Listbox, [ngxListbox], ngx-headlessui-listbox', standalone: true, providers: [ ListboxContextService ], exportAs: 'ngxListbox', template: `<ng-content />` }] }], ctorParameters: () => [], propDecorators: { class: [{ type: Input }], modelValue: [{ type: Input }], modelValueChange: [{ type: Output }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], expanded: [{ type: HostBinding, args: ['attr.aria-expanded'] }], handleClickOutside: [{ type: HostListener, args: ['document:click', ['$event']] }] } }); class ListboxButtonComponent { ctx = inject(ListboxContextService); class = ''; get hostClass() { return this.class; } role = 'button'; haspopup = 'listbox'; get expanded() { return this.ctx.isOpen(); } tabindex = '0'; onClick() { this.ctx.toggle(); } onKeydown(event) { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.ctx.toggle(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: ListboxButtonComponent, isStandalone: true, selector: "ListboxButton, [ngxListboxButton], ngx-headlessui-listbox-button", inputs: { class: "class" }, host: { listeners: { "click": "onClick()", "keydown": "onKeydown($event)" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.aria-haspopup": "this.haspopup", "attr.aria-expanded": "this.expanded", "attr.tabindex": "this.tabindex" } }, exportAs: ["ngxListboxButton"], ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxButtonComponent, decorators: [{ type: Component, args: [{ selector: 'ListboxButton, [ngxListboxButton], ngx-headlessui-listbox-button', standalone: true, exportAs: 'ngxListboxButton', template: `<ng-content />` }] }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], haspopup: [{ type: HostBinding, args: ['attr.aria-haspopup'] }], expanded: [{ type: HostBinding, args: ['attr.aria-expanded'] }], tabindex: [{ type: HostBinding, args: ['attr.tabindex'] }], onClick: [{ type: HostListener, args: ['click'] }], onKeydown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); class ListboxOptionsComponent { ctx = inject(ListboxContextService); class = ''; get hostClass() { return this.class; } role = 'listbox'; get hidden() { return !this.ctx.isOpen() ? true : undefined; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxOptionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: ListboxOptionsComponent, isStandalone: true, selector: "ListboxOptions, [ngxListboxOptions], ngx-headlessui-listbox-options", inputs: { class: "class" }, host: { properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.hidden": "this.hidden" } }, exportAs: ["ngxListboxOptions"], ngImport: i0, template: `<ng-content />`, isInline: true }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxOptionsComponent, decorators: [{ type: Component, args: [{ selector: 'ListboxOptions, [ngxListboxOptions], ngx-headlessui-listbox-options', standalone: true, exportAs: 'ngxListboxOptions', template: `<ng-content />` }] }], propDecorators: { class: [{ type: Input }], hostClass: [{ type: HostBinding, args: ['class'] }], role: [{ type: HostBinding, args: ['attr.role'] }], hidden: [{ type: HostBinding, args: ['attr.hidden'] }] } }); class ListboxOptionComponent { ctx = inject(ListboxContextService); class = ''; value; disabled = false; selected = new EventEmitter(); get hostClass() { return this.class; } role = 'option'; tabindex = '-1'; get ariaDisabled() { return this.disabled ? 'true' : undefined; } get ariaSelected() { return this.ctx.selectedValue() === this.value; } onClick() { if (!this.disabled) { this.selected.emit(this.value); this.ctx.selectValue(this.value); } } isSelected() { return this.ctx.selectedValue() === this.value; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: ListboxOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.11", type: ListboxOptionComponent, isStandalone: true, selector: "ListboxOption, [ngxListboxOption], ngx-headlessui-listbox-option", inputs: { class: "class", value: "value", disabled: "disabled" }, outputs: { selected: "selected" }, host: { listeners: { "click": "onClick()" }, properties: { "class": "this.hostClass", "attr.role": "this.role", "attr.tabindex": "this.tabindex", "attr.aria-disabled": "this.ariaDisabled", "attr.aria-selected": "this.ariaSelected" } }, exportAs: ["ngxListboxOption"], ngImport: i0, template: `<ng-conten