{"version":3,"file":"mn-angular-lib-modal.mjs","sources":["../../../projects/mn-angular-lib/modal/src/mn-modal/mn-modal.service.ts","../../../projects/mn-angular-lib/modal/public-api.ts","../../../projects/mn-angular-lib/modal/mn-angular-lib-modal.ts"],"sourcesContent":["import {ApplicationRef, ComponentRef, createComponent, EnvironmentInjector, inject, Injectable, Type,} from '@angular/core';\nimport {MnModalRef, ModalCloseReason, ModalConfig} from 'mn-angular-lib/modal-core';\nimport type {MnModalShellComponent} from 'mn-angular-lib/modal-ui';\n\n/** The modal components entry point, once loaded. */\ntype ModalUi = { MnModalShellComponent: Type<MnModalShellComponent<unknown>> };\n\n/** The loaded modal components, shared by every service instance. */\nlet modalUi: ModalUi | null = null;\n\n/** The in-flight or settled load of the modal components. */\nlet modalUiLoad: Promise<ModalUi> | null = null;\n\n/**\n * Loads `mn-angular-lib/modal-ui` once. The shell and its bodies render every form field and\n * the table, so importing them statically put most of the library into each consumer's\n * startup bundle just because a service injects `MnModalService`.\n * @returns The loaded entry point.\n */\nfunction loadModalUi(): Promise<ModalUi> {\n  modalUiLoad ??= import('mn-angular-lib/modal-ui').then((ui) => (modalUi = ui));\n  return modalUiLoad;\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class MnModalService {\n  private readonly appRef = inject(ApplicationRef);\n  private readonly injector = inject(EnvironmentInjector);\n  private readonly modalStack: MnModalRef<unknown>[] = [];\n\n  constructor() {\n    // Fetch the modal components once the app is idle, so the first modal opens without a\n    // network round trip while startup never waits for them.\n    if (typeof window !== 'undefined') {\n      const whenIdle = window.requestIdleCallback ?? ((callback: () => void) => setTimeout(callback, 2000));\n      whenIdle(() => void this.preload().catch(() => undefined));\n    }\n  }\n\n  /**\n   * Loads the modal components ahead of the first `open()`. After it resolves, `open()` renders\n   * synchronously; tests await it before asserting on the DOM.\n   * @returns Resolves once the components are loaded.\n   */\n  preload(): Promise<void> {\n    return loadModalUi().then(() => undefined);\n  }\n\n  open<TResult = unknown, TModel = unknown>(config: ModalConfig<TResult, TModel>): MnModalRef<TResult> {\n    // Work off a mutable shallow copy of the (frozen) builder config, shared by\n    // both the shell and the ref. `ModalBuilder.build()` returns a frozen object;\n    // `MnModalRef.update()` mutates the config in place (so the shell, which holds\n    // the same reference, sees the change), which would throw on a frozen object.\n    // Cloning here keeps the caller's built config immutable while giving the\n    // runtime an extensible object to update (e.g. footer actions set at runtime).\n    const workingConfig = {...(config as ModalConfig<TResult>)};\n\n    // The ref exists straight away so callers can subscribe and close as before; the shell\n    // attaches to it as soon as the modal components are available (immediately once loaded).\n    const modalRef = new MnModalRef<TResult>(null, workingConfig);\n\n    if (modalUi) {\n      this.render(modalUi, modalRef, workingConfig);\n    } else {\n      loadModalUi().then(\n        (ui) => {\n          if (!modalRef.isCloseRequested) this.render(ui, modalRef, workingConfig);\n        },\n        (error: unknown) => {\n          console.error('[MnModal] Failed to load the modal components', error);\n          modalRef.dismiss(ModalCloseReason.PROGRAMMATIC);\n        },\n      );\n    }\n\n    return modalRef;\n  }\n\n  /**\n   * Creates the shell for a modal, stacks it on top of any open modal and attaches it to the app.\n   * @param ui The loaded modal components.\n   * @param modalRef The ref returned from `open()`.\n   * @param workingConfig The mutable config shared by the ref and the shell.\n   */\n  private render<TResult>(ui: ModalUi, modalRef: MnModalRef<TResult>, workingConfig: ModalConfig<TResult>): void {\n    const componentRef = createComponent(ui.MnModalShellComponent, {\n      environmentInjector: this.injector,\n    }) as unknown as ComponentRef<MnModalShellComponent<TResult>>;\n\n    // TModel is erased at the shell boundary — the shell only needs TResult\n    componentRef.instance.config = workingConfig;\n    componentRef.instance.modalRef = modalRef;\n    modalRef.attach(componentRef);\n\n    // Update stack and dim previous modal\n    if (this.modalStack.length > 0) {\n      const prevModal = this.modalStack[this.modalStack.length - 1];\n      (prevModal.component as MnModalShellComponent<unknown>).isStacked.set(true);\n    }\n    this.modalStack.push(modalRef as unknown as MnModalRef<unknown>);\n\n    // Attach to application\n    this.appRef.attachView(componentRef.hostView);\n    const domElem = componentRef.location.nativeElement;\n    document.body.appendChild(domElem);\n\n    // Clean up on close\n    modalRef.afterClosed$.subscribe(() => {\n      this.appRef.detachView(componentRef.hostView);\n      domElem.remove();\n\n      // Update stack\n      const index = this.modalStack.indexOf(modalRef as unknown as MnModalRef<unknown>);\n      if (index > -1) {\n        this.modalStack.splice(index, 1);\n        if (this.modalStack.length > 0) {\n          const topModal = this.modalStack[this.modalStack.length - 1];\n          (topModal.component as MnModalShellComponent<unknown>).isStacked.set(false);\n        }\n      }\n    });\n  }\n}\n","/**\n * Public API of the `mn-angular-lib/modal` entry point: the modal service.\n *\n * Each entry point is its own module in the published package, so a consumer's bundler\n * splits it into the chunk that uses it instead of loading the whole library at startup.\n * The root `mn-angular-lib` entry re-exports every entry point.\n */\nexport { MnModalService } from './src/mn-modal/mn-modal.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}