{"version":3,"file":"ngx-core-components-dialog.mjs","sources":["../../../projects/ngx-core-components/dialog/dialog-container.component.ts","../../../projects/ngx-core-components/dialog/dialog.service.ts","../../../projects/ngx-core-components/dialog/public-api.ts","../../../projects/ngx-core-components/dialog/ngx-core-components-dialog.ts"],"sourcesContent":["import {\n  Component, ChangeDetectionStrategy, ViewChild, ViewContainerRef,\n  ViewRef, ChangeDetectorRef, inject, ElementRef, HostListener\n} from '@angular/core';\n\n/**\n * DialogContainerComponent — the floating shell rendered by DialogService.\n *\n * It renders:\n *   • A full-screen semi-transparent backdrop\n *   • A centered panel that hosts the user-provided content component\n *\n * The service programmatically attaches a content ViewRef into the\n * `contentOutlet` ViewContainerRef after construction.\n */\n@Component({\n  selector: 'ngx-dialog-container',\n  standalone: true,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    <div\n      class=\"ngx-dialog-backdrop\"\n      (click)=\"onBackdropClick()\"\n      role=\"presentation\"\n    >\n      <div\n        class=\"ngx-dialog-panel\"\n        [class]=\"panelClass\"\n        [style.max-width]=\"maxWidth\"\n        role=\"dialog\"\n        [attr.aria-label]=\"ariaLabel\"\n        aria-modal=\"true\"\n        (click)=\"$event.stopPropagation()\"\n        tabindex=\"-1\"\n        style=\"outline: none;\"\n      >\n        <ng-container #contentOutlet></ng-container>\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host { display: block; }\n    .ngx-dialog-backdrop {\n      position: fixed; inset: 0; z-index: 1000;\n      background: rgba(0, 0, 0, 0.45);\n      display: flex; align-items: center; justify-content: center;\n      animation: ngx-fade-in 0.15s ease;\n    }\n    .ngx-dialog-panel {\n      background: var(--ngx-dialog-bg, #fff);\n      border-radius: var(--ngx-dialog-radius, 8px);\n      box-shadow: 0 8px 40px rgba(0, 0, 0, 0.22);\n      width: 100%; max-height: 90vh; overflow-y: auto;\n      animation: ngx-slide-in 0.2s ease;\n    }\n    @keyframes ngx-fade-in {\n      from { opacity: 0; }\n      to   { opacity: 1; }\n    }\n    @keyframes ngx-slide-in {\n      from { transform: translateY(-24px); opacity: 0; }\n      to   { transform: translateY(0);     opacity: 1; }\n    }\n  `],\n})\nexport class DialogContainerComponent {\n  @ViewChild('contentOutlet', { read: ViewContainerRef, static: true })\n  contentOutlet!: ViewContainerRef;\n\n  ariaLabel = 'Dialog';\n  maxWidth = '560px';\n  panelClass = '';\n  backdropClick: (() => void) | null = null;\n\n  private cdr = inject(ChangeDetectorRef);\n  private elRef = inject(ElementRef);\n\n  attachContent(view: ViewRef): void {\n    this.contentOutlet.insert(view);\n    this.cdr.markForCheck();\n\n    // Auto-focus first focusable element, or the panel itself\n    setTimeout(() => {\n      const focusable = this.getFocusableElements();\n      if (focusable.length > 0) {\n        focusable[0].focus();\n      } else {\n        const panel = this.elRef.nativeElement.querySelector('.ngx-dialog-panel');\n        panel?.focus();\n      }\n    }, 0);\n  }\n\n  onBackdropClick(): void {\n    this.backdropClick?.();\n  }\n\n  @HostListener('document:keydown', ['$event'])\n  onKeydown(event: KeyboardEvent): void {\n    if (event.key === 'Escape') {\n      event.preventDefault();\n      this.backdropClick?.();\n    } else if (event.key === 'Tab') {\n      this.handleTab(event);\n    }\n  }\n\n  private handleTab(event: KeyboardEvent): void {\n    const focusable = this.getFocusableElements();\n    if (focusable.length === 0) {\n      event.preventDefault();\n      return;\n    }\n\n    const first = focusable[0];\n    const last = focusable[focusable.length - 1];\n    const active = document.activeElement as HTMLElement;\n\n    if (event.shiftKey) {\n      if (active === first || !this.elRef.nativeElement.contains(active)) {\n        last.focus();\n        event.preventDefault();\n      }\n    } else {\n      if (active === last || !this.elRef.nativeElement.contains(active)) {\n        first.focus();\n        event.preventDefault();\n      }\n    }\n  }\n\n  private getFocusableElements(): HTMLElement[] {\n    const selector = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex=\"-1\"]), [contenteditable]';\n    const elements = Array.from(this.elRef.nativeElement.querySelectorAll(selector)) as HTMLElement[];\n    return elements.filter(el => el.offsetWidth > 0 || el.offsetHeight > 0);\n  }\n}\n","import {\n  Injectable, ApplicationRef, createComponent, EnvironmentInjector,\n  inject, signal, Type, PLATFORM_ID\n} from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { DialogContainerComponent } from './dialog-container.component';\n\nexport interface DialogConfig<D = unknown> {\n  /** Data passed to the dialog content component via the `dialogData` input. */\n  data?: D;\n  /** Whether clicking the backdrop closes the dialog. Defaults to true. */\n  closeOnBackdrop?: boolean;\n  /** Additional CSS class(es) to apply to the dialog panel. */\n  panelClass?: string | string[];\n  /** ARIA label for the dialog (for screen readers). */\n  ariaLabel?: string;\n  /** Max width of the dialog panel (CSS value). Defaults to '560px'. */\n  maxWidth?: string;\n}\n\nexport interface DialogRef<R = unknown> {\n  /** Emits the result value and removes the dialog from the DOM. */\n  close(result?: R): void;\n  /** Signal that resolves with the result once the dialog closes. */\n  readonly closed: ReturnType<typeof signal<R | undefined>>;\n}\n\n/**\n * DialogService — programmatically opens Angular components inside a floating\n * overlay without requiring NgModule or z-index hacks.\n *\n * Usage:\n * ```ts\n * const ref = this.dialog.open(MyFormComponent, { data: { id: 42 } });\n * ref.closed(); // reactive signal — undefined until dialog closes\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class DialogService {\n  private appRef = inject(ApplicationRef);\n  private injector = inject(EnvironmentInjector);\n  private platformId = inject(PLATFORM_ID);\n\n  open<C, D = unknown, R = unknown>(\n    component: Type<C>,\n    config?: DialogConfig<D>,\n  ): DialogRef<R> {\n    const closedSignal = signal<R | undefined>(undefined);\n    let remove = () => {};\n\n    const previouslyFocused = isPlatformBrowser(this.platformId) ? document.activeElement as HTMLElement : null;\n\n    const dialogRef: DialogRef<R> = {\n      closed: closedSignal,\n      close: (result?: R) => {\n        closedSignal.set(result);\n        if (isPlatformBrowser(this.platformId)) {\n          remove();\n        }\n      },\n    };\n\n    if (!isPlatformBrowser(this.platformId)) {\n      return dialogRef;\n    }\n\n    const cfg: Required<DialogConfig<D>> = {\n      data: config?.data as D,\n      closeOnBackdrop: config?.closeOnBackdrop ?? true,\n      panelClass: config?.panelClass ?? [],\n      ariaLabel: config?.ariaLabel ?? 'Dialog',\n      maxWidth: config?.maxWidth ?? '560px',\n    };\n\n    // Create a host element appended to <body>\n    const hostEl = document.createElement('ngx-dialog-host');\n    document.body.appendChild(hostEl);\n\n    // Create the container component\n    const containerRef = createComponent(DialogContainerComponent, {\n      environmentInjector: this.injector,\n      hostElement: hostEl,\n    });\n\n    const container = containerRef.instance;\n    container.ariaLabel = cfg.ariaLabel;\n    container.maxWidth = cfg.maxWidth;\n    container.panelClass = Array.isArray(cfg.panelClass)\n      ? cfg.panelClass.join(' ')\n      : cfg.panelClass;\n\n    container.backdropClick = () => {\n      if (cfg.closeOnBackdrop) dialogRef.close();\n    };\n\n    // Create the content component and project it into the container\n    const contentRef = createComponent(component as Type<unknown>, {\n      environmentInjector: this.injector,\n      projectableNodes: [],\n    });\n\n    // Always assign common integration properties so dynamic dialog content\n    // can close itself even when these are plain class fields (not @Input).\n    const instance = contentRef.instance as Record<string, unknown>;\n    instance['dialogData'] = cfg.data;\n    instance['dialogRef'] = dialogRef;\n\n    // If the content uses Angular inputs, update them through setInput as well.\n    if (typeof contentRef.setInput === 'function') {\n      try { contentRef.setInput('dialogData', cfg.data); } catch {}\n      try { contentRef.setInput('dialogRef', dialogRef); } catch {}\n    }\n\n    container.attachContent(contentRef.hostView);\n    this.appRef.attachView(containerRef.hostView);\n\n    // Ensure the content template sees injected properties immediately.\n    contentRef.changeDetectorRef.detectChanges();\n\n    containerRef.changeDetectorRef.detectChanges();\n\n    remove = () => {\n      this.appRef.detachView(containerRef.hostView);\n      contentRef.destroy();\n      containerRef.destroy();\n      if (document.body.contains(hostEl)) {\n        document.body.removeChild(hostEl);\n      }\n      if (previouslyFocused && typeof previouslyFocused.focus === 'function') {\n        previouslyFocused.focus();\n      }\n    };\n\n    return dialogRef;\n  }\n}\n","/*\n * Public API Surface — secondary entry point: ngx-core-components/dialog\n */\n\nexport { DialogService } from './dialog.service';\nexport type { DialogRef, DialogConfig } from './dialog.service';\nexport { DialogContainerComponent } from './dialog-container.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}