import * as Vue from 'vue';
import { isServer } from '@tanstack/router-core/isServer';
import { useStore } from '@tanstack/vue-store';
import { CatchBoundary } from './CatchBoundary';
import { useRouter } from './useRouter';
import { useTransitionerSetup } from './Transitioner';
import { routeIdContext } from './matchContext';
import { Match } from './Match';
import { renderInNonRouteComponentContext } from './nonRouteComponentContext';
export const Matches = Vue.defineComponent({
    name: 'Matches',
    setup() {
        const router = useRouter();
        useTransitionerSetup();
        return () => {
            const pendingElement = router.options.defaultPendingComponent
                ? process.env.NODE_ENV !== 'production'
                    ? renderInNonRouteComponentContext(router.options.defaultPendingComponent, undefined, 'pendingComponent')
                    : Vue.h(router.options.defaultPendingComponent)
                : null;
            // Do not render a root Suspense during SSR or hydrating from SSR
            const inner = (isServer ?? router.isServer) ||
                (typeof document !== 'undefined' && router.ssr)
                ? Vue.h(MatchesInner)
                : Vue.h(Vue.Suspense, { fallback: pendingElement }, {
                    default: () => Vue.h(MatchesInner),
                });
            return router.options.InnerWrap
                ? Vue.h(router.options.InnerWrap, null, { default: () => inner })
                : inner;
        };
    },
});
// Create a simple error component function that matches ErrorRouteComponent
const errorComponentFn = (props) => {
    return Vue.h('div', { class: 'error' }, [
        Vue.h('h1', null, 'Error'),
        Vue.h('p', null, props.error.message || String(props.error)),
        Vue.h('button', { onClick: props.reset }, 'Try Again'),
    ]);
};
const MatchesInner = Vue.defineComponent({
    name: 'MatchesInner',
    setup() {
        const router = useRouter();
        const matches = useStore(router.stores.matches);
        const routeId = Vue.computed(() => matches.value[0]?.routeId);
        return () => {
            // Generate a placeholder element if routeId.value is not present
            const childElement = routeId.value
                ? Vue.h(Match, { routeId: routeId.value })
                : Vue.h('div');
            // If disableGlobalCatchBoundary is true, don't wrap in CatchBoundary
            if (router.options.disableGlobalCatchBoundary) {
                return childElement;
            }
            return Vue.h(CatchBoundary, {
                getResetKey: () => matches.value,
                errorComponent: errorComponentFn,
                onCatch: process.env.NODE_ENV !== 'production'
                    ? (error) => {
                        console.warn(`Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`);
                        console.warn(`Warning: ${error.message || error.toString()}`);
                    }
                    : undefined,
                children: childElement,
            });
        };
    },
});
export function useMatchRoute() {
    const router = useRouter();
    const location = useStore(router.stores.location, (value) => value.href);
    const resolvedLocation = useStore(router.stores.resolvedLocation, (value) => value?.href);
    const status = useStore(router.stores.status);
    return (opts) => {
        const matchRoute = Vue.computed(() => {
            location.value;
            resolvedLocation.value;
            status.value;
            const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts;
            return router.matchRoute(rest, {
                pending,
                caseSensitive,
                fuzzy,
                includeSearch,
            });
        });
        return matchRoute;
    };
}
export const MatchRoute = Vue.defineComponent({
    name: 'MatchRoute',
    props: {
        // Define props to match MakeMatchRouteOptions
        from: {
            type: String,
            required: false,
        },
        to: {
            type: String,
            required: false,
        },
        fuzzy: {
            type: Boolean,
            required: false,
        },
        caseSensitive: {
            type: Boolean,
            required: false,
        },
        includeSearch: {
            type: Boolean,
            required: false,
        },
        pending: {
            type: Boolean,
            required: false,
        },
    },
    setup(props, { slots }) {
        const params = useMatchRoute()(props);
        return () => {
            const match = params.value;
            // Create a component that renders the slot in a reactive manner
            if (!match || !slots.default) {
                return null;
            }
            // For function slots, pass the params
            if (typeof slots.default === 'function') {
                // Use h to create a wrapper component that will call the slot function
                return Vue.h(Vue.Fragment, null, slots.default(match));
            }
            // For normal slots, just render them
            return Vue.h(Vue.Fragment, null, slots.default);
        };
    },
});
export function useMatches(opts) {
    const router = useRouter();
    return useStore(router.stores.matches, (matches) => {
        return opts?.select
            ? opts.select(matches)
            : matches;
    });
}
export function useParentMatches(opts) {
    const contextRouteId = Vue.inject(routeIdContext);
    return useMatches({
        select: (matches) => {
            matches = matches.slice(0, matches.findIndex((d) => d.routeId === contextRouteId));
            return opts?.select ? opts.select(matches) : matches;
        },
    });
}
export function useChildMatches(opts) {
    const contextRouteId = Vue.inject(routeIdContext);
    return useMatches({
        select: (matches) => {
            matches = matches.slice(matches.findIndex((d) => d.routeId === contextRouteId) + 1);
            return opts?.select ? opts.select(matches) : matches;
        },
    });
}
//# sourceMappingURL=Matches.jsx.map