{"version":3,"file":"nix-ionic.cjs","names":[],"sources":["../../src/lifecycle.ts","../../src/IonRouterOutlet.ts"],"sourcesContent":["/**\n * @deijose/nix-ionic / lifecycle.ts  —  v2\n *\n * Page-lifecycle plumbing identical to v1. The hooks (ionViewWillEnter,\n * ionViewDidEnter, ionViewWillLeave, ionViewDidLeave) still come from the\n * native <ion-page> element events — IonRouterOutlet attaches the listeners\n * when it creates each page.\n *\n * Nothing here needed to change for the single-router refactor.\n */\n\nimport { signal, watch } from \"@deijose/nix-js\";\nimport type { Signal } from \"@deijose/nix-js\";\nimport { NixComponent } from \"@deijose/nix-js\";\n\nexport interface PageLifecycle {\n    willEnter: Signal<number>;\n    didEnter: Signal<number>;\n    willLeave: Signal<number>;\n    didLeave: Signal<number>;\n}\n\nexport function createPageLifecycle(): PageLifecycle {\n    return {\n        willEnter: signal(0),\n        didEnter: signal(0),\n        willLeave: signal(0),\n        didLeave: signal(0),\n    };\n}\n\n/**\n * Internal symbol used by IonRouterOutlet's mount adapter to connect the\n * Ionic page lifecycle to an IonPage instance WITHOUT relying on the\n * subclass calling `super.onInit()`. The outlet calls this method directly\n * and stores the returned disposer so the watches are torn down with the view.\n */\nexport const _connectIonicLifecycle = Symbol(\"nix-ionic:connectLifecycle\");\n\n/**\n * Class-based pages. Subclass and implement any of the hooks.\n *\n *   class HomePage extends IonPage {\n *     constructor(lc: PageLifecycle) { super(lc); }\n *     ionViewWillEnter() { this.refreshData(); }\n *     render() { return html`...`; }\n *   }\n *\n * Lifecycle wiring no longer depends on `onInit()` / `super.onInit()`:\n * the router outlet calls the symbol-based `_connectIonicLifecycle` method\n * directly and disposes the watches when the view is cleaned up. Subclasses\n * may override `onInit` freely for their own setup without calling super.\n */\nexport abstract class IonPage extends NixComponent {\n    private __lc: PageLifecycle;\n    private __lifecycleDisposers: Array<() => void> = [];\n\n    constructor(lc: PageLifecycle) {\n        super();\n        this.__lc = lc;\n    }\n\n    /**\n     * Connects the Ionic view lifecycle signals to this page's hooks.\n     * Called once by the router outlet's mount adapter. Returns a disposer\n     * that tears down all lifecycle watches.\n     *\n     * Idempotent: calling it more than once is a no-op after the first call.\n     */\n    public [_connectIonicLifecycle](): () => void {\n        if (this.__lifecycleDisposers.length > 0) return () => this._disposeLifecycle();\n        const lc = this.__lc;\n        if (this.ionViewWillEnter) {\n            this.__lifecycleDisposers.push(watch(lc.willEnter, this.ionViewWillEnter.bind(this)));\n        }\n        if (this.ionViewDidEnter) {\n            this.__lifecycleDisposers.push(watch(lc.didEnter, this.ionViewDidEnter.bind(this)));\n        }\n        if (this.ionViewWillLeave) {\n            this.__lifecycleDisposers.push(watch(lc.willLeave, this.ionViewWillLeave.bind(this)));\n        }\n        if (this.ionViewDidLeave) {\n            this.__lifecycleDisposers.push(watch(lc.didLeave, this.ionViewDidLeave.bind(this)));\n        }\n        return () => this._disposeLifecycle();\n    }\n\n    private _disposeLifecycle(): void {\n        for (const d of this.__lifecycleDisposers) d();\n        this.__lifecycleDisposers = [];\n    }\n\n    ionViewWillEnter?(): void;\n    ionViewDidEnter?(): void;\n    ionViewWillLeave?(): void;\n    ionViewDidLeave?(): void;\n}\n\nexport function useIonViewWillEnter(lc: PageLifecycle, fn: () => void): () => void {\n    return watch(lc.willEnter, fn);\n}\n\nexport function useIonViewDidEnter(lc: PageLifecycle, fn: () => void): () => void {\n    return watch(lc.didEnter, fn);\n}\n\nexport function useIonViewWillLeave(lc: PageLifecycle, fn: () => void): () => void {\n    return watch(lc.willLeave, fn);\n}\n\nexport function useIonViewDidLeave(lc: PageLifecycle, fn: () => void): () => void {\n    return watch(lc.didLeave, fn);\n}","/**\n * @deijose/nix-ionic / IonRouterOutlet.ts  —  v2.5\n *\n *  Architecture: \"core API + ion-router-outlet motor\" (with auto-bootstrap)\n *\n *  Changes vs v2.4:\n *\n *  (E) Manual lifecycle dispatch on duration-0 transitions.\n *      EMPIRICAL FINDING: <ion-router-outlet>.commit() with `duration: 0`\n *      (used for direction: \"none\" and \"root\") does NOT fire the lifecycle\n *      events. We confirmed this with `replace(\"/login\")` after a logout —\n *      the leaving page's `ionViewWillLeave` never ran.\n *\n *      The fix: when `direction` is \"none\" or \"root\", we synthesize the\n *      events ourselves around the commit() call, in the order Ionic\n *      documents:\n *        1. WillLeave on the leaving page  (BEFORE commit starts)\n *        2. WillEnter on the entering page (BEFORE commit starts)\n *        3. await commit()                  (instantaneous when duration=0)\n *        4. DidEnter on the entering page  (AFTER commit resolves)\n *        5. DidLeave on the leaving page   (AFTER DidEnter — Ionic docs)\n *\n *      For animated transitions (\"forward\"/\"back\") we still rely on Ionic\n *      to fire the events, since those go through the full animation path\n *      where the events ARE wired correctly.\n *\n *  Kept from earlier versions:\n *    (A) Anti-flash on first mount.\n *    (B) StackManager `back` recognition.\n *    (C) _hideInactivePages defensive sweep after every transition.\n *    (D) Manual lifecycle dispatch on first mount (no leaving page).\n *\n *  Subclass note for IonPage users: if you override `onInit()` in a\n *  subclass, you MUST call `super.onInit()` first. The base IonPage uses\n *  onInit to wire `watch()` calls onto the lifecycle signals — without the\n *  super call, your `ionViewWillEnter`/etc. methods never fire.\n */\n\nimport { NixComponent, effect } from \"@deijose/nix-js\";\nimport type { NixTemplate } from \"@deijose/nix-js\";\nimport {\n    nixRouter,\n    createRouter,\n    _hasActiveRouter,\n    type Router,\n    type RouteRecord,\n    type NavigationGuard,\n    type NavigationIntent,\n} from \"@deijose/nix-js\";\nimport { createPageLifecycle, _connectIonicLifecycle, type PageLifecycle } from \"./lifecycle\";\nimport { NavigationManager, StackManager } from \"./navigation\";\n\nexport type GuardResult =\n    | boolean\n    | string\n    | { redirect: string }\n    | void\n    | undefined;\n\nexport interface PageContext {\n    lc: PageLifecycle;\n    params: Record<string, string>;\n    query: Record<string, string>;\n}\n\nexport interface RouteDefinition {\n    path: string;\n    component: (ctx: PageContext) => NixComponent | NixTemplate;\n    beforeEnter?: (ctx: PageContext) => GuardResult | Promise<GuardResult>;\n    /**\n     * Per-route cache policy override. When set, takes precedence over the\n     * outlet-level policy for this route.\n     *\n     * - `true` — use the outlet's default cache policy\n     * - `false` — never cache this route (cleanup on leave)\n     * - `{ max: N }` — cache at most N instances of this route\n     * - `{ ttl: N }` — cache entries expire after N milliseconds\n     * - `{ max: N, ttl: N }` — both bounds\n     */\n    cache?: boolean | CachePolicy;\n}\n\n/**\n * Bounded cache policy for cached pages.\n *\n * - `max`: maximum number of cached entries per tab. When exceeded, the\n *   least-recently-used entry is evicted. Default: unlimited.\n * - `ttl`: time-to-live in milliseconds. Entries older than this are\n *   evicted on next access or by a background timer. Default: unlimited.\n * - `strategy`: \"lru\" (default) evicts the least-recently-used entry when\n *   `max` is reached. \"fifo\" evicts the oldest entry.\n */\nexport interface CachePolicy {\n    max?: number;\n    ttl?: number;\n    strategy?: \"lru\" | \"fifo\";\n}\n\nexport interface IonRouterOutletOptions {\n    /** Enable/disable caching globally. Set to false to disable all caching. */\n    cache?: boolean;\n    /**\n     * Bounded cache policy applied to all cached routes (unless overridden\n     * per-route via `RouteDefinition.cache`).\n     */\n    cachePolicy?: CachePolicy;\n    defaultAnimation?: unknown;\n    tabs?: string[];\n    skipAutoBootstrap?: boolean;\n    /**\n     * Optional NavigationManager for centralized navigation state, hooks,\n     * and programmatic tab switching. When provided, the outlet delegates\n     * stack management and transition state to the manager.\n     */\n    navigation?: NavigationManager;\n}\n\nfunction adaptGuardForCore(\n    routePath: string,\n    pageGuard: (ctx: PageContext) => GuardResult | Promise<GuardResult>,\n): NavigationGuard {\n    return (to: string, _from: string) => {\n        const params = extractParamsFromPath(routePath, to);\n        const query = extractQueryFromPath(to);\n        const lc = createPageLifecycle();\n        return pageGuard({ lc, params, query }) as any;\n    };\n}\n\nfunction extractQueryFromPath(path: string): Record<string, string> {\n    const qIndex = path.indexOf(\"?\");\n    if (qIndex === -1) return {};\n    const search = path.slice(qIndex + 1);\n    const result: Record<string, string> = {};\n    for (const pair of search.split(\"&\")) {\n        if (!pair) continue;\n        const eq = pair.indexOf(\"=\");\n        if (eq === -1) {\n            result[pair] = \"\";\n        } else {\n            const k = pair.slice(0, eq);\n            try {\n                result[k] = decodeURIComponent(pair.slice(eq + 1));\n            } catch {\n                result[k] = pair.slice(eq + 1);\n            }\n        }\n    }\n    return result;\n}\n\nfunction extractParamsFromPath(pattern: string, actual: string): Record<string, string> {\n    const patternParts = pattern.split(\"/\").filter(Boolean);\n    const actualParts = actual.split(\"/\").filter(Boolean);\n    const params: Record<string, string> = {};\n    for (let i = 0; i < patternParts.length && i < actualParts.length; i++) {\n        const p = patternParts[i];\n        if (p.startsWith(\":\")) {\n            try {\n                params[p.slice(1)] = decodeURIComponent(actualParts[i] ?? \"\");\n            } catch {\n                params[p.slice(1)] = actualParts[i] ?? \"\";\n            }\n        }\n    }\n    return params;\n}\n\nfunction _parseGuardResult(r: GuardResult): { allow: boolean; redirect?: string } {\n    if (r === false) return { allow: false };\n    if (r === true || r === undefined || r === null) return { allow: true };\n    if (typeof r === \"string\") return { allow: false, redirect: r };\n    if (typeof r === \"object\" && \"redirect\" in r && typeof r.redirect === \"string\") {\n        return { allow: false, redirect: r.redirect };\n    }\n    return { allow: true };\n}\n\nfunction buildCoreRouteRecords(routes: RouteDefinition[]): RouteRecord[] {\n    return routes.map((r): RouteRecord => ({\n        path: r.path,\n        component: undefined,\n        beforeEnter: r.beforeEnter\n            ? adaptGuardForCore(r.path, r.beforeEnter)\n            : undefined,\n    }));\n}\n\ninterface CachedView {\n    pageEl: HTMLElement;\n    lc: PageLifecycle;\n    cleanup: () => void;\n    cacheKey: string;\n    /** Timestamp of last access (for LRU). */\n    lastAccessed: number;\n    /** Timestamp of creation (for TTL). */\n    createdAt: number;\n    /** Route path (for route-level policy lookup). */\n    routePath: string;\n    /** Per-route policy override (null = use outlet default). */\n    routePolicy: CachePolicy | false | null;\n    /** TTL timer handle (if TTL is set). */\n    ttlTimer: ReturnType<typeof setTimeout> | null;\n}\n\nconst IONIC_STATE_CLASSES_TO_RESET = [\"ion-page-hidden\", \"can-go-back\"];\n\nfunction _resetCachedPageState(el: HTMLElement): void {\n    el.classList.remove(...IONIC_STATE_CLASSES_TO_RESET);\n    el.style.removeProperty(\"display\");\n    el.style.removeProperty(\"visibility\");\n    el.style.removeProperty(\"opacity\");\n    el.style.removeProperty(\"transform\");\n    el.style.removeProperty(\"animation\");\n    el.style.removeProperty(\"transition\");\n    el.style.removeProperty(\"pointer-events\");\n    el.style.removeProperty(\"z-index\");\n}\n\nfunction _hasDynamicSegments(path: string): boolean {\n    return path.includes(\":\");\n}\n\nfunction _buildCacheKey(\n    routePath: string,\n    params: Record<string, string>,\n    query?: Record<string, string>,\n): string {\n    const parts: string[] = [];\n\n    // Params segment — only when the route has dynamic segments.\n    if (_hasDynamicSegments(routePath) && params && Object.keys(params).length > 0) {\n        parts.push(\n            Object.keys(params)\n                .sort()\n                .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`)\n                .join(\"&\"),\n        );\n    }\n\n    // Query segment — encoded to avoid collisions (e.g. x=1&y=2 vs x=1y=2).\n    if (query && Object.keys(query).length > 0) {\n        parts.push(\n            Object.keys(query)\n                .sort()\n                .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(query[k])}`)\n                .join(\"&\"),\n        );\n    }\n\n    if (parts.length === 0) return routePath;\n    return `${routePath}?${parts.join(\"&\")}`;\n}\n\n/**\n * Synthesize an Ionic page-lifecycle event on a pageEl. Used when commit()\n * either won't run at all (first mount) or runs with duration:0 (which\n * empirically does not fire lifecycle events in Ionic).\n */\nfunction _dispatchIonicLifecycle(\n    pageEl: HTMLElement,\n    name: \"ionViewWillEnter\" | \"ionViewDidEnter\" | \"ionViewWillLeave\" | \"ionViewDidLeave\",\n): void {\n    pageEl.dispatchEvent(new CustomEvent(name, {\n        bubbles: true,\n        cancelable: false,\n        composed: true,\n    }));\n}\n\n/**\n * Tracks cleanup functions for pages that are NOT in the cache (cache:false\n * mode). Without this, effects/lifecycle watchers leak when a non-cached\n * page is removed from the DOM.\n */\nconst _uncachedCleanups = new WeakMap<HTMLElement, () => void>();\n\nclass CacheRegistry {\n    private _byTab = new Map<string, Map<string, CachedView>>();\n    /** Eviction callback — called when an entry is evicted by policy. */\n    private _onEvict: ((view: CachedView) => void) | null = null;\n\n    /** Set the eviction callback for policy-driven evictions. */\n    onEvict(cb: (view: CachedView) => void): void {\n        this._onEvict = cb;\n    }\n\n    get(tabKey: string, cacheKey: string): CachedView | undefined {\n        const view = this._byTab.get(tabKey)?.get(cacheKey);\n        if (view) {\n            // Update LRU timestamp on access\n            view.lastAccessed = Date.now();\n        }\n        return view;\n    }\n\n    set(tabKey: string, cacheKey: string, view: CachedView): void {\n        let map = this._byTab.get(tabKey);\n        if (!map) { map = new Map(); this._byTab.set(tabKey, map); }\n        map.set(cacheKey, view);\n    }\n\n    delete(tabKey: string, cacheKey: string): void {\n        const map = this._byTab.get(tabKey);\n        if (!map) return;\n        const view = map.get(cacheKey);\n        if (view?.ttlTimer) {\n            clearTimeout(view.ttlTimer);\n            view.ttlTimer = null;\n        }\n        map.delete(cacheKey);\n    }\n\n    /**\n     * Enforce cache policy for a specific tab. Evicts entries that exceed\n     * `max` or have expired by `ttl`. Returns the number of evicted entries.\n     */\n    enforcePolicy(\n        tabKey: string,\n        policy: CachePolicy,\n        routePolicies: Map<string, boolean | CachePolicy>,\n    ): number {\n        const map = this._byTab.get(tabKey);\n        if (!map) return 0;\n\n        let evicted = 0;\n\n        // 1. TTL expiry — check all entries\n        const now = Date.now();\n        for (const [cacheKey, view] of map) {\n            const effectivePolicy = this._getEffectivePolicy(view.routePath, routePolicies, policy);\n            if (effectivePolicy === false) continue; // not cached\n            const ttl = effectivePolicy.ttl;\n            if (ttl && now - view.createdAt > ttl) {\n                this._evict(tabKey, cacheKey, view);\n                evicted++;\n            }\n        }\n\n        // 2. Max enforcement — evict LRU/FIFO entries until under max\n        const max = policy.max;\n        if (max && map.size > max) {\n            const strategy = policy.strategy ?? \"lru\";\n            const entries = [...map.entries()];\n            // Sort by eviction priority\n            if (strategy === \"lru\") {\n                entries.sort((a, b) => a[1].lastAccessed - b[1].lastAccessed);\n            } else {\n                // FIFO — oldest creation first\n                entries.sort((a, b) => a[1].createdAt - b[1].createdAt);\n            }\n            const toEvict = map.size - max;\n            for (let i = 0; i < toEvict; i++) {\n                const [cacheKey, view] = entries[i];\n                this._evict(tabKey, cacheKey, view);\n                evicted++;\n            }\n        }\n\n        return evicted;\n    }\n\n    private _getEffectivePolicy(\n        routePath: string,\n        routePolicies: Map<string, boolean | CachePolicy>,\n        defaultPolicy: CachePolicy,\n    ): CachePolicy | false {\n        const routeOverride = routePolicies.get(routePath);\n        if (routeOverride === false) return false;\n        if (routeOverride === true) return defaultPolicy;\n        if (routeOverride && typeof routeOverride === \"object\") return routeOverride;\n        return defaultPolicy;\n    }\n\n    private _evict(tabKey: string, cacheKey: string, view: CachedView): void {\n        if (view.ttlTimer) {\n            clearTimeout(view.ttlTimer);\n            view.ttlTimer = null;\n        }\n        this._byTab.get(tabKey)?.delete(cacheKey);\n        // Run cleanup + remove DOM\n        this._onEvict?.(view);\n    }\n\n    *all(): Generator<{ tabKey: string; cacheKey: string; view: CachedView }> {\n        for (const [tabKey, map] of this._byTab.entries()) {\n            for (const [cacheKey, view] of map.entries()) {\n                yield { tabKey, cacheKey, view };\n            }\n        }\n    }\n\n    clear(): void {\n        for (const map of this._byTab.values()) {\n            for (const view of map.values()) {\n                if (view.ttlTimer) clearTimeout(view.ttlTimer);\n            }\n        }\n        this._byTab.clear();\n    }\n}\n\nexport function IonBackButton(defaultHref: string = \"/\"): NixTemplate {\n    return {\n        __isNixTemplate: true as const,\n        mount(container: Element | string) {\n            const el = typeof container === \"string\"\n                ? document.querySelector(container)!\n                : container;\n            const cleanup = this._render(el, null);\n            return { unmount: cleanup };\n        },\n        _render(parent: Node, before: Node | null): () => void {\n            // Wrap in <ion-buttons slot=\"start\"> for correct layout.\n            // Without ion-buttons, ion-back-button has no flex constraints\n            // and can expand to fill the toolbar.\n            const buttons = document.createElement(\"ion-buttons\");\n            buttons.setAttribute(\"slot\", \"start\");\n\n            const btn = document.createElement(\"ion-back-button\");\n            btn.setAttribute(\"default-href\", defaultHref);\n            const onClick = (ev: Event) => {\n                ev.preventDefault();\n                ev.stopPropagation();\n                const router = nixRouter();\n                const nav = _activeNavigationManager;\n                const canGoBack = nav ? nav.canGoBack.value : router.canGoBack.value;\n                if (canGoBack) {\n                    router.back();\n                } else {\n                    router.replace(defaultHref);\n                }\n            };\n            btn.addEventListener(\"click\", onClick);\n            buttons.appendChild(btn);\n            parent.insertBefore(buttons, before);\n            return () => {\n                btn.removeEventListener(\"click\", onClick);\n                buttons.remove();\n            };\n        },\n    };\n}\n\n/**\n * Internal registry for the active NavigationManager, set by IonRouterOutlet\n * when it has one. This allows IonBackButton to use per-tab canGoBack\n * without prop drilling.\n */\nlet _activeNavigationManager: NavigationManager | null = null;\n\nexport class IonRouterOutlet extends NixComponent {\n    private _routesByPath = new Map<string, RouteDefinition>();\n    private _wildcardRoute: RouteDefinition | null = null;\n    private _enableCache: boolean;\n    private _cachePolicy: CachePolicy;\n    private _routeCachePolicies = new Map<string, boolean | CachePolicy>();\n    private _defaultAnimation: unknown;\n\n    private _stacks: StackManager;\n    private _cache = new CacheRegistry();\n    private _nav: NavigationManager | null;\n\n    private _activePageEl: HTMLElement | null = null;\n    private _activeCacheKey: string | null = null;\n    private _activeTabKey: string | null = null;\n\n    private _outletEl: HTMLElement | null = null;\n    private _routeEffectDisposer: (() => void) | null = null;\n\n    private _isTransitioning = false;\n    private _pendingNav: { path: string; intent: NavigationIntent } | null = null;\n    // True when the outlet auto-bootstrapped the core router with page guards\n    // registered. In that case _transitionTo must NOT re-run beforeEnter\n    // (the core router already did) — otherwise guards fire twice.\n    private _guardsInCoreRouter: boolean;\n\n    constructor(routes: RouteDefinition[], opts: IonRouterOutletOptions = {}) {\n        super();\n        this._enableCache = opts.cache ?? true;\n        this._cachePolicy = opts.cachePolicy ?? {};\n        this._defaultAnimation = opts.defaultAnimation;\n\n        // Use provided NavigationManager or create an internal one\n        if (opts.navigation) {\n            this._nav = opts.navigation;\n            this._stacks = opts.navigation.stacks;\n            _activeNavigationManager = opts.navigation;\n        } else {\n            this._nav = null;\n            this._stacks = new StackManager(opts.tabs);\n        }\n\n        for (const r of routes) {\n            if (r.path === \"*\") {\n                if (this._wildcardRoute) {\n                    console.warn(\n                        `[nix-ionic] Duplicate wildcard route \"*\" — the previous ` +\n                        `fallback will be overwritten. Define only one \"*\" route.`,\n                    );\n                }\n                this._wildcardRoute = r;\n                continue;\n            }\n            if (this._routesByPath.has(r.path)) {\n                console.warn(\n                    `[nix-ionic] Duplicate route path \"${r.path}\" — the previous ` +\n                    `definition will be overwritten. Each route path must be unique.`,\n                );\n            }\n            this._routesByPath.set(r.path, r);\n            // Collect per-route cache policy overrides\n            if (r.cache !== undefined) {\n                this._routeCachePolicies.set(r.path, r.cache);\n            }\n        }\n\n        // Set up eviction callback — runs cleanup + removes DOM\n        this._cache.onEvict((view) => {\n            try {\n                view.cleanup();\n            } catch { /* ignore */ }\n            if (view.pageEl.parentElement) {\n                view.pageEl.remove();\n            }\n        });\n\n        this._guardsInCoreRouter = !opts.skipAutoBootstrap && !_hasActiveRouter();\n        if (this._guardsInCoreRouter) {\n            createRouter(buildCoreRouteRecords(routes));\n        }\n\n        // Register cache invalidation handlers on the NavigationManager\n        if (this._nav) {\n            for (const r of routes) {\n                if (r.path === \"*\") continue;\n                this._nav.registerInvalidationHandler(r.path, (params) => {\n                    if (params) {\n                        this.invalidateCache(r.path, params);\n                    } else {\n                        // Invalidate all instances of this route\n                        for (const entry of this._cache.all()) {\n                            if (entry.view.routePath === r.path) {\n                                this.invalidateCache(\n                                    r.path,\n                                    undefined,\n                                    entry.tabKey,\n                                );\n                            }\n                        }\n                    }\n                });\n            }\n        }\n    }\n\n    private _resolveRouteDefinition(currentPath: string): {\n        def: RouteDefinition;\n        params: Record<string, string>;\n    } | null {\n        const router = nixRouter();\n        const resolved = router.resolve(currentPath);\n        if (!resolved.matched || !resolved.route) return null;\n        const def = this._routesByPath.get(resolved.route.path);\n        if (def) return { def, params: resolved.params };\n        // Fallback to the wildcard route (if any) when the core router matched\n        // a \"*\" route that the outlet excluded from _routesByPath.\n        if (this._wildcardRoute) {\n            return { def: this._wildcardRoute, params: resolved.params };\n        }\n        return null;\n    }\n\n    private _createPageEl(): { pageEl: HTMLElement; lc: PageLifecycle } {\n        const pageEl = document.createElement(\"ion-page\");\n        pageEl.classList.add(\"ion-page\");\n        pageEl.classList.add(\"ion-page-invisible\");\n        const lc = createPageLifecycle();\n        pageEl.addEventListener(\"ionViewWillEnter\", () =>\n            lc.willEnter.update((n) => n + 1));\n        pageEl.addEventListener(\"ionViewDidEnter\", () =>\n            lc.didEnter.update((n) => n + 1));\n        pageEl.addEventListener(\"ionViewWillLeave\", () =>\n            lc.willLeave.update((n) => n + 1));\n        pageEl.addEventListener(\"ionViewDidLeave\", () =>\n            lc.didLeave.update((n) => n + 1));\n        return { pageEl, lc };\n    }\n\n    private _mountComponent(\n        pageEl: HTMLElement,\n        def: RouteDefinition,\n        ctx: PageContext,\n    ): () => void {\n        const node = def.component(ctx);\n        if (\"render\" in node && typeof (node as NixComponent).render === \"function\") {\n            const comp = node as NixComponent;\n            // Connect Ionic lifecycle via the symbol-based internal API so\n            // the contract does NOT depend on subclasses calling super.onInit().\n            // IonPage implements this symbol; other NixComponents ignore it.\n            let lifecycleDispose: (() => void) | null = null;\n            if (_connectIonicLifecycle in comp) {\n                lifecycleDispose = (comp as any)[_connectIonicLifecycle]();\n            }\n            comp.onInit?.();\n            const renderCleanup = comp.render()._render(pageEl, null);\n            const mountRet = comp.onMount?.();\n            return () => {\n                comp.onUnmount?.();\n                if (typeof mountRet === \"function\") mountRet();\n                renderCleanup();\n                lifecycleDispose?.();\n            };\n        } else {\n            return (node as NixTemplate)._render(pageEl, null);\n        }\n    }\n\n    private _hideInactivePages(activeEl: HTMLElement | null): void {\n        const outletEl = this._outletEl;\n        if (!outletEl) return;\n        const children = Array.from(outletEl.children);\n        for (const child of children) {\n            if (!(child instanceof HTMLElement)) continue;\n            if (child.tagName !== \"ION-PAGE\" && !child.classList.contains(\"ion-page\")) continue;\n            if (child === activeEl) {\n                child.classList.remove(\"ion-page-hidden\");\n            } else {\n                child.classList.add(\"ion-page-hidden\");\n            }\n        }\n    }\n\n    private async _transitionTo(\n        targetPath: string,\n        intent: NavigationIntent,\n    ): Promise<void> {\n        const outletEl = this._outletEl;\n        if (!outletEl) return;\n\n        const resolved = this._resolveRouteDefinition(targetPath);\n        if (!resolved) return;\n\n        const { def, params } = resolved;\n        const router = nixRouter();\n        const query = router.query.value;\n        const cacheKey = _buildCacheKey(def.path, params, query);\n        const targetTabKey = this._stacks.keyForPath(targetPath);\n\n        if (this._isTransitioning) {\n            // Preserve full intent metadata (direction, animation, action)\n            // so the deferred navigation behaves identically to the original.\n            if (this._nav) {\n                this._nav.setPendingNav(targetPath, intent);\n            } else {\n                this._pendingNav = { path: targetPath, intent };\n            }\n            return;\n        }\n\n        if (cacheKey === this._activeCacheKey && targetTabKey === this._activeTabKey) return;\n        this._isTransitioning = true;\n        if (this._nav) this._nav.beginTransition();\n        let transitionCancelled = false;\n\n        // Run beforeNav hooks from NavigationManager\n        if (this._nav) {\n            const allowed = await this._nav.runBeforeNav(targetPath, intent);\n            if (!allowed) {\n                this._isTransitioning = false;\n                this._nav.endTransition();\n                return;\n            }\n        }\n\n        try {\n            // Page-level guard — only run here if the core router is NOT\n            // already handling it (skipAutoBootstrap or external router).\n            // When the outlet auto-bootstrapped, guards are registered in the\n            // core router and running them again here would double-fire.\n            if (def.beforeEnter && !this._guardsInCoreRouter) {\n                const cached = this._cache.get(targetTabKey, cacheKey);\n                const lcForGuard = cached?.lc ?? createPageLifecycle();\n                const guardResult = await Promise.resolve(\n                    def.beforeEnter({ lc: lcForGuard, params, query: router.query.value }),\n                );\n                const parsed = _parseGuardResult(guardResult);\n                if (!parsed.allow) {\n                    if (parsed.redirect) {\n                        // Clear any stale pending nav before redirecting so the\n                        // only pending nav after this is the one triggered by\n                        // the redirect itself (which is legitimate).\n                        this._pendingNav = null;\n                        nixRouter().replace(parsed.redirect);\n                        // Don't mark as cancelled — the redirect enqueued a\n                        // new pending nav via the effect that should process.\n                    } else {\n                        // Pure cancel (no redirect) — drop pending navs.\n                        transitionCancelled = true;\n                    }\n                    return;\n                }\n            }\n\n            // Resolve entering page\n            let enteringEl: HTMLElement;\n            let isNewlyMounted = false;\n\n            // Determine if this route should be cached\n            const routeCacheOpt = this._routeCachePolicies.get(def.path);\n            const routeCacheDisabled = routeCacheOpt === false;\n            const shouldCache = this._enableCache && !routeCacheDisabled;\n\n            const cached = shouldCache\n                ? this._cache.get(targetTabKey, cacheKey)\n                : undefined;\n\n            if (cached) {\n                _resetCachedPageState(cached.pageEl);\n                // Remove ion-page-hidden (added by _hideInactivePages when the\n                // page was cached) so Ionic's commit() can show it. Keep\n                // ion-page-invisible to prevent flash before the transition.\n                cached.pageEl.classList.remove(\"ion-page-hidden\");\n                cached.pageEl.style.removeProperty(\"display\");\n                cached.pageEl.classList.add(\"ion-page-invisible\");\n                enteringEl = cached.pageEl;\n            } else {\n                const { pageEl, lc } = this._createPageEl();\n                const cleanup = this._mountComponent(pageEl, def, { lc, params, query });\n                if (shouldCache) {\n                    const now = Date.now();\n                    const routePolicy = (routeCacheOpt && typeof routeCacheOpt === \"object\")\n                        ? routeCacheOpt\n                        : null;\n                    const effectivePolicy = routePolicy ?? this._cachePolicy;\n                    const ttl = effectivePolicy.ttl;\n                    const view: CachedView = {\n                        pageEl, lc, cleanup, cacheKey,\n                        lastAccessed: now,\n                        createdAt: now,\n                        routePath: def.path,\n                        routePolicy,\n                        ttlTimer: ttl ? setTimeout(() => {\n                            // TTL expired — evict if still in cache and not active\n                            if (this._activeCacheKey !== cacheKey || this._activeTabKey !== targetTabKey) {\n                                this._cache.delete(targetTabKey, cacheKey);\n                                try { cleanup(); } catch { /* ignore */ }\n                                if (pageEl.parentElement) pageEl.remove();\n                            }\n                        }, ttl) : null,\n                    };\n                    this._cache.set(targetTabKey, cacheKey, view);\n                    // Enforce max after inserting\n                    if (this._cachePolicy.max) {\n                        this._cache.enforcePolicy(targetTabKey, this._cachePolicy, this._routeCachePolicies);\n                    }\n                } else {\n                    // cache:false — track cleanup so it runs when the page leaves.\n                    _uncachedCleanups.set(pageEl, cleanup);\n                }\n                enteringEl = pageEl;\n                isNewlyMounted = true;\n            }\n\n            if (!outletEl.contains(enteringEl)) {\n                outletEl.appendChild(enteringEl);\n            }\n\n            const direction = this._stacks.apply(targetPath, intent);\n            const leavingEl = this._activePageEl;\n\n            if (!leavingEl || leavingEl === enteringEl) {\n                this._activePageEl = enteringEl;\n                this._activeCacheKey = cacheKey;\n                this._activeTabKey = targetTabKey;\n\n                const finalEl = enteringEl;\n                _dispatchIonicLifecycle(finalEl, \"ionViewWillEnter\");\n\n                if (isNewlyMounted) {\n                    requestAnimationFrame(() => {\n                        requestAnimationFrame(() => {\n                            finalEl.classList.remove(\"ion-page-invisible\");\n                            this._hideInactivePages(finalEl);\n                            _dispatchIonicLifecycle(finalEl, \"ionViewDidEnter\");\n                        });\n                    });\n                } else {\n                    finalEl.classList.remove(\"ion-page-invisible\");\n                    this._hideInactivePages(finalEl);\n                    _dispatchIonicLifecycle(finalEl, \"ionViewDidEnter\");\n                }\n                return;\n            }\n\n            const animationBuilder = (intent.animation ?? this._defaultAnimation) as\n                | undefined | unknown;\n\n            // duration:0 is what Ionic uses for \"no animation\" navigations.\n            // Empirically, this path skips lifecycle event dispatch — so we\n            // synthesize them manually around the commit() call.\n            const isDuration0 = direction === \"root\" || direction === \"none\";\n\n            const commitOpts: any = {\n                duration: isDuration0 ? 0 : undefined,\n                direction:\n                    direction === \"back\" ? \"back\"\n                        : direction === \"forward\" ? \"forward\"\n                            : undefined,\n                showGoBack: direction === \"forward\",\n            };\n            if (animationBuilder) commitOpts.animationBuilder = animationBuilder;\n\n            // Ionic docs: WillLeave fires BEFORE WillEnter.\n            // Animated paths (duration > 0): commit() handles dispatch.\n            if (isDuration0) {\n                _dispatchIonicLifecycle(leavingEl, \"ionViewWillLeave\");\n                _dispatchIonicLifecycle(enteringEl, \"ionViewWillEnter\");\n            }\n\n            await (outletEl as any).commit(enteringEl, leavingEl, commitOpts);\n\n            this._activePageEl = enteringEl;\n            this._activeCacheKey = cacheKey;\n            this._activeTabKey = targetTabKey;\n\n            // Remove the invisible/hidden classes that were added when reusing\n            // a cached page. Ionic's commit() may remove them during animation,\n            // but with reduced-motion or duration-0 transitions they can persist.\n            enteringEl.classList.remove(\"ion-page-invisible\");\n            enteringEl.classList.remove(\"ion-page-hidden\");\n            enteringEl.style.removeProperty(\"display\");\n            // Ensure the entering page has a higher z-index than the leaving\n            // page. Ionic's commit() with reduced-motion may not swap z-index.\n            const leavingZ = leavingEl ? parseInt(getComputedStyle(leavingEl).zIndex, 10) || 0 : 0;\n            enteringEl.style.zIndex = String(leavingZ + 1);\n            this._hideInactivePages(enteringEl);\n\n            // Ionic docs: DidLeave fires AFTER DidEnter (after the new\n            // page has fully transitioned in).\n            if (isDuration0) {\n                _dispatchIonicLifecycle(enteringEl, \"ionViewDidEnter\");\n                _dispatchIonicLifecycle(leavingEl, \"ionViewDidLeave\");\n            }\n\n            // If the leaving page is not in the cache (either because cache is\n            // disabled OR because it was invalidated while active), run its\n            // cleanup before removing the DOM node, otherwise effects/lifecycle\n            // watchers leak.\n            const leavingCleanup = _uncachedCleanups.get(leavingEl);\n            if (leavingCleanup && leavingEl.parentElement === outletEl) {\n                leavingCleanup();\n                _uncachedCleanups.delete(leavingEl);\n                leavingEl.remove();\n            } else if (!this._enableCache && leavingEl.parentElement === outletEl) {\n                leavingEl.remove();\n            }\n        } finally {\n            this._isTransitioning = false;\n            if (this._nav) this._nav.endTransition();\n\n            // Determine the effective direction for afterNav hooks\n            const effectiveDirection = this._stacks.apply(targetPath, intent);\n\n            // Run afterNav and tabChange hooks\n            if (this._nav && !transitionCancelled) {\n                this._nav.runAfterNav(targetPath, effectiveDirection);\n                this._nav.runTabChangeIfNeeded(targetPath);\n                this._nav.updateCanGoBack();\n            }\n\n            // Only process pending nav if the current transition succeeded.\n            // A cancelled/failed transition (guard reject, route not found)\n            // must NOT blindly replay a stale pending nav — the router state\n            // may have already moved (e.g. redirect) and the pending path\n            // could be inconsistent with the new current.\n            const pending = this._nav ? this._nav.consumePendingNav() : this._pendingNav;\n            if (!this._nav) this._pendingNav = null;\n\n            if (pending && !transitionCancelled) {\n                // Re-validate against current router state before processing.\n                const currentRouter = nixRouter();\n                if (pending.path === currentRouter.current.value) {\n                    void this._transitionTo(pending.path, pending.intent);\n                }\n            } else if (transitionCancelled && this._nav) {\n                this._nav.clearPendingNav();\n            }\n        }\n    }\n\n    override render(): NixTemplate {\n        const self = this;\n        return {\n            __isNixTemplate: true as const,\n\n            mount(container: Element | string) {\n                const el = typeof container === \"string\"\n                    ? document.querySelector(container)!\n                    : container;\n                const cleanup = this._render(el, null);\n                return { unmount: cleanup };\n            },\n\n            _render(parent: Node, before: Node | null): () => void {\n                const outletEl = document.createElement(\"ion-router-outlet\");\n                self._outletEl = outletEl;\n\n                (outletEl as any).delegate = {\n                    attachViewToDom: (\n                        container: HTMLElement,\n                        component: HTMLElement,\n                    ): HTMLElement => {\n                        if (component && !container.contains(component)) {\n                            container.appendChild(component);\n                        }\n                        return component;\n                    },\n                    removeViewFromDom: async (): Promise<void> => { /* no-op */ },\n                };\n\n                parent.insertBefore(outletEl, before);\n\n                const router: Router = nixRouter();\n                let lastSeenNavKey: string | null = null;\n                let initialDeferred = false;\n\n                self._routeEffectDisposer = effect(() => {\n                    const path = router.current.value;\n                    const intent = router.intent.value;\n                    // Observe query so query-only navigation (same path, different\n                    // query) triggers a transition. The nav key combines path +\n                    // serialized query; reading router.query.value subscribes\n                    // the effect to query changes.\n                    const query = router.query.value;\n                    const queryStr = Object.keys(query).length > 0\n                        ? \"?\" + Object.keys(query).sort().map(\n                            (k) => `${encodeURIComponent(k)}=${encodeURIComponent(query[k])}`,\n                        ).join(\"&\")\n                        : \"\";\n                    const navKey = path + queryStr;\n\n                    if (!initialDeferred) {\n                        initialDeferred = true;\n                        queueMicrotask(() => {\n                            const settledPath = router.current.value;\n                            const settledIntent = router.intent.value;\n                            const settledQuery = router.query.value;\n                            const settledQueryStr = Object.keys(settledQuery).length > 0\n                                ? \"?\" + Object.keys(settledQuery).sort().map(\n                                    (k) => `${encodeURIComponent(k)}=${encodeURIComponent(settledQuery[k])}`,\n                                ).join(\"&\")\n                                : \"\";\n                            lastSeenNavKey = settledPath + settledQueryStr;\n                            void self._transitionTo(settledPath, settledIntent);\n                        });\n                        return;\n                    }\n\n                    if (navKey === lastSeenNavKey) {\n                        // The router sets intent.value before current.value,\n                        // which can trigger the effect with a stale path.\n                        // If the intent indicates a pop (hashchange back),\n                        // defer to a microtask to read the settled path.\n                        if (intent.action === \"pop\" && intent.direction === \"none\") {\n                            queueMicrotask(() => {\n                                const settledPath = router.current.value;\n                                const settledQuery = router.query.value;\n                                const settledQueryStr = Object.keys(settledQuery).length > 0\n                                    ? \"?\" + Object.keys(settledQuery).sort().map(\n                                        (k) => `${encodeURIComponent(k)}=${encodeURIComponent(settledQuery[k])}`,\n                                    ).join(\"&\")\n                                    : \"\";\n                                const settledNavKey = settledPath + settledQueryStr;\n                                if (settledNavKey === lastSeenNavKey) return;\n                                lastSeenNavKey = settledNavKey;\n                                void self._transitionTo(settledPath, router.intent.value);\n                            });\n                        }\n                        return;\n                    }\n                    lastSeenNavKey = navKey;\n                    void self._transitionTo(path, intent);\n                });\n\n                return () => {\n                    self._routeEffectDisposer?.();\n                    self._routeEffectDisposer = null;\n                    for (const { view } of self._cache.all()) {\n                        view.cleanup();\n                        if (view.pageEl.parentElement) view.pageEl.remove();\n                    }\n                    self._cache.clear();\n                    // cache:false active page — run its cleanup too.\n                    if (self._activePageEl) {\n                        const activeCleanup = _uncachedCleanups.get(self._activePageEl);\n                        if (activeCleanup) {\n                            activeCleanup();\n                            _uncachedCleanups.delete(self._activePageEl);\n                        }\n                    }\n                    self._activePageEl = null;\n                    self._activeCacheKey = null;\n                    self._activeTabKey = null;\n                    self._outletEl = null;\n                    outletEl.remove();\n                };\n            },\n        };\n    }\n\n    invalidateCache(\n        routePath: string,\n        params?: Record<string, string>,\n        tabKey?: string,\n        query?: Record<string, string>,\n    ): void {\n        const key = (params || query)\n            ? _buildCacheKey(routePath, params ?? {}, query)\n            : routePath;\n        const targetTabKey = tabKey ?? this._stacks.keyForPath(routePath);\n        const cached = this._cache.get(targetTabKey, key);\n        if (!cached) return;\n\n        if (cached.pageEl === this._activePageEl) {\n            // Active page: do NOT dispose reactivity or remove DOM — that would\n            // leave a visible-but-dead view. Just drop the cache entry so the\n            // next visit remounts a fresh instance. Move the cleanup to the\n            // uncached tracker so the normal transition path disposes it when\n            // the user navigates away.\n            _uncachedCleanups.set(cached.pageEl, cached.cleanup);\n            this._cache.delete(targetTabKey, key);\n            this._activeCacheKey = null;\n            return;\n        }\n\n        cached.cleanup();\n        if (cached.pageEl.parentElement) {\n            cached.pageEl.remove();\n        }\n        this._cache.delete(targetTabKey, key);\n    }\n\n    clearCache(): void {\n        const entries: Array<{ tabKey: string; cacheKey: string; view: CachedView }> = [];\n        for (const e of this._cache.all()) entries.push(e);\n        for (const { tabKey, cacheKey, view } of entries) {\n            if (view.pageEl === this._activePageEl) continue;\n            view.cleanup();\n            if (view.pageEl.parentElement) view.pageEl.remove();\n            this._cache.delete(tabKey, cacheKey);\n        }\n    }\n\n    /**\n     * Clear all cached pages for a specific tab. Useful when leaving a tab\n     * permanently or for memory management.\n     */\n    clearTabCache(tabKey: string): void {\n        const entries: Array<{ tabKey: string; cacheKey: string; view: CachedView }> = [];\n        for (const e of this._cache.all()) {\n            if (e.tabKey === tabKey) entries.push(e);\n        }\n        for (const { tabKey, cacheKey, view } of entries) {\n            if (view.pageEl === this._activePageEl) continue;\n            view.cleanup();\n            if (view.pageEl.parentElement) view.pageEl.remove();\n            this._cache.delete(tabKey, cacheKey);\n        }\n    }\n\n    /** The NavigationManager used by this outlet (if any). */\n    get navigation(): NavigationManager | null {\n        return this._nav;\n    }\n}"],"mappings":"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"}