@frame-kit/ui-ng 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"frame-kit-ui-ng-ui-drawer.mjs","sources":["../../../../packages/ui-ng/ui/drawer/drawer.component.ts","../../../../packages/ui-ng/ui/drawer/drawer.component.html","../../../../packages/ui-ng/ui/drawer/drawer.config.ts","../../../../packages/ui-ng/ui/drawer/drawer-ref.ts","../../../../packages/ui-ng/ui/drawer/drawer.service.ts","../../../../packages/ui-ng/ui/drawer/frame-kit-ui-ng-ui-drawer.ts"],"sourcesContent":["import { A11yModule } from '@angular/cdk/a11y';\nimport { DOCUMENT } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n effect,\n HostBinding,\n HostListener,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport type {\n DrawerAnimation,\n DrawerCanCloseFn,\n DrawerWidth,\n} from './drawer.types';\n\nlet nextDrawerId = 0;\n\n@Component({\n selector: 'fk-drawer',\n standalone: true,\n imports: [A11yModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './drawer.component.html',\n styleUrl: './drawer.component.scss',\n})\nexport class DrawerComponent {\n // ===== INPUTS =====\n /** Controls whether the drawer is open. */\n readonly open = input(false);\n /** When true, shows the close button in the drawer header. */\n readonly closable = input(true);\n /** When true, pressing Escape closes the drawer. */\n readonly closeOnEscape = input(true);\n /** When true, clicking the backdrop overlay closes the drawer. */\n readonly closeOnBackdrop = input(true);\n /** Width variant of the drawer panel. */\n readonly width = input<DrawerWidth>('md');\n /** Optional title text rendered in the drawer header. */\n readonly header = input<string | null>(null);\n /** When true, focus returns to the previously focused element when the drawer closes. */\n readonly restoreFocus = input(true);\n /** When true, CDK auto-focus is applied when the drawer opens. */\n readonly autoFocus = input(true);\n /** Entry/exit animation applied to the drawer panel. */\n readonly animation = input<DrawerAnimation>('slide-right');\n /** When true, all close mechanisms are blocked. */\n readonly preventClose = input(false);\n /** Async guard function called before closing; return false to cancel the close. */\n readonly canClose = input<DrawerCanCloseFn | null>(null);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires when the drawer's open state should change, emitting the new boolean. */\n readonly openChange = output<boolean>();\n /** Fires immediately before the drawer begins its open animation. */\n readonly beforeOpen = output<void>();\n /** Fires after the drawer is fully open. */\n readonly opened = output<void>();\n /** Fires immediately before the drawer begins its close animation. */\n readonly beforeClose = output<void>();\n /** Fires after the drawer is fully closed. */\n readonly closed = output<void>();\n\n // ===== INTERNAL STATE =====\n private readonly doc = inject(DOCUMENT);\n private readonly destroyRef = inject(DestroyRef);\n readonly titleId = `fk-drawer-title-${nextDrawerId++}`;\n private previouslyFocusedElement: HTMLElement | null = null;\n private closeGuardRunning = false;\n\n readonly visible = signal(false);\n readonly animatingOut = signal(false);\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return ['fk-drawer', this.className()].filter(Boolean).join(' ');\n });\n\n readonly ariaLabelledBy = computed(() => {\n if (this.ariaLabel()) {\n return null;\n }\n\n return this.header() ? this.titleId : null;\n });\n\n constructor() {\n effect(() => {\n const isOpen = this.open();\n\n if (isOpen) {\n this.onDrawerOpen();\n } else {\n this.onDrawerClose();\n }\n });\n\n this.destroyRef.onDestroy(() => {\n // Placeholder for future cleanup (e.g., nested drawer teardown)\n });\n }\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId() {\n return this.id();\n }\n\n // ===== KEYBOARD =====\n @HostListener('document:keydown.escape')\n onEscapeKey() {\n if (this.open() && this.closeOnEscape()) {\n this.close();\n }\n }\n\n // ===== ACTIONS =====\n /** Closes the drawer, running any `canClose` guard first; no-ops when `preventClose` is true. */\n async close() {\n if (this.closeGuardRunning) {\n return;\n }\n\n if (this.preventClose()) {\n return;\n }\n\n const guard = this.canClose();\n\n if (guard) {\n this.closeGuardRunning = true;\n\n try {\n const allowed = await Promise.resolve(guard());\n\n if (!allowed) {\n return;\n }\n } finally {\n this.closeGuardRunning = false;\n }\n }\n\n this.beforeClose.emit();\n this.openChange.emit(false);\n this.closed.emit();\n }\n\n onOverlayClick() {\n if (this.closeOnBackdrop()) {\n this.close();\n }\n }\n\n onExitAnimationDone() {\n if (this.animatingOut()) {\n this.animatingOut.set(false);\n this.visible.set(false);\n }\n }\n\n // ===== LIFECYCLE =====\n private onDrawerOpen() {\n this.previouslyFocusedElement =\n (this.doc.activeElement as HTMLElement) ?? null;\n\n this.beforeOpen.emit();\n this.animatingOut.set(false);\n this.visible.set(true);\n this.opened.emit();\n }\n\n private onDrawerClose() {\n if (this.visible()) {\n if (this.animation() !== 'none') {\n this.animatingOut.set(true);\n } else {\n this.visible.set(false);\n }\n }\n\n if (this.restoreFocus() && this.previouslyFocusedElement) {\n this.previouslyFocusedElement.focus();\n this.previouslyFocusedElement = null;\n }\n }\n}\n","@if (visible()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"fk-drawer__overlay\"\n [class.fk-drawer__animate-overlay--in]=\"!animatingOut()\"\n [class.fk-drawer__animate-overlay--out]=\"animatingOut()\"\n [class.fk-drawer__animate-overlay--none]=\"animation() === 'none'\"\n (click)=\"onOverlayClick()\"\n (animationend)=\"onExitAnimationDone()\"\n >\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <div\n class=\"fk-drawer__panel\"\n [class.fk-drawer__panel--sm]=\"width() === 'sm'\"\n [class.fk-drawer__panel--md]=\"width() === 'md'\"\n [class.fk-drawer__panel--lg]=\"width() === 'lg'\"\n [class.fk-drawer__panel--xl]=\"width() === 'xl'\"\n [class.fk-drawer__animate-panel--slide-right]=\"\n animation() === 'slide-right' && !animatingOut()\n \"\n [class.fk-drawer__animate-panel--fade]=\"\n animation() === 'fade' && !animatingOut()\n \"\n [class.fk-drawer__animate-panel-out--slide-right]=\"\n animation() === 'slide-right' && animatingOut()\n \"\n [class.fk-drawer__animate-panel-out--fade]=\"\n animation() === 'fade' && animatingOut()\n \"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledBy()\"\n [cdkTrapFocus]=\"true\"\n [cdkTrapFocusAutoCapture]=\"autoFocus()\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (header() || closable()) {\n <div class=\"fk-drawer__header\">\n @if (header()) {\n <span class=\"fk-drawer__title\" [id]=\"titleId\">\n {{ header() }}\n </span>\n }\n\n @if (closable()) {\n <button\n class=\"fk-drawer__close\"\n type=\"button\"\n aria-label=\"Close drawer\"\n (click)=\"close()\"\n >\n &times;\n </button>\n }\n </div>\n }\n\n <div class=\"fk-drawer__body\">\n <ng-content />\n </div>\n\n <div class=\"fk-drawer__footer\">\n <ng-content select=\"[fkDrawerFooter]\" />\n </div>\n </div>\n </div>\n}\n","import type {\n DrawerAnimation,\n DrawerCanCloseFn,\n DrawerWidth,\n} from './drawer.types';\n\nexport interface DrawerConfig<TData = unknown> {\n closable?: boolean;\n closeOnEscape?: boolean;\n closeOnBackdrop?: boolean;\n width?: DrawerWidth;\n animation?: DrawerAnimation;\n header?: string | null;\n restoreFocus?: boolean;\n autoFocus?: boolean;\n preventClose?: boolean;\n canClose?: DrawerCanCloseFn;\n className?: string;\n ariaLabel?: string | null;\n data?: TData;\n /** Element to append the drawer into. Must have `position: relative`. Defaults to `document.body`. */\n container?: HTMLElement;\n}\n\nexport const DEFAULT_DRAWER_CONFIG: DrawerConfig = {\n closable: true,\n closeOnEscape: true,\n closeOnBackdrop: true,\n width: 'md',\n animation: 'slide-right',\n header: null,\n restoreFocus: true,\n autoFocus: true,\n preventClose: false,\n className: '',\n ariaLabel: null,\n};\n","import { Observable, Subject } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\nimport type { DrawerConfig } from './drawer.config';\nimport type { DrawerCanCloseFn } from './drawer.types';\n\nexport class DrawerRef<TResult = unknown, TData = unknown> {\n private readonly beforeOpenSubject = new Subject<void>();\n private readonly afterOpenedSubject = new Subject<void>();\n private readonly beforeCloseSubject = new Subject<void>();\n private readonly afterClosedSubject = new Subject<TResult | undefined>();\n private closed = false;\n private closeGuard: DrawerCanCloseFn | null = null;\n\n readonly config: DrawerConfig<TData>;\n\n constructor(config: DrawerConfig<TData> = {} as DrawerConfig<TData>) {\n this.config = config;\n\n if (config.canClose) {\n this.closeGuard = config.canClose;\n }\n }\n\n get data(): TData | undefined {\n return this.config.data;\n }\n\n setCanClose(guard: DrawerCanCloseFn | null) {\n this.closeGuard = guard;\n }\n\n async close(result?: TResult) {\n if (this.closed) {\n return;\n }\n\n if (this.config.preventClose) {\n return;\n }\n\n if (this.closeGuard) {\n const allowed = await Promise.resolve(this.closeGuard());\n\n if (!allowed) {\n return;\n }\n }\n\n this.beforeCloseSubject.next();\n this.beforeCloseSubject.complete();\n\n this.closed = true;\n this.afterClosedSubject.next(result);\n this.afterClosedSubject.complete();\n }\n\n beforeOpen(): Observable<void> {\n return this.beforeOpenSubject.asObservable().pipe(take(1));\n }\n\n afterOpened(): Observable<void> {\n return this.afterOpenedSubject.asObservable().pipe(take(1));\n }\n\n beforeClose(): Observable<void> {\n return this.beforeCloseSubject.asObservable().pipe(take(1));\n }\n\n afterClosed(): Observable<TResult | undefined> {\n return this.afterClosedSubject.asObservable().pipe(take(1));\n }\n\n /** @internal */\n markBeforeOpen() {\n this.beforeOpenSubject.next();\n this.beforeOpenSubject.complete();\n }\n\n /** @internal */\n markOpened() {\n this.afterOpenedSubject.next();\n this.afterOpenedSubject.complete();\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport {\n ApplicationRef,\n ComponentRef,\n createComponent,\n EnvironmentInjector,\n inject,\n Injectable,\n Injector,\n Type,\n} from '@angular/core';\n\nimport { OverlayOrchestrator } from '@frame-kit/ui-ng/services/overlay-orchestrator';\nimport { OVERLAY_PRIORITY } from '@frame-kit/ui-ng/services/overlay-orchestrator';\nimport { DrawerComponent } from './drawer.component';\nimport { DEFAULT_DRAWER_CONFIG, DrawerConfig } from './drawer.config';\nimport { DrawerRef } from './drawer-ref';\n\nexport const DRAWER_DATA = Symbol('DRAWER_DATA');\nexport const DRAWER_REF = Symbol('DRAWER_REF');\n\nconst BASE_Z_INDEX = 1100;\nconst Z_INDEX_STEP = 10;\n\ninterface DrawerEntry {\n ref: DrawerRef;\n hostRef: ComponentRef<DrawerComponent>;\n contentRef: ComponentRef<unknown>;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class DrawerService {\n private readonly appRef = inject(ApplicationRef);\n private readonly injector = inject(EnvironmentInjector);\n private readonly doc = inject(DOCUMENT);\n private readonly orchestrator = inject(OverlayOrchestrator);\n\n private activeDrawers: DrawerEntry[] = [];\n private overlayIds = new Map<DrawerEntry, string>();\n\n get openCount(): number {\n return this.activeDrawers.length;\n }\n\n open<TResult = unknown, TData = unknown>(\n content: Type<unknown>,\n config?: DrawerConfig<TData>,\n ): DrawerRef<TResult, TData> {\n const mergedConfig = {\n ...DEFAULT_DRAWER_CONFIG,\n ...config,\n } as DrawerConfig<TData>;\n const drawerRef = new DrawerRef<TResult, TData>(mergedConfig);\n\n const childInjector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: DRAWER_DATA as never, useValue: mergedConfig.data },\n { provide: DRAWER_REF as never, useValue: drawerRef },\n ],\n });\n\n const hostRef = createComponent(DrawerComponent, {\n environmentInjector: this.injector,\n elementInjector: childInjector,\n });\n\n const contentRef = createComponent(content, {\n environmentInjector: this.injector,\n elementInjector: childInjector,\n hostElement: this.doc.createElement('div'),\n });\n\n this.applyConfig(hostRef, mergedConfig);\n this.appRef.attachView(hostRef.hostView);\n this.appRef.attachView(contentRef.hostView);\n\n this.doc.body.appendChild(hostRef.location.nativeElement);\n\n const entry: DrawerEntry = {\n ref: drawerRef as DrawerRef<unknown, unknown>,\n hostRef,\n contentRef,\n };\n\n this.activeDrawers.push(entry);\n\n const overlayId = this.orchestrator.register({\n priority: OVERLAY_PRIORITY.DRAWER,\n type: 'drawer',\n close: () => drawerRef.close(),\n });\n\n this.overlayIds.set(entry, overlayId);\n\n hostRef.instance.beforeOpen.subscribe(() => {\n drawerRef.markBeforeOpen();\n });\n\n hostRef.instance.opened.subscribe(() => {\n drawerRef.markOpened();\n });\n\n hostRef.instance.closed.subscribe(() => {\n drawerRef.close();\n });\n\n drawerRef.afterClosed().subscribe(() => {\n this.destroyDrawer(entry);\n });\n\n hostRef.setInput('open', true);\n hostRef.changeDetectorRef.detectChanges();\n\n const panelBody =\n hostRef.location.nativeElement.querySelector('.fk-drawer__body');\n\n if (panelBody) {\n panelBody.appendChild(contentRef.location.nativeElement);\n }\n\n // Move [fkDrawerFooter] elements from the body into the footer wrapper\n const footerWrapper =\n hostRef.location.nativeElement.querySelector('.fk-drawer__footer');\n\n if (footerWrapper && panelBody) {\n const footerElements = panelBody.querySelectorAll('[fkDrawerFooter]');\n\n for (const el of footerElements) {\n footerWrapper.appendChild(el);\n }\n }\n\n // Position the overlay to match the container's bounds\n if (mergedConfig.container) {\n this.applyContainerBounds(entry, mergedConfig.container);\n }\n\n this.applyZIndex(entry);\n\n return drawerRef;\n }\n\n closeAll() {\n [...this.activeDrawers].forEach((entry) => entry.ref.close());\n }\n\n private applyContainerBounds(entry: DrawerEntry, container: HTMLElement) {\n const rect = container.getBoundingClientRect();\n const overlay = entry.hostRef.location.nativeElement.querySelector(\n '.fk-drawer__overlay',\n );\n\n if (overlay) {\n overlay.style.setProperty('--fk-drawer-bounds-top', `${rect.top}px`);\n\n overlay.style.setProperty(\n '--fk-drawer-bounds-right',\n `${window.innerWidth - rect.right}px`,\n );\n\n overlay.style.setProperty(\n '--fk-drawer-bounds-bottom',\n `${window.innerHeight - rect.bottom}px`,\n );\n\n overlay.style.setProperty('--fk-drawer-bounds-left', `${rect.left}px`);\n }\n }\n\n private applyZIndex(entry: DrawerEntry) {\n const index = this.activeDrawers.indexOf(entry);\n const zIndex = BASE_Z_INDEX + index * Z_INDEX_STEP;\n const overlay = entry.hostRef.location.nativeElement.querySelector(\n '.fk-drawer__overlay',\n );\n\n if (overlay) {\n overlay.style.zIndex = String(zIndex);\n }\n }\n\n private applyConfig(\n hostRef: ComponentRef<DrawerComponent>,\n config: DrawerConfig,\n ) {\n hostRef.setInput('closable', config.closable ?? true);\n hostRef.setInput('closeOnEscape', config.closeOnEscape ?? true);\n hostRef.setInput('closeOnBackdrop', config.closeOnBackdrop ?? true);\n hostRef.setInput('width', config.width ?? 'md');\n hostRef.setInput('animation', config.animation ?? 'slide-right');\n hostRef.setInput('header', config.header ?? null);\n hostRef.setInput('restoreFocus', config.restoreFocus ?? true);\n hostRef.setInput('autoFocus', config.autoFocus ?? true);\n hostRef.setInput('className', config.className ?? '');\n hostRef.setInput('preventClose', config.preventClose ?? false);\n hostRef.setInput('canClose', config.canClose ?? null);\n hostRef.setInput('ariaLabel', config.ariaLabel ?? null);\n }\n\n private destroyDrawer(entry: DrawerEntry) {\n const overlayId = this.overlayIds.get(entry);\n\n if (overlayId) {\n this.orchestrator.unregister(overlayId);\n this.overlayIds.delete(entry);\n }\n\n const idx = this.activeDrawers.indexOf(entry);\n\n if (idx > -1) {\n this.activeDrawers.splice(idx, 1);\n }\n\n entry.hostRef.setInput('open', false);\n entry.hostRef.changeDetectorRef.detectChanges();\n\n this.appRef.detachView(entry.contentRef.hostView);\n this.appRef.detachView(entry.hostRef.hostView);\n\n entry.contentRef.destroy();\n entry.hostRef.destroy();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;AAsBA,IAAI,YAAY,GAAG,CAAC;MAUP,eAAe,CAAA;;;AAGjB,IAAA,IAAI,GAAG,KAAK,CAAC,KAAK,2EAAC;;AAEnB,IAAA,QAAQ,GAAG,KAAK,CAAC,IAAI,+EAAC;;AAEtB,IAAA,aAAa,GAAG,KAAK,CAAC,IAAI,oFAAC;;AAE3B,IAAA,eAAe,GAAG,KAAK,CAAC,IAAI,sFAAC;;AAE7B,IAAA,KAAK,GAAG,KAAK,CAAc,IAAI,4EAAC;;AAEhC,IAAA,MAAM,GAAG,KAAK,CAAgB,IAAI,6EAAC;;AAEnC,IAAA,YAAY,GAAG,KAAK,CAAC,IAAI,mFAAC;;AAE1B,IAAA,SAAS,GAAG,KAAK,CAAC,IAAI,gFAAC;;AAEvB,IAAA,SAAS,GAAG,KAAK,CAAkB,aAAa,gFAAC;;AAEjD,IAAA,YAAY,GAAG,KAAK,CAAC,KAAK,mFAAC;;AAE3B,IAAA,QAAQ,GAAG,KAAK,CAA0B,IAAI,+EAAC;;AAG/C,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;AAC7B,IAAA,EAAE,GAAG,KAAK,CAAgB,IAAI,yEAAC;AAC/B,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;;;IAItC,UAAU,GAAG,MAAM,EAAW;;IAE9B,UAAU,GAAG,MAAM,EAAQ;;IAE3B,MAAM,GAAG,MAAM,EAAQ;;IAEvB,WAAW,GAAG,MAAM,EAAQ;;IAE5B,MAAM,GAAG,MAAM,EAAQ;;AAGf,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AACtB,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AACvC,IAAA,OAAO,GAAG,CAAA,gBAAA,EAAmB,YAAY,EAAE,EAAE;IAC9C,wBAAwB,GAAuB,IAAI;IACnD,iBAAiB,GAAG,KAAK;AAExB,IAAA,OAAO,GAAG,MAAM,CAAC,KAAK,8EAAC;AACvB,IAAA,YAAY,GAAG,MAAM,CAAC,KAAK,mFAAC;;AAG5B,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AAC/B,QAAA,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAClE,IAAA,CAAC,8EAAC;AAEO,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAK;AACtC,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;AACpB,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI;AAC5C,IAAA,CAAC,qFAAC;AAEF,IAAA,WAAA,GAAA;QACE,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE;YAE1B,IAAI,MAAM,EAAE;gBACV,IAAI,CAAC,YAAY,EAAE;YACrB;iBAAO;gBACL,IAAI,CAAC,aAAa,EAAE;YACtB;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;;AAE/B,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,IACI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;AAEA,IAAA,IACI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,EAAE,EAAE;IAClB;;IAIA,WAAW,GAAA;QACT,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE;YACvC,IAAI,CAAC,KAAK,EAAE;QACd;IACF;;;AAIA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE;YAC1B;QACF;AAEA,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;YACvB;QACF;AAEA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE;QAE7B,IAAI,KAAK,EAAE;AACT,YAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI;AAE7B,YAAA,IAAI;gBACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAE9C,IAAI,CAAC,OAAO,EAAE;oBACZ;gBACF;YACF;oBAAU;AACR,gBAAA,IAAI,CAAC,iBAAiB,GAAG,KAAK;YAChC;QACF;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;AACvB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;AAC3B,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;IACpB;IAEA,cAAc,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE,EAAE;YAC1B,IAAI,CAAC,KAAK,EAAE;QACd;IACF;IAEA,mBAAmB,GAAA;AACjB,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;AACvB,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5B,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACzB;IACF;;IAGQ,YAAY,GAAA;AAClB,QAAA,IAAI,CAAC,wBAAwB;AAC1B,YAAA,IAAI,CAAC,GAAG,CAAC,aAA6B,IAAI,IAAI;AAEjD,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5B,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;IACpB;IAEQ,aAAa,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;AAClB,YAAA,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,MAAM,EAAE;AAC/B,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;YAC7B;iBAAO;AACL,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YACzB;QACF;QAEA,IAAI,IAAI,CAAC,YAAY,EAAE,IAAI,IAAI,CAAC,wBAAwB,EAAE;AACxD,YAAA,IAAI,CAAC,wBAAwB,CAAC,KAAK,EAAE;AACrC,YAAA,IAAI,CAAC,wBAAwB,GAAG,IAAI;QACtC;IACF;uGAxKW,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAf,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,MAAA,EAAA,QAAA,EAAA,WAAA,EAAA,aAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,yBAAA,EAAA,eAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,SAAA,EAAA,aAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EChC5B,szEAoEA,EAAA,MAAA,EAAA,CAAA,6xIAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDzCY,UAAU,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,YAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,cAAA,EAAA,yBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,cAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAKT,eAAe,EAAA,UAAA,EAAA,CAAA;kBAR3B,SAAS;+BACE,WAAW,EAAA,UAAA,EACT,IAAI,EAAA,OAAA,EACP,CAAC,UAAU,CAAC,EAAA,eAAA,EACJ,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,szEAAA,EAAA,MAAA,EAAA,CAAA,6xIAAA,CAAA,EAAA;;sBAqF9C,WAAW;uBAAC,OAAO;;sBAKnB,WAAW;uBAAC,SAAS;;sBAMrB,YAAY;uBAAC,yBAAyB;;;AEpGlC,MAAM,qBAAqB,GAAiB;AACjD,IAAA,QAAQ,EAAE,IAAI;AACd,IAAA,aAAa,EAAE,IAAI;AACnB,IAAA,eAAe,EAAE,IAAI;AACrB,IAAA,KAAK,EAAE,IAAI;AACX,IAAA,SAAS,EAAE,aAAa;AACxB,IAAA,MAAM,EAAE,IAAI;AACZ,IAAA,YAAY,EAAE,IAAI;AAClB,IAAA,SAAS,EAAE,IAAI;AACf,IAAA,YAAY,EAAE,KAAK;AACnB,IAAA,SAAS,EAAE,EAAE;AACb,IAAA,SAAS,EAAE,IAAI;;;MC7BJ,SAAS,CAAA;AACH,IAAA,iBAAiB,GAAG,IAAI,OAAO,EAAQ;AACvC,IAAA,kBAAkB,GAAG,IAAI,OAAO,EAAQ;AACxC,IAAA,kBAAkB,GAAG,IAAI,OAAO,EAAQ;AACxC,IAAA,kBAAkB,GAAG,IAAI,OAAO,EAAuB;IAChE,MAAM,GAAG,KAAK;IACd,UAAU,GAA4B,IAAI;AAEzC,IAAA,MAAM;AAEf,IAAA,WAAA,CAAY,SAA8B,EAAyB,EAAA;AACjE,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AAEpB,QAAA,IAAI,MAAM,CAAC,QAAQ,EAAE;AACnB,YAAA,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,QAAQ;QACnC;IACF;AAEA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI;IACzB;AAEA,IAAA,WAAW,CAAC,KAA8B,EAAA;AACxC,QAAA,IAAI,CAAC,UAAU,GAAG,KAAK;IACzB;IAEA,MAAM,KAAK,CAAC,MAAgB,EAAA;AAC1B,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;YACf;QACF;AAEA,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;YAC5B;QACF;AAEA,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,YAAA,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAExD,IAAI,CAAC,OAAO,EAAE;gBACZ;YACF;QACF;AAEA,QAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE;AAC9B,QAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;AAElC,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;AAClB,QAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;AACpC,QAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;IACpC;IAEA,UAAU,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5D;IAEA,WAAW,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D;IAEA,WAAW,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D;IAEA,WAAW,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D;;IAGA,cAAc,GAAA;AACZ,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE;AAC7B,QAAA,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE;IACnC;;IAGA,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE;AAC9B,QAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;IACpC;AACD;;MClEY,WAAW,GAAG,MAAM,CAAC,aAAa;MAClC,UAAU,GAAG,MAAM,CAAC,YAAY;AAE7C,MAAM,YAAY,GAAG,IAAI;AACzB,MAAM,YAAY,GAAG,EAAE;MASV,aAAa,CAAA;AACP,IAAA,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC;AAC/B,IAAA,QAAQ,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACtC,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AACtB,IAAA,YAAY,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAEnD,aAAa,GAAkB,EAAE;AACjC,IAAA,UAAU,GAAG,IAAI,GAAG,EAAuB;AAEnD,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM;IAClC;IAEA,IAAI,CACF,OAAsB,EACtB,MAA4B,EAAA;AAE5B,QAAA,MAAM,YAAY,GAAG;AACnB,YAAA,GAAG,qBAAqB;AACxB,YAAA,GAAG,MAAM;SACa;AACxB,QAAA,MAAM,SAAS,GAAG,IAAI,SAAS,CAAiB,YAAY,CAAC;AAE7D,QAAA,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;YACpC,MAAM,EAAE,IAAI,CAAC,QAAQ;AACrB,YAAA,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,WAAoB,EAAE,QAAQ,EAAE,YAAY,CAAC,IAAI,EAAE;AAC9D,gBAAA,EAAE,OAAO,EAAE,UAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE;AACtD,aAAA;AACF,SAAA,CAAC;AAEF,QAAA,MAAM,OAAO,GAAG,eAAe,CAAC,eAAe,EAAE;YAC/C,mBAAmB,EAAE,IAAI,CAAC,QAAQ;AAClC,YAAA,eAAe,EAAE,aAAa;AAC/B,SAAA,CAAC;AAEF,QAAA,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,EAAE;YAC1C,mBAAmB,EAAE,IAAI,CAAC,QAAQ;AAClC,YAAA,eAAe,EAAE,aAAa;YAC9B,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC;AAC3C,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,YAAY,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC;AAE3C,QAAA,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;AAEzD,QAAA,MAAM,KAAK,GAAgB;AACzB,YAAA,GAAG,EAAE,SAAwC;YAC7C,OAAO;YACP,UAAU;SACX;AAED,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;AAE9B,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC3C,QAAQ,EAAE,gBAAgB,CAAC,MAAM;AACjC,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,KAAK,EAAE,MAAM,SAAS,CAAC,KAAK,EAAE;AAC/B,SAAA,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC;QAErC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;YACzC,SAAS,CAAC,cAAc,EAAE;AAC5B,QAAA,CAAC,CAAC;QAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAK;YACrC,SAAS,CAAC,UAAU,EAAE;AACxB,QAAA,CAAC,CAAC;QAEF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAK;YACrC,SAAS,CAAC,KAAK,EAAE;AACnB,QAAA,CAAC,CAAC;AAEF,QAAA,SAAS,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,MAAK;AACrC,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;AAC3B,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;AAC9B,QAAA,OAAO,CAAC,iBAAiB,CAAC,aAAa,EAAE;AAEzC,QAAA,MAAM,SAAS,GACb,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,kBAAkB,CAAC;QAElE,IAAI,SAAS,EAAE;YACb,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC1D;;AAGA,QAAA,MAAM,aAAa,GACjB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,oBAAoB,CAAC;AAEpE,QAAA,IAAI,aAAa,IAAI,SAAS,EAAE;YAC9B,MAAM,cAAc,GAAG,SAAS,CAAC,gBAAgB,CAAC,kBAAkB,CAAC;AAErE,YAAA,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE;AAC/B,gBAAA,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B;QACF;;AAGA,QAAA,IAAI,YAAY,CAAC,SAAS,EAAE;YAC1B,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC;QAC1D;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAEvB,QAAA,OAAO,SAAS;IAClB;IAEA,QAAQ,GAAA;QACN,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IAC/D;IAEQ,oBAAoB,CAAC,KAAkB,EAAE,SAAsB,EAAA;AACrE,QAAA,MAAM,IAAI,GAAG,SAAS,CAAC,qBAAqB,EAAE;AAC9C,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAChE,qBAAqB,CACtB;QAED,IAAI,OAAO,EAAE;AACX,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,CAAA,EAAG,IAAI,CAAC,GAAG,CAAA,EAAA,CAAI,CAAC;AAEpE,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CACvB,0BAA0B,EAC1B,CAAA,EAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAA,EAAA,CAAI,CACtC;AAED,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CACvB,2BAA2B,EAC3B,CAAA,EAAG,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAA,EAAA,CAAI,CACxC;AAED,YAAA,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,CAAA,EAAG,IAAI,CAAC,IAAI,CAAA,EAAA,CAAI,CAAC;QACxE;IACF;AAEQ,IAAA,WAAW,CAAC,KAAkB,EAAA;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC;AAC/C,QAAA,MAAM,MAAM,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY;AAClD,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAChE,qBAAqB,CACtB;QAED,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACvC;IACF;IAEQ,WAAW,CACjB,OAAsC,EACtC,MAAoB,EAAA;QAEpB,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;QACrD,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC;QAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,eAAe,IAAI,IAAI,CAAC;QACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC;QAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,IAAI,aAAa,CAAC;QAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC;QACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;QAC7D,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC;QACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,YAAY,IAAI,KAAK,CAAC;QAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;QACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC;IACzD;AAEQ,IAAA,aAAa,CAAC,KAAkB,EAAA;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QAE5C,IAAI,SAAS,EAAE;AACb,YAAA,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC;AACvC,YAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;QAC/B;QAEA,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC;AAE7C,QAAA,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE;YACZ,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QACnC;QAEA,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;AACrC,QAAA,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,aAAa,EAAE;QAE/C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;AAE9C,QAAA,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE;AAC1B,QAAA,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE;IACzB;uGA/LW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAb,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,aAAa,cADA,MAAM,EAAA,CAAA;;2FACnB,aAAa,EAAA,UAAA,EAAA,CAAA;kBADzB,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;AC9BlC;;AAEG;;;;"}
1
+ {"version":3,"file":"frame-kit-ui-ng-ui-drawer.mjs","sources":["../../../../packages/ui-ng/ui/drawer/drawer.component.ts","../../../../packages/ui-ng/ui/drawer/drawer.component.html","../../../../packages/ui-ng/ui/drawer/drawer.config.ts","../../../../packages/ui-ng/ui/drawer/drawer-ref.ts","../../../../packages/ui-ng/ui/drawer/drawer.service.ts","../../../../packages/ui-ng/ui/drawer/frame-kit-ui-ng-ui-drawer.ts"],"sourcesContent":["import { A11yModule } from '@angular/cdk/a11y';\nimport { DOCUMENT } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n HostBinding,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport type {\n DrawerAnimation,\n DrawerCanCloseFn,\n DrawerWidth,\n} from './drawer.types';\n\nlet nextDrawerId = 0;\n\n/**\n * Drawer panel chrome.\n *\n * Hosted inside a CDK overlay by `DrawerService`, which owns the backdrop,\n * scroll blocking, positioning, stacking, and Escape / outside dispatch. This\n * component renders the sliding panel: header / body / footer projection,\n * width sizing, the slide animation, focus trapping, and the close guard.\n */\n@Component({\n selector: 'fk-drawer',\n standalone: true,\n imports: [A11yModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './drawer.component.html',\n styleUrl: './drawer.component.scss',\n})\nexport class DrawerComponent {\n // ===== INPUTS =====\n /** Controls whether the drawer is open. */\n readonly open = input(false);\n /** When true, shows the close button in the drawer header. */\n readonly closable = input(true);\n /** Width variant of the drawer panel. */\n readonly width = input<DrawerWidth>('md');\n /** Optional title text rendered in the drawer header. */\n readonly header = input<string | null>(null);\n /** When true, focus returns to the previously focused element when the drawer closes. */\n readonly restoreFocus = input(true);\n /** When true, CDK auto-focus is applied when the drawer opens. */\n readonly autoFocus = input(true);\n /** Entry/exit animation applied to the drawer panel. */\n readonly animation = input<DrawerAnimation>('slide-right');\n /** When true, all close mechanisms are blocked. */\n readonly preventClose = input(false);\n /** Async guard function called before closing; return false to cancel the close. */\n readonly canClose = input<DrawerCanCloseFn | null>(null);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires when the drawer's open state should change, emitting the new boolean. */\n readonly openChange = output<boolean>();\n /** Fires immediately before the drawer begins its open animation. */\n readonly beforeOpen = output<void>();\n /** Fires after the drawer is fully open. */\n readonly opened = output<void>();\n /** Fires immediately before the drawer begins its close animation. */\n readonly beforeClose = output<void>();\n /** Fires after the drawer is fully closed. */\n readonly closed = output<void>();\n\n // ===== INTERNAL STATE =====\n private readonly doc = inject(DOCUMENT);\n readonly titleId = `fk-drawer-title-${nextDrawerId++}`;\n private previouslyFocusedElement: HTMLElement | null = null;\n private closeGuardRunning = false;\n\n readonly visible = signal(false);\n readonly animatingOut = signal(false);\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return ['fk-drawer', this.className()].filter(Boolean).join(' ');\n });\n\n readonly ariaLabelledBy = computed(() => {\n if (this.ariaLabel()) {\n return null;\n }\n\n return this.header() ? this.titleId : null;\n });\n\n constructor() {\n effect(() => {\n const isOpen = this.open();\n\n if (isOpen) {\n this.onDrawerOpen();\n } else {\n this.onDrawerClose();\n }\n });\n }\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId() {\n return this.id();\n }\n\n // ===== ACTIONS =====\n /** Closes the drawer, running any `canClose` guard first; no-ops when `preventClose` is true. */\n async close() {\n if (this.closeGuardRunning) {\n return;\n }\n\n if (this.preventClose()) {\n return;\n }\n\n const guard = this.canClose();\n\n if (guard) {\n this.closeGuardRunning = true;\n\n try {\n const allowed = await Promise.resolve(guard());\n\n if (!allowed) {\n return;\n }\n } finally {\n this.closeGuardRunning = false;\n }\n }\n\n this.beforeClose.emit();\n this.openChange.emit(false);\n this.closed.emit();\n }\n\n /** Called when the panel exit animation finishes. */\n onExitAnimationDone() {\n if (this.animatingOut()) {\n this.animatingOut.set(false);\n this.visible.set(false);\n }\n }\n\n // ===== LIFECYCLE =====\n private onDrawerOpen() {\n this.previouslyFocusedElement =\n (this.doc.activeElement as HTMLElement) ?? null;\n\n this.beforeOpen.emit();\n this.animatingOut.set(false);\n this.visible.set(true);\n this.opened.emit();\n }\n\n private onDrawerClose() {\n if (this.visible()) {\n if (this.animation() !== 'none') {\n this.animatingOut.set(true);\n } else {\n this.visible.set(false);\n }\n }\n\n if (this.restoreFocus() && this.previouslyFocusedElement) {\n this.previouslyFocusedElement.focus();\n this.previouslyFocusedElement = null;\n }\n }\n}\n","@if (visible()) {\n <div\n class=\"fk-drawer__panel\"\n [class.fk-drawer__panel--sm]=\"width() === 'sm'\"\n [class.fk-drawer__panel--md]=\"width() === 'md'\"\n [class.fk-drawer__panel--lg]=\"width() === 'lg'\"\n [class.fk-drawer__panel--xl]=\"width() === 'xl'\"\n [class.fk-drawer__animate-panel--slide-right]=\"\n animation() === 'slide-right' && !animatingOut()\n \"\n [class.fk-drawer__animate-panel--fade]=\"\n animation() === 'fade' && !animatingOut()\n \"\n [class.fk-drawer__animate-panel-out--slide-right]=\"\n animation() === 'slide-right' && animatingOut()\n \"\n [class.fk-drawer__animate-panel-out--fade]=\"\n animation() === 'fade' && animatingOut()\n \"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledBy()\"\n [cdkTrapFocus]=\"true\"\n [cdkTrapFocusAutoCapture]=\"autoFocus()\"\n (animationend)=\"onExitAnimationDone()\"\n >\n @if (header() || closable()) {\n <div class=\"fk-drawer__header\">\n @if (header()) {\n <span class=\"fk-drawer__title\" [id]=\"titleId\">\n {{ header() }}\n </span>\n }\n\n @if (closable()) {\n <button\n class=\"fk-drawer__close\"\n type=\"button\"\n aria-label=\"Close drawer\"\n (click)=\"close()\"\n >\n &times;\n </button>\n }\n </div>\n }\n\n <div class=\"fk-drawer__body\">\n <ng-content />\n </div>\n\n <div class=\"fk-drawer__footer\">\n <ng-content select=\"[fkDrawerFooter]\" />\n </div>\n </div>\n}\n","import type {\n DrawerAnimation,\n DrawerCanCloseFn,\n DrawerWidth,\n} from './drawer.types';\n\nexport interface DrawerConfig<TData = unknown> {\n closable?: boolean;\n closeOnEscape?: boolean;\n closeOnBackdrop?: boolean;\n width?: DrawerWidth;\n animation?: DrawerAnimation;\n header?: string | null;\n restoreFocus?: boolean;\n autoFocus?: boolean;\n preventClose?: boolean;\n canClose?: DrawerCanCloseFn;\n className?: string;\n ariaLabel?: string | null;\n data?: TData;\n}\n\nexport const DEFAULT_DRAWER_CONFIG: DrawerConfig = {\n closable: true,\n closeOnEscape: true,\n closeOnBackdrop: true,\n width: 'md',\n animation: 'slide-right',\n header: null,\n restoreFocus: true,\n autoFocus: true,\n preventClose: false,\n className: '',\n ariaLabel: null,\n};\n","import { Observable, Subject } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\nimport type { DrawerConfig } from './drawer.config';\nimport type { DrawerCanCloseFn } from './drawer.types';\n\nexport class DrawerRef<TResult = unknown, TData = unknown> {\n private readonly beforeOpenSubject = new Subject<void>();\n private readonly afterOpenedSubject = new Subject<void>();\n private readonly beforeCloseSubject = new Subject<void>();\n private readonly afterClosedSubject = new Subject<TResult | undefined>();\n private closed = false;\n private closeGuard: DrawerCanCloseFn | null = null;\n\n readonly config: DrawerConfig<TData>;\n\n constructor(config: DrawerConfig<TData> = {} as DrawerConfig<TData>) {\n this.config = config;\n\n if (config.canClose) {\n this.closeGuard = config.canClose;\n }\n }\n\n get data(): TData | undefined {\n return this.config.data;\n }\n\n setCanClose(guard: DrawerCanCloseFn | null) {\n this.closeGuard = guard;\n }\n\n async close(result?: TResult) {\n if (this.closed) {\n return;\n }\n\n if (this.config.preventClose) {\n return;\n }\n\n if (this.closeGuard) {\n const allowed = await Promise.resolve(this.closeGuard());\n\n if (!allowed) {\n return;\n }\n }\n\n this.beforeCloseSubject.next();\n this.beforeCloseSubject.complete();\n\n this.closed = true;\n this.afterClosedSubject.next(result);\n this.afterClosedSubject.complete();\n }\n\n beforeOpen(): Observable<void> {\n return this.beforeOpenSubject.asObservable().pipe(take(1));\n }\n\n afterOpened(): Observable<void> {\n return this.afterOpenedSubject.asObservable().pipe(take(1));\n }\n\n beforeClose(): Observable<void> {\n return this.beforeCloseSubject.asObservable().pipe(take(1));\n }\n\n afterClosed(): Observable<TResult | undefined> {\n return this.afterClosedSubject.asObservable().pipe(take(1));\n }\n\n /** @internal */\n markBeforeOpen() {\n this.beforeOpenSubject.next();\n this.beforeOpenSubject.complete();\n }\n\n /** @internal */\n markOpened() {\n this.afterOpenedSubject.next();\n this.afterOpenedSubject.complete();\n }\n}\n","import { ESCAPE } from '@angular/cdk/keycodes';\nimport { Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport {\n ApplicationRef,\n ComponentRef,\n createComponent,\n EnvironmentInjector,\n inject,\n Injectable,\n Injector,\n Type,\n} from '@angular/core';\n\nimport { DrawerComponent } from './drawer.component';\nimport { DEFAULT_DRAWER_CONFIG, DrawerConfig } from './drawer.config';\nimport { DrawerRef } from './drawer-ref';\n\nexport const DRAWER_DATA = Symbol('DRAWER_DATA');\nexport const DRAWER_REF = Symbol('DRAWER_REF');\n\ninterface DrawerEntry {\n ref: DrawerRef;\n overlayRef: OverlayRef;\n hostRef: ComponentRef<DrawerComponent>;\n contentRef: ComponentRef<unknown>;\n}\n\n/**\n * Opens drawers as CDK overlays pinned to the right edge.\n *\n * CDK owns the backdrop, scroll blocking, positioning, z-index stacking, and\n * top-of-stack Escape / outside dispatch. The hosted `DrawerComponent` is the\n * panel chrome (header / body / footer, the slide animation, focus trap). A\n * drawer and a dialog opened over it coexist — the dialog stacks on top by\n * open order, and the drawer is no longer evicted.\n */\n@Injectable({ providedIn: 'root' })\nexport class DrawerService {\n private readonly overlay = inject(Overlay);\n private readonly appRef = inject(ApplicationRef);\n private readonly injector = inject(EnvironmentInjector);\n private readonly doc = inject(DOCUMENT);\n\n private activeDrawers: DrawerEntry[] = [];\n\n get openCount(): number {\n return this.activeDrawers.length;\n }\n\n open<TResult = unknown, TData = unknown>(\n content: Type<unknown>,\n config?: DrawerConfig<TData>,\n ): DrawerRef<TResult, TData> {\n const mergedConfig = {\n ...DEFAULT_DRAWER_CONFIG,\n ...config,\n } as DrawerConfig<TData>;\n const drawerRef = new DrawerRef<TResult, TData>(mergedConfig);\n\n const overlayRef = this.overlay.create({\n hasBackdrop: true,\n backdropClass: 'fk-drawer__backdrop',\n panelClass: 'fk-drawer__pane',\n scrollStrategy: this.overlay.scrollStrategies.block(),\n positionStrategy: this.overlay.position().global().right('0').top('0'),\n height: '100%',\n disposeOnNavigation: true,\n });\n\n const childInjector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: DRAWER_DATA as never, useValue: mergedConfig.data },\n { provide: DRAWER_REF as never, useValue: drawerRef },\n ],\n });\n\n const hostRef = overlayRef.attach(\n new ComponentPortal(DrawerComponent, null, childInjector),\n );\n\n const contentRef = createComponent(content, {\n environmentInjector: this.injector,\n elementInjector: childInjector,\n hostElement: this.doc.createElement('div'),\n });\n\n this.appRef.attachView(contentRef.hostView);\n\n const entry: DrawerEntry = {\n ref: drawerRef as DrawerRef<unknown, unknown>,\n overlayRef,\n hostRef,\n contentRef,\n };\n\n this.activeDrawers.push(entry);\n\n this.applyConfig(hostRef, mergedConfig);\n\n overlayRef.keydownEvents().subscribe((event) => {\n if (event.keyCode === ESCAPE && mergedConfig.closeOnEscape) {\n drawerRef.close();\n }\n });\n\n overlayRef.backdropClick().subscribe(() => {\n if (mergedConfig.closeOnBackdrop) {\n drawerRef.close();\n }\n });\n\n hostRef.instance.beforeOpen.subscribe(() => {\n drawerRef.markBeforeOpen();\n });\n\n hostRef.instance.opened.subscribe(() => {\n drawerRef.markOpened();\n });\n\n hostRef.instance.closed.subscribe(() => {\n drawerRef.close();\n });\n\n drawerRef.afterClosed().subscribe(() => {\n this.destroyDrawer(entry);\n });\n\n hostRef.setInput('open', true);\n hostRef.changeDetectorRef.detectChanges();\n\n const panelBody =\n overlayRef.overlayElement.querySelector('.fk-drawer__body');\n\n if (panelBody) {\n panelBody.appendChild(contentRef.location.nativeElement);\n contentRef.changeDetectorRef.detectChanges();\n\n // Move [fkDrawerFooter] elements from the body into the footer wrapper.\n const footerWrapper =\n overlayRef.overlayElement.querySelector('.fk-drawer__footer');\n const footerElements = panelBody.querySelectorAll('[fkDrawerFooter]');\n\n if (footerWrapper) {\n footerElements.forEach((el: Element) => {\n footerWrapper.appendChild(el);\n });\n }\n }\n\n return drawerRef;\n }\n\n closeAll() {\n [...this.activeDrawers].forEach((entry) => entry.ref.close());\n }\n\n private applyConfig(\n hostRef: ComponentRef<DrawerComponent>,\n config: DrawerConfig,\n ) {\n hostRef.setInput('closable', config.closable ?? true);\n hostRef.setInput('width', config.width ?? 'md');\n hostRef.setInput('animation', config.animation ?? 'slide-right');\n hostRef.setInput('header', config.header ?? null);\n hostRef.setInput('restoreFocus', config.restoreFocus ?? true);\n hostRef.setInput('autoFocus', config.autoFocus ?? true);\n hostRef.setInput('className', config.className ?? '');\n hostRef.setInput('preventClose', config.preventClose ?? false);\n hostRef.setInput('canClose', config.canClose ?? null);\n hostRef.setInput('ariaLabel', config.ariaLabel ?? null);\n }\n\n private destroyDrawer(entry: DrawerEntry) {\n const idx = this.activeDrawers.indexOf(entry);\n\n if (idx > -1) {\n this.activeDrawers.splice(idx, 1);\n }\n\n entry.hostRef.setInput('open', false);\n entry.hostRef.changeDetectorRef.detectChanges();\n\n this.appRef.detachView(entry.contentRef.hostView);\n entry.contentRef.destroy();\n\n entry.overlayRef.dispose();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -44,6 +44,13 @@ class NavGroupComponent {
44
44
  * stays untouched regardless of this input.
45
45
  */
46
46
  lockedOpen = input(false, ...(ngDevMode ? [{ debugName: "lockedOpen" }] : /* istanbul ignore next */ []));
47
+ /**
48
+ * When true, renders a chevron at the trailing edge of the trigger row
49
+ * that points right while collapsed and rotates to point down while
50
+ * expanded. Decorative (`aria-hidden`); hidden in rail mode. Off by
51
+ * default so existing consumers are unaffected.
52
+ */
53
+ showChevron = input(false, ...(ngDevMode ? [{ debugName: "showChevron" }] : /* istanbul ignore next */ []));
47
54
  // ===== MODELS =====
48
55
  /** Whether the group is currently expanded, showing projected child links. */
49
56
  expanded = model(false, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
@@ -92,12 +99,12 @@ class NavGroupComponent {
92
99
  this.expanded.update((v) => !v);
93
100
  }
94
101
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
95
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: NavGroupComponent, isStandalone: true, selector: "fk-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, lockedOpen: { classPropertyName: "lockedOpen", publicName: "lockedOpen", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange", requestOpen: "requestOpen" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input \u2014\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}.fk-nav-group__row{display:flex;align-items:center;gap:var(--fk-nav-group-row-gap, var(--fk-rhythm-1, .25rem))}.fk-nav-group__link{flex:1;min-width:0}.fk-nav-group__children{display:flex;flex-direction:column;gap:var(--fk-nav-group-children-gap, var(--fk-rhythm-1, .25rem));padding-left:var(--fk-nav-group-children-indent, var(--fk-rhythm-6, 1.5rem));margin-top:var(--fk-nav-group-children-offset, var(--fk-rhythm-1, .25rem))}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: SidenavLinkComponent, selector: "fk-sidenav-link", inputs: ["icon", "iconSize", "label", "routerLink", "exact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
102
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: NavGroupComponent, isStandalone: true, selector: "fk-nav-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, lockedOpen: { classPropertyName: "lockedOpen", publicName: "lockedOpen", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange", requestOpen: "requestOpen" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n\n @if (showChevron()) {\n <span\n class=\"fk-nav-group__chevron\"\n [class.fk-nav-group__chevron--open]=\"expanded()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-nav-group__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input \u2014\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}.fk-nav-group__row{display:flex;align-items:center;gap:var(--fk-nav-group-row-gap, var(--fk-rhythm-1, .25rem))}.fk-nav-group__link{flex:1;min-width:0}.fk-nav-group__chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--fk-nav-group-chevron-color, var(--fk-color-muted, #64748b));transform:rotate(-90deg);transition:transform .15s ease}.fk-nav-group__chevron--open{transform:rotate(0)}.fk-nav-group__chevron-svg{display:block}:host(.fk-nav-group--collapsed) .fk-nav-group__chevron{display:none}.fk-nav-group__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-nav-group-children-gap, var(--fk-rhythm-1, .25rem));padding-left:var(--fk-nav-group-children-indent, var(--fk-rhythm-6, 1.5rem));margin-top:var(--fk-nav-group-children-offset, var(--fk-rhythm-1, .25rem))}.fk-nav-group__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-nav-group-children-border-offset, var(--fk-sidenav-link-padding-inline, var(--fk-rhythm-3, .75rem)));width:var(--fk-nav-group-children-border-width, var(--fk-border-width, 1px));background:var(--fk-nav-group-children-border-color, var(--fk-color-border, #d9e2ee))}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: SidenavLinkComponent, selector: "fk-sidenav-link", inputs: ["icon", "iconSize", "label", "routerLink", "exact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
96
103
  }
97
104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavGroupComponent, decorators: [{
98
105
  type: Component,
99
- args: [{ selector: 'fk-nav-group', standalone: true, imports: [RouterModule, SidenavLinkComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input \u2014\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}.fk-nav-group__row{display:flex;align-items:center;gap:var(--fk-nav-group-row-gap, var(--fk-rhythm-1, .25rem))}.fk-nav-group__link{flex:1;min-width:0}.fk-nav-group__children{display:flex;flex-direction:column;gap:var(--fk-nav-group-children-gap, var(--fk-rhythm-1, .25rem));padding-left:var(--fk-nav-group-children-indent, var(--fk-rhythm-6, 1.5rem));margin-top:var(--fk-nav-group-children-offset, var(--fk-rhythm-1, .25rem))}\n"] }]
100
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], lockedOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockedOpen", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], requestOpen: [{ type: i0.Output, args: ["requestOpen"] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], hostClass: [{
106
+ args: [{ selector: 'fk-nav-group', standalone: true, imports: [RouterModule, SidenavLinkComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n\n @if (showChevron()) {\n <span\n class=\"fk-nav-group__chevron\"\n [class.fk-nav-group__chevron--open]=\"expanded()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-nav-group__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input \u2014\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}.fk-nav-group__row{display:flex;align-items:center;gap:var(--fk-nav-group-row-gap, var(--fk-rhythm-1, .25rem))}.fk-nav-group__link{flex:1;min-width:0}.fk-nav-group__chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--fk-nav-group-chevron-color, var(--fk-color-muted, #64748b));transform:rotate(-90deg);transition:transform .15s ease}.fk-nav-group__chevron--open{transform:rotate(0)}.fk-nav-group__chevron-svg{display:block}:host(.fk-nav-group--collapsed) .fk-nav-group__chevron{display:none}.fk-nav-group__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-nav-group-children-gap, var(--fk-rhythm-1, .25rem));padding-left:var(--fk-nav-group-children-indent, var(--fk-rhythm-6, 1.5rem));margin-top:var(--fk-nav-group-children-offset, var(--fk-rhythm-1, .25rem))}.fk-nav-group__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-nav-group-children-border-offset, var(--fk-sidenav-link-padding-inline, var(--fk-rhythm-3, .75rem)));width:var(--fk-nav-group-children-border-width, var(--fk-border-width, 1px));background:var(--fk-nav-group-children-border-color, var(--fk-color-border, #d9e2ee))}\n"] }]
107
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], lockedOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockedOpen", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], requestOpen: [{ type: i0.Output, args: ["requestOpen"] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], hostClass: [{
101
108
  type: HostBinding,
102
109
  args: ['class']
103
110
  }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"frame-kit-ui-ng-ui-nav-group.mjs","sources":["../../../../packages/ui-ng/ui/nav-group/nav-group.component.ts","../../../../packages/ui-ng/ui/nav-group/nav-group.component.html","../../../../packages/ui-ng/ui/nav-group/frame-kit-ui-ng-ui-nav-group.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n model,\n output,\n} from '@angular/core';\nimport { RouterModule } from '@angular/router';\n\nimport type { IconSize } from '@frame-kit/ui-ng/core/icon';\nimport { SidenavLinkComponent } from '@frame-kit/ui-ng/ui/sidenav-link';\n\n/**\n * Expandable nav group — renders a trigger row (icon + label, optionally\n * linked) and reveals projected children when `expanded` is true. Designed\n * to sit inside a collapsible sidenav: when the outer shell is collapsed,\n * clicking the row emits `requestOpen` so the host can pop the sidenav\n * open, and the group auto-expands once it's visible.\n */\n@Component({\n selector: 'fk-nav-group',\n standalone: true,\n imports: [RouterModule, SidenavLinkComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nav-group.component.html',\n styleUrl: './nav-group.component.scss',\n})\nexport class NavGroupComponent {\n // ===== INPUTS =====\n /** Primary label text shown in the group trigger row. */\n readonly label = input.required<string>();\n /** Optional icon name shown to the leading side of the label. */\n readonly icon = input<string | null>(null);\n /** Size of the leading icon. */\n readonly iconSize = input<IconSize>('sm');\n /** Optional router path; when set, the trigger navigates on click in expanded sidenav mode. */\n readonly routerLink = input<string | string[] | null>(null);\n\n /**\n * True when the containing sidenav is in its collapsed rail state.\n * In that mode, clicking the trigger BOTH navigates via\n * `routerLink` AND emits `requestOpen` so the host can expand the\n * outer shell — the user lands on the group's route with the\n * sidenav already open. The trigger never expands its own children\n * inside the rail (no horizontal room); the rail-to-expanded\n * transition is what reveals them.\n */\n readonly collapsed = input<boolean>(false);\n\n /**\n * When true and the sidenav is in its expanded state, clicking the\n * trigger row does NOT fold the group — children stay visible.\n * Useful when the group's children are permanent navigation rather\n * than a collapsible disclosure (e.g. a parent nav item that should\n * always show its sub-pages while the sidenav is open). Clicks on\n * the trigger still navigate via `routerLink`.\n *\n * Has no effect in collapsed (rail) mode — clicks there still\n * navigate via `routerLink` and emit `requestOpen`, and `expanded`\n * stays untouched regardless of this input.\n */\n readonly lockedOpen = input<boolean>(false);\n\n // ===== MODELS =====\n /** Whether the group is currently expanded, showing projected child links. */\n readonly expanded = model<boolean>(false);\n\n // ===== OUTPUTS =====\n /**\n * Emitted when the group is clicked while the outer sidenav is\n * collapsed. Hosts typically listen to open their collapsible shell\n * so the projected children become visible.\n */\n readonly requestOpen = output<void>();\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return [\n 'fk-nav-group',\n this.expanded() ? 'fk-nav-group--expanded' : '',\n this.collapsed() ? 'fk-nav-group--collapsed' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n protected toggle(): void {\n if (this.collapsed()) {\n // In rail mode the children must not render inside the rail —\n // there's no horizontal room and the visual hierarchy collapses.\n // Just ask the host to expand the sidenav; once it does and\n // `collapsed` flips to false, the consumer's `[expanded]`\n // binding can push true and the children render in the now-open\n // sidenav. We DO NOT set `expanded` here, so a click in rail\n // mode never reveals children inside the rail itself.\n this.requestOpen.emit();\n\n return;\n }\n\n // Locked-open: in expanded sidenav mode, the trigger no longer\n // folds the group on click. Navigation via `routerLink` still\n // fires from the inner sidenav-link; this branch just suppresses\n // the toggle behavior so children stay visible.\n if (this.lockedOpen()) {\n return;\n }\n\n this.expanded.update((v) => !v);\n }\n}\n","<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input —\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frame-kit-ui-ng-ui-nav-group.mjs","sources":["../../../../packages/ui-ng/ui/nav-group/nav-group.component.ts","../../../../packages/ui-ng/ui/nav-group/nav-group.component.html","../../../../packages/ui-ng/ui/nav-group/frame-kit-ui-ng-ui-nav-group.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n model,\n output,\n} from '@angular/core';\nimport { RouterModule } from '@angular/router';\n\nimport type { IconSize } from '@frame-kit/ui-ng/core/icon';\nimport { SidenavLinkComponent } from '@frame-kit/ui-ng/ui/sidenav-link';\n\n/**\n * Expandable nav group — renders a trigger row (icon + label, optionally\n * linked) and reveals projected children when `expanded` is true. Designed\n * to sit inside a collapsible sidenav: when the outer shell is collapsed,\n * clicking the row emits `requestOpen` so the host can pop the sidenav\n * open, and the group auto-expands once it's visible.\n */\n@Component({\n selector: 'fk-nav-group',\n standalone: true,\n imports: [RouterModule, SidenavLinkComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './nav-group.component.html',\n styleUrl: './nav-group.component.scss',\n})\nexport class NavGroupComponent {\n // ===== INPUTS =====\n /** Primary label text shown in the group trigger row. */\n readonly label = input.required<string>();\n /** Optional icon name shown to the leading side of the label. */\n readonly icon = input<string | null>(null);\n /** Size of the leading icon. */\n readonly iconSize = input<IconSize>('sm');\n /** Optional router path; when set, the trigger navigates on click in expanded sidenav mode. */\n readonly routerLink = input<string | string[] | null>(null);\n\n /**\n * True when the containing sidenav is in its collapsed rail state.\n * In that mode, clicking the trigger BOTH navigates via\n * `routerLink` AND emits `requestOpen` so the host can expand the\n * outer shell — the user lands on the group's route with the\n * sidenav already open. The trigger never expands its own children\n * inside the rail (no horizontal room); the rail-to-expanded\n * transition is what reveals them.\n */\n readonly collapsed = input<boolean>(false);\n\n /**\n * When true and the sidenav is in its expanded state, clicking the\n * trigger row does NOT fold the group — children stay visible.\n * Useful when the group's children are permanent navigation rather\n * than a collapsible disclosure (e.g. a parent nav item that should\n * always show its sub-pages while the sidenav is open). Clicks on\n * the trigger still navigate via `routerLink`.\n *\n * Has no effect in collapsed (rail) mode — clicks there still\n * navigate via `routerLink` and emit `requestOpen`, and `expanded`\n * stays untouched regardless of this input.\n */\n readonly lockedOpen = input<boolean>(false);\n\n /**\n * When true, renders a chevron at the trailing edge of the trigger row\n * that points right while collapsed and rotates to point down while\n * expanded. Decorative (`aria-hidden`); hidden in rail mode. Off by\n * default so existing consumers are unaffected.\n */\n readonly showChevron = input<boolean>(false);\n\n // ===== MODELS =====\n /** Whether the group is currently expanded, showing projected child links. */\n readonly expanded = model<boolean>(false);\n\n // ===== OUTPUTS =====\n /**\n * Emitted when the group is clicked while the outer sidenav is\n * collapsed. Hosts typically listen to open their collapsible shell\n * so the projected children become visible.\n */\n readonly requestOpen = output<void>();\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return [\n 'fk-nav-group',\n this.expanded() ? 'fk-nav-group--expanded' : '',\n this.collapsed() ? 'fk-nav-group--collapsed' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n protected toggle(): void {\n if (this.collapsed()) {\n // In rail mode the children must not render inside the rail —\n // there's no horizontal room and the visual hierarchy collapses.\n // Just ask the host to expand the sidenav; once it does and\n // `collapsed` flips to false, the consumer's `[expanded]`\n // binding can push true and the children render in the now-open\n // sidenav. We DO NOT set `expanded` here, so a click in rail\n // mode never reveals children inside the rail itself.\n this.requestOpen.emit();\n\n return;\n }\n\n // Locked-open: in expanded sidenav mode, the trigger no longer\n // folds the group on click. Navigation via `routerLink` still\n // fires from the inner sidenav-link; this branch just suppresses\n // the toggle behavior so children stay visible.\n if (this.lockedOpen()) {\n return;\n }\n\n this.expanded.update((v) => !v);\n }\n}\n","<div class=\"fk-nav-group__row\" role=\"presentation\" (click)=\"toggle()\">\n <fk-sidenav-link\n class=\"fk-nav-group__link\"\n [icon]=\"icon() ?? ''\"\n [iconSize]=\"iconSize()\"\n [label]=\"label()\"\n [routerLink]=\"routerLink()\"\n />\n\n @if (showChevron()) {\n <span\n class=\"fk-nav-group__chevron\"\n [class.fk-nav-group__chevron--open]=\"expanded()\"\n aria-hidden=\"true\"\n >\n <svg\n class=\"fk-nav-group__chevron-svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n >\n <path\n d=\"M4.5 6.75L9 11.25L13.5 6.75\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n }\n</div>\n\n@if (expanded()) {\n <!--\n Stop child clicks from bubbling to the fk-nav-group host. When a\n consumer binds [routerLink] on <fk-nav-group>, Angular attaches the\n RouterLink directive to the host element in addition to our input —\n so an un-stopped child click would re-navigate to the parent URL\n after the child's own RouterLink fires. This is an event absorber,\n not an interactive element; keyboard activation fires click events\n that bubble through the same path, so the a11y rules don't apply.\n -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"fk-nav-group__children\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAcA;;;;;;AAMG;MASU,iBAAiB,CAAA;;;AAGnB,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,2EAAU;;AAEhC,IAAA,IAAI,GAAG,KAAK,CAAgB,IAAI,2EAAC;;AAEjC,IAAA,QAAQ,GAAG,KAAK,CAAW,IAAI,+EAAC;;AAEhC,IAAA,UAAU,GAAG,KAAK,CAA2B,IAAI,iFAAC;AAE3D;;;;;;;;AAQG;AACM,IAAA,SAAS,GAAG,KAAK,CAAU,KAAK,gFAAC;AAE1C;;;;;;;;;;;AAWG;AACM,IAAA,UAAU,GAAG,KAAK,CAAU,KAAK,iFAAC;AAE3C;;;;;AAKG;AACM,IAAA,WAAW,GAAG,KAAK,CAAU,KAAK,kFAAC;;;AAInC,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC;;AAGzC;;;;AAIG;IACM,WAAW,GAAG,MAAM,EAAQ;;AAG5B,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;;AAG7B,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;QAC/B,OAAO;YACL,cAAc;YACd,IAAI,CAAC,QAAQ,EAAE,GAAG,wBAAwB,GAAG,EAAE;YAC/C,IAAI,CAAC,SAAS,EAAE,GAAG,yBAAyB,GAAG,EAAE;YACjD,IAAI,CAAC,SAAS,EAAE;AACjB;aACE,MAAM,CAAC,OAAO;aACd,IAAI,CAAC,GAAG,CAAC;AACd,IAAA,CAAC,8EAAC;AAEF,IAAA,IACI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;IAEU,MAAM,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;;;;;;;;AAQpB,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;YAEvB;QACF;;;;;AAMA,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;YACrB;QACF;AAEA,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACjC;uGAnGW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,iBAAiB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC7B9B,8pDAkDA,EAAA,MAAA,EAAA,CAAA,wrCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,ED1BY,YAAY,gRAAE,oBAAoB,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,OAAA,EAAA,YAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAKjC,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAR7B,SAAS;+BACE,cAAc,EAAA,UAAA,EACZ,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,oBAAoB,CAAC,EAAA,eAAA,EAC5B,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,8pDAAA,EAAA,MAAA,EAAA,CAAA,wrCAAA,CAAA,EAAA;;sBA2E9C,WAAW;uBAAC,OAAO;;;AEpGtB;;AAEG;;;;"}
@@ -10,7 +10,6 @@ export * from '@frame-kit/ui-ng/directives/tooltip';
10
10
  export * from '@frame-kit/ui-ng/forms';
11
11
  export * from '@frame-kit/ui-ng/layouts/app-shell';
12
12
  export * from '@frame-kit/ui-ng/layouts/content-split';
13
- export * from '@frame-kit/ui-ng/services/overlay-orchestrator';
14
13
  export * from '@frame-kit/ui-ng/services/spotlight';
15
14
  export * from '@frame-kit/ui-ng/services/toast';
16
15
  export * from '@frame-kit/ui-ng/ui/accordion';
@@ -1 +1 @@
1
- {"version":3,"file":"frame-kit-ui-ng.mjs","sources":["../../../../packages/ui-ng/frame-kit-ui-ng.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAEG"}
1
+ {"version":3,"file":"frame-kit-ui-ng.mjs","sources":["../../../../packages/ui-ng/frame-kit-ui-ng.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AAEG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frame-kit/ui-ng",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Style-agnostic, token-driven Angular UI component library for FrameKit.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -81,10 +81,6 @@
81
81
  "types": "./types/frame-kit-ui-ng-layouts-content-split.d.ts",
82
82
  "default": "./fesm2022/frame-kit-ui-ng-layouts-content-split.mjs"
83
83
  },
84
- "./services/overlay-orchestrator": {
85
- "types": "./types/frame-kit-ui-ng-services-overlay-orchestrator.d.ts",
86
- "default": "./fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs"
87
- },
88
84
  "./services/spotlight": {
89
85
  "types": "./types/frame-kit-ui-ng-services-spotlight.d.ts",
90
86
  "default": "./fesm2022/frame-kit-ui-ng-services-spotlight.mjs"
@@ -21,9 +21,6 @@ declare class AppShellComponent {
21
21
  readonly endWidth: _angular_core.InputSignal<string>;
22
22
  /** Width of the end panel when collapsed to icon-rail mode. */
23
23
  readonly endCollapsedWidth: _angular_core.InputSignal<string>;
24
- private readonly orchestrator;
25
- private navOverlayId;
26
- private endOverlayId;
27
24
  readonly stickyPreference: _angular_core.WritableSignal<"closed" | null>;
28
25
  readonly tempOpen: _angular_core.WritableSignal<boolean>;
29
26
  readonly isMobile: _angular_core.WritableSignal<boolean>;
@@ -51,21 +48,21 @@ declare class AppShellComponent {
51
48
  private readonly breakpointObserver;
52
49
  private readonly destroyRef;
53
50
  constructor();
54
- /** Open the primary sidenav, registering it with the overlay orchestrator on mobile. */
51
+ /** Open the primary sidenav (temporary overlay on mobile). */
55
52
  openSidenav(): void;
56
- /** Close the primary sidenav and unregister it from the overlay orchestrator. */
53
+ /** Close the primary sidenav. */
57
54
  closeSidenav(): void;
58
55
  /** Toggle the primary sidenav between open and closed. */
59
56
  toggleSidenav(): void;
60
57
  /** Dismiss the sidenav overlay on mobile without marking it as permanently closed. */
61
58
  dismissSidenav(): void;
62
- /** Open the end panel, registering it with the overlay orchestrator on mobile. */
59
+ /** Open the end panel (temporary overlay on mobile). */
63
60
  openEnd(): void;
64
- /** Close the end panel and unregister it from the overlay orchestrator. */
61
+ /** Close the end panel. */
65
62
  closeEnd(): void;
66
63
  /** Toggle the end panel between open and closed. */
67
64
  toggleEnd(): void;
68
- /** Dismiss the end panel overlay and unregister it from the overlay orchestrator. */
65
+ /** Dismiss the end panel overlay. */
69
66
  dismissEnd(): void;
70
67
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AppShellComponent, never>;
71
68
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<AppShellComponent, "fk-app-shell", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "sidenavWidth": { "alias": "sidenavWidth"; "required": false; "isSignal": true; }; "collapsedWidth": { "alias": "collapsedWidth"; "required": false; "isSignal": true; }; "breakpoint": { "alias": "breakpoint"; "required": false; "isSignal": true; }; "sticky": { "alias": "sticky"; "required": false; "isSignal": true; }; "collapseOnMobile": { "alias": "collapseOnMobile"; "required": false; "isSignal": true; }; "endMode": { "alias": "endMode"; "required": false; "isSignal": true; }; "endWidth": { "alias": "endWidth"; "required": false; "isSignal": true; }; "endCollapsedWidth": { "alias": "endCollapsedWidth"; "required": false; "isSignal": true; }; }, {}, never, ["[appShellHeader]", "[appShellSidenav]", "[appShellContent]", "[appShellEnd]", "[appShellFooter]"], true, never>;
@@ -1,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { Type, ComponentRef } from '@angular/core';
2
+ import { Type } from '@angular/core';
3
3
  import { Observable } from 'rxjs';
4
4
 
5
5
  type DialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'fullscreen';
@@ -12,17 +12,22 @@ declare class FkDialogHeaderDirective {
12
12
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<FkDialogHeaderDirective, "[fkDialogHeader]", never, {}, {}, never, never, true, never>;
13
13
  }
14
14
 
15
+ /**
16
+ * Dialog panel chrome.
17
+ *
18
+ * Hosted inside a CDK overlay by `DialogService`, so the overlay layer owns
19
+ * the backdrop, scroll blocking, positioning, stacking, and Escape / outside
20
+ * dispatch. This component renders the panel itself: header / body / footer
21
+ * projection, sizing, the enter animation, focus trapping, and the close
22
+ * guard.
23
+ */
15
24
  declare class DialogComponent {
16
25
  /** Controls whether the dialog is open. */
17
26
  readonly open: _angular_core.InputSignal<boolean>;
18
- /** When true, renders a backdrop overlay behind the dialog. */
27
+ /** When true, marks the panel `aria-modal` and traps focus. */
19
28
  readonly modal: _angular_core.InputSignal<boolean>;
20
29
  /** When true, shows the close button in the dialog header. */
21
30
  readonly closable: _angular_core.InputSignal<boolean>;
22
- /** When true, pressing Escape closes the dialog. */
23
- readonly closeOnEscape: _angular_core.InputSignal<boolean>;
24
- /** When true, clicking the backdrop overlay closes the dialog. */
25
- readonly closeOnBackdrop: _angular_core.InputSignal<boolean>;
26
31
  /** Size variant that controls the dialog's max-width. */
27
32
  readonly size: _angular_core.InputSignal<DialogSize>;
28
33
  /** Where the dialog is anchored on screen. */
@@ -59,10 +64,8 @@ declare class DialogComponent {
59
64
  /** Fires after the dialog is fully closed. */
60
65
  readonly closed: _angular_core.OutputEmitterRef<void>;
61
66
  private readonly doc;
62
- private readonly destroyRef;
63
67
  readonly titleId: string;
64
68
  private previouslyFocusedElement;
65
- private bodyScrollLocked;
66
69
  private closeGuardRunning;
67
70
  /** Whether the dialog DOM is rendered (stays true during exit animation). */
68
71
  readonly visible: _angular_core.WritableSignal<boolean>;
@@ -73,18 +76,14 @@ declare class DialogComponent {
73
76
  constructor();
74
77
  get hostClass(): string;
75
78
  get hostId(): string | null;
76
- onEscapeKey(): void;
77
79
  /** Closes the dialog, running any `canClose` guard first; no-ops when `preventClose` is true. */
78
80
  close(): Promise<void>;
79
- onOverlayClick(): void;
80
- /** Called when the overlay exit animation finishes. */
81
+ /** Called when the panel exit animation finishes. */
81
82
  onExitAnimationDone(): void;
82
83
  private onDialogOpen;
83
84
  private onDialogClose;
84
- private lockBodyScroll;
85
- private unlockBodyScroll;
86
85
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DialogComponent, never>;
87
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DialogComponent, "fk-dialog", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "closeOnEscape": { "alias": "closeOnEscape"; "required": false; "isSignal": true; }; "closeOnBackdrop": { "alias": "closeOnBackdrop"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "animation": { "alias": "animation"; "required": false; "isSignal": true; }; "preventClose": { "alias": "preventClose"; "required": false; "isSignal": true; }; "canClose": { "alias": "canClose"; "required": false; "isSignal": true; }; "fullscreenMobile": { "alias": "fullscreenMobile"; "required": false; "isSignal": true; }; "flexBody": { "alias": "flexBody"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaDescribedBy": { "alias": "ariaDescribedBy"; "required": false; "isSignal": true; }; }, { "openChange": "openChange"; "beforeOpen": "beforeOpen"; "opened": "opened"; "beforeClose": "beforeClose"; "closed": "closed"; }, ["customHeader"], ["[fkDialogHeader]", "*", "[libDialogFooter]"], true, never>;
86
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DialogComponent, "fk-dialog", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "animation": { "alias": "animation"; "required": false; "isSignal": true; }; "preventClose": { "alias": "preventClose"; "required": false; "isSignal": true; }; "canClose": { "alias": "canClose"; "required": false; "isSignal": true; }; "fullscreenMobile": { "alias": "fullscreenMobile"; "required": false; "isSignal": true; }; "flexBody": { "alias": "flexBody"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaDescribedBy": { "alias": "ariaDescribedBy"; "required": false; "isSignal": true; }; }, { "openChange": "openChange"; "beforeOpen": "beforeOpen"; "opened": "opened"; "beforeClose": "beforeClose"; "closed": "closed"; }, ["customHeader"], ["[fkDialogHeader]", "*", "[libDialogFooter]"], true, never>;
88
87
  }
89
88
 
90
89
  interface DialogConfig<TData = unknown> {
@@ -133,24 +132,26 @@ declare class DialogRef<TResult = unknown, TData = unknown> {
133
132
 
134
133
  declare const DIALOG_DATA: unique symbol;
135
134
  declare const DIALOG_REF: unique symbol;
136
- interface DialogEntry {
137
- ref: DialogRef;
138
- hostRef: ComponentRef<DialogComponent>;
139
- contentRef: ComponentRef<unknown>;
140
- }
135
+ /**
136
+ * Opens dialogs as CDK overlays.
137
+ *
138
+ * CDK owns the cross-cutting overlay concerns — backdrop, scroll blocking,
139
+ * centered positioning, z-index stacking (overlays layer by open order), and
140
+ * top-of-stack dispatch of Escape / outside clicks. The `DialogComponent` it
141
+ * hosts is just the panel chrome (header / body / footer, sizing, enter
142
+ * animation, focus trap). There is no global "opening X closes lower overlays"
143
+ * rule: a dialog opened over a drawer stacks on top of it, and Escape / an
144
+ * outside press dismisses whichever overlay is on top.
145
+ */
141
146
  declare class DialogService {
147
+ private readonly overlay;
142
148
  private readonly appRef;
143
149
  private readonly injector;
144
150
  private readonly doc;
145
- private readonly orchestrator;
146
151
  private activeDialogs;
147
- private overlayIds;
148
152
  get openCount(): number;
149
153
  open<TResult = unknown, TData = unknown>(content: Type<unknown>, config?: DialogConfig<TData>): DialogRef<TResult, TData>;
150
154
  closeAll(): void;
151
- /** Returns true if the given entry is the topmost (last) active dialog. */
152
- isTopmost(entry: DialogEntry): boolean;
153
- private applyZIndex;
154
155
  private applyConfig;
155
156
  private destroyDialog;
156
157
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DialogService, never>;
@@ -6,15 +6,19 @@ type DrawerWidth = 'sm' | 'md' | 'lg' | 'xl';
6
6
  type DrawerAnimation = 'slide-right' | 'fade' | 'none';
7
7
  type DrawerCanCloseFn = () => boolean | Promise<boolean>;
8
8
 
9
+ /**
10
+ * Drawer panel chrome.
11
+ *
12
+ * Hosted inside a CDK overlay by `DrawerService`, which owns the backdrop,
13
+ * scroll blocking, positioning, stacking, and Escape / outside dispatch. This
14
+ * component renders the sliding panel: header / body / footer projection,
15
+ * width sizing, the slide animation, focus trapping, and the close guard.
16
+ */
9
17
  declare class DrawerComponent {
10
18
  /** Controls whether the drawer is open. */
11
19
  readonly open: _angular_core.InputSignal<boolean>;
12
20
  /** When true, shows the close button in the drawer header. */
13
21
  readonly closable: _angular_core.InputSignal<boolean>;
14
- /** When true, pressing Escape closes the drawer. */
15
- readonly closeOnEscape: _angular_core.InputSignal<boolean>;
16
- /** When true, clicking the backdrop overlay closes the drawer. */
17
- readonly closeOnBackdrop: _angular_core.InputSignal<boolean>;
18
22
  /** Width variant of the drawer panel. */
19
23
  readonly width: _angular_core.InputSignal<DrawerWidth>;
20
24
  /** Optional title text rendered in the drawer header. */
@@ -43,7 +47,6 @@ declare class DrawerComponent {
43
47
  /** Fires after the drawer is fully closed. */
44
48
  readonly closed: _angular_core.OutputEmitterRef<void>;
45
49
  private readonly doc;
46
- private readonly destroyRef;
47
50
  readonly titleId: string;
48
51
  private previouslyFocusedElement;
49
52
  private closeGuardRunning;
@@ -54,15 +57,14 @@ declare class DrawerComponent {
54
57
  constructor();
55
58
  get hostClass(): string;
56
59
  get hostId(): string | null;
57
- onEscapeKey(): void;
58
60
  /** Closes the drawer, running any `canClose` guard first; no-ops when `preventClose` is true. */
59
61
  close(): Promise<void>;
60
- onOverlayClick(): void;
62
+ /** Called when the panel exit animation finishes. */
61
63
  onExitAnimationDone(): void;
62
64
  private onDrawerOpen;
63
65
  private onDrawerClose;
64
66
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DrawerComponent, never>;
65
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DrawerComponent, "fk-drawer", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "closeOnEscape": { "alias": "closeOnEscape"; "required": false; "isSignal": true; }; "closeOnBackdrop": { "alias": "closeOnBackdrop"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "animation": { "alias": "animation"; "required": false; "isSignal": true; }; "preventClose": { "alias": "preventClose"; "required": false; "isSignal": true; }; "canClose": { "alias": "canClose"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "openChange": "openChange"; "beforeOpen": "beforeOpen"; "opened": "opened"; "beforeClose": "beforeClose"; "closed": "closed"; }, never, ["*", "[fkDrawerFooter]"], true, never>;
67
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DrawerComponent, "fk-drawer", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "closable": { "alias": "closable"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; "animation": { "alias": "animation"; "required": false; "isSignal": true; }; "preventClose": { "alias": "preventClose"; "required": false; "isSignal": true; }; "canClose": { "alias": "canClose"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "openChange": "openChange"; "beforeOpen": "beforeOpen"; "opened": "opened"; "beforeClose": "beforeClose"; "closed": "closed"; }, never, ["*", "[fkDrawerFooter]"], true, never>;
66
68
  }
67
69
 
68
70
  interface DrawerConfig<TData = unknown> {
@@ -79,8 +81,6 @@ interface DrawerConfig<TData = unknown> {
79
81
  className?: string;
80
82
  ariaLabel?: string | null;
81
83
  data?: TData;
82
- /** Element to append the drawer into. Must have `position: relative`. Defaults to `document.body`. */
83
- container?: HTMLElement;
84
84
  }
85
85
  declare const DEFAULT_DRAWER_CONFIG: DrawerConfig;
86
86
 
@@ -108,18 +108,24 @@ declare class DrawerRef<TResult = unknown, TData = unknown> {
108
108
 
109
109
  declare const DRAWER_DATA: unique symbol;
110
110
  declare const DRAWER_REF: unique symbol;
111
+ /**
112
+ * Opens drawers as CDK overlays pinned to the right edge.
113
+ *
114
+ * CDK owns the backdrop, scroll blocking, positioning, z-index stacking, and
115
+ * top-of-stack Escape / outside dispatch. The hosted `DrawerComponent` is the
116
+ * panel chrome (header / body / footer, the slide animation, focus trap). A
117
+ * drawer and a dialog opened over it coexist — the dialog stacks on top by
118
+ * open order, and the drawer is no longer evicted.
119
+ */
111
120
  declare class DrawerService {
121
+ private readonly overlay;
112
122
  private readonly appRef;
113
123
  private readonly injector;
114
124
  private readonly doc;
115
- private readonly orchestrator;
116
125
  private activeDrawers;
117
- private overlayIds;
118
126
  get openCount(): number;
119
127
  open<TResult = unknown, TData = unknown>(content: Type<unknown>, config?: DrawerConfig<TData>): DrawerRef<TResult, TData>;
120
128
  closeAll(): void;
121
- private applyContainerBounds;
122
- private applyZIndex;
123
129
  private applyConfig;
124
130
  private destroyDrawer;
125
131
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DrawerService, never>;
@@ -41,6 +41,13 @@ declare class NavGroupComponent {
41
41
  * stays untouched regardless of this input.
42
42
  */
43
43
  readonly lockedOpen: _angular_core.InputSignal<boolean>;
44
+ /**
45
+ * When true, renders a chevron at the trailing edge of the trigger row
46
+ * that points right while collapsed and rotates to point down while
47
+ * expanded. Decorative (`aria-hidden`); hidden in rail mode. Off by
48
+ * default so existing consumers are unaffected.
49
+ */
50
+ readonly showChevron: _angular_core.InputSignal<boolean>;
44
51
  /** Whether the group is currently expanded, showing projected child links. */
45
52
  readonly expanded: _angular_core.ModelSignal<boolean>;
46
53
  /**
@@ -54,7 +61,7 @@ declare class NavGroupComponent {
54
61
  get hostClass(): string;
55
62
  protected toggle(): void;
56
63
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NavGroupComponent, never>;
57
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NavGroupComponent, "fk-nav-group", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconSize": { "alias": "iconSize"; "required": false; "isSignal": true; }; "routerLink": { "alias": "routerLink"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "lockedOpen": { "alias": "lockedOpen"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; }, { "expanded": "expandedChange"; "requestOpen": "requestOpen"; }, never, ["*"], true, never>;
64
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NavGroupComponent, "fk-nav-group", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconSize": { "alias": "iconSize"; "required": false; "isSignal": true; }; "routerLink": { "alias": "routerLink"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "lockedOpen": { "alias": "lockedOpen"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; }, { "expanded": "expandedChange"; "requestOpen": "requestOpen"; }, never, ["*"], true, never>;
58
65
  }
59
66
 
60
67
  export { NavGroupComponent };
@@ -10,7 +10,6 @@ export * from '@frame-kit/ui-ng/directives/tooltip';
10
10
  export * from '@frame-kit/ui-ng/forms';
11
11
  export * from '@frame-kit/ui-ng/layouts/app-shell';
12
12
  export * from '@frame-kit/ui-ng/layouts/content-split';
13
- export * from '@frame-kit/ui-ng/services/overlay-orchestrator';
14
13
  export * from '@frame-kit/ui-ng/services/spotlight';
15
14
  export * from '@frame-kit/ui-ng/services/toast';
16
15
  export * from '@frame-kit/ui-ng/ui/accordion';
@@ -178,10 +178,6 @@ canClose = async () => {
178
178
  `fk-dialog` uses the following design tokens:
179
179
 
180
180
  ```scss
181
- // Overlay
182
- --fk-dialog-overlay-bg
183
- --fk-dialog-overlay-z-index
184
-
185
181
  // Panel
186
182
  --fk-dialog-panel-bg
187
183
  --fk-dialog-panel-border-radius
@@ -224,10 +224,6 @@ canClose = async () => {
224
224
  `fk-drawer` uses the following design tokens:
225
225
 
226
226
  ```scss
227
- // Overlay
228
- --fk-drawer-overlay-bg
229
- --fk-drawer-overlay-z-index
230
-
231
227
  // Panel
232
228
  --fk-drawer-bg
233
229
  --fk-drawer-border-color