"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { Suspense, use, useId } from "react";
import { invariant } from "./errors";
import { OutletProvider } from "./client.js";
import { isLoaderDataResult } from "./types.js";
/**
 * Stable async wrapper component for route content
 * Using a module-level component ensures React sees the same component reference
 * across renders, preventing unnecessary remounts during actions.
 *
 * When content is a pending promise, React suspends and shows the nearest
 * Suspense fallback. When content is already resolved, it renders immediately
 * without suspension.
 *
 * @param segmentId - Stable ID from segment, used for consistent keys across renders
 */
export function RouteContentWrapper({ content, fallback, segmentId, }) {
    if (!content) {
        // Already resolved
        return content;
    }
    return (_jsx(Suspense, { fallback: fallback ?? null, children: _jsx(Suspender, { content: content }, segmentId) }, segmentId ? "route-content-suspense-" + segmentId : undefined));
}
export function RouteContentWrapperCallback({ resolve, fallback, children, }) {
    const id = useId();
    invariant(children, "RouteContentWrapperCallback requires children");
    invariant(typeof children === "function", "RouteContentWrapperCallback requires children to be a function");
    invariant(resolve !== undefined, "RouteContentWrapperCallback requires resolve");
    return (_jsx(Suspense, { fallback: fallback ?? null, children: _jsx(SuspenderCallback, { resolve: resolve, children: children }, id) }, "route-content-suspense-callback-" + id));
}
const Suspender = ({ content, }) => {
    invariant(content instanceof Promise, "Suspender expects a Promise content");
    return use(content);
};
const SuspenderCallback = ({ resolve, children, }) => {
    return resolve instanceof Promise
        ? children(use(resolve))
        : children(resolve);
};
export function LoaderBoundary({ loaderDataPromise, loaderIds, fallback, outletKey, outletContent, segment, parallel, children, }) {
    return (_jsx(Suspense, { fallback: fallback ?? null, children: _jsx(LoaderResolver, { loaderDataPromise: loaderDataPromise, loaderIds: loaderIds, outletKey: outletKey, outletContent: outletContent, segment: segment, parallel: parallel, children: children }) }, `loader-boundary-${outletKey}`));
}
/**
 * Internal component that resolves loader promises and renders OutletProvider
 */
function LoaderResolver({ loaderDataPromise, loaderIds, outletKey, outletContent, segment, parallel, children, }) {
    // Resolve loader promises using React's use()
    const resolvedData = loaderDataPromise instanceof Promise
        ? use(loaderDataPromise)
        : loaderDataPromise;
    // Build loaderData record from resolved values
    const loaderData = {};
    let loaderErrorFallback = null;
    loaderIds.forEach((id, i) => {
        const result = resolvedData[i];
        if (isLoaderDataResult(result)) {
            if (result.ok) {
                loaderData[id] = result.data;
            }
            else {
                if (result.fallback) {
                    loaderErrorFallback = result.fallback;
                }
                else {
                    throw new Error(result.error.message);
                }
            }
        }
        else {
            // Legacy format - direct data
            loaderData[id] = result;
        }
    });
    return (_jsx(OutletProvider, { content: outletContent, segment: segment, parallel: parallel, loaderData: Object.keys(loaderData).length > 0 ? loaderData : undefined, children: loaderErrorFallback ?? children }, outletKey));
}
//# sourceMappingURL=route-content-wrapper.js.map