@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
JavaScript
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