import type { ReactNode } from "react";
import type { PartialCacheOptions, DefaultEnv, ErrorBoundaryHandler, ExtractRouteParams, Handler, LoaderDefinition, MiddlewareFn, NotFoundBoundaryHandler, ResolvedRouteMap, RouteDefinition, RouteDefinitionOptions, ShouldRevalidateFn, TrailingSlashMode } from "./types.js";
import { type InterceptWhenFn } from "./server/context";
import type { AllUseItems, LayoutItem, RouteItem, ParallelItem, InterceptItem, MiddlewareItem, RevalidateItem, LoaderItem, LoadingItem, ErrorBoundaryItem, NotFoundBoundaryItem, LayoutUseItem, RouteUseItem, ParallelUseItem, InterceptUseItem, LoaderUseItem, WhenItem, CacheItem } from "./route-types.js";
/**
 * Result of route() function with paths and trailing slash config
 */
export interface RouteDefinitionResult<T extends RouteDefinition> {
    routes: ResolvedRouteMap<T>;
    trailingSlash: Record<string, TrailingSlashMode>;
}
/**
 * Define routes with optional trailing slash configuration
 *
 * @example
 * ```typescript
 * // Simple string paths
 * const routes = route({
 *   blog: "/blog",
 *   post: "/blog/:id",
 * });
 *
 * // With trailing slash config
 * const routes = route({
 *   blog: "/blog",
 *   api: { path: "/api", trailingSlash: "ignore" },
 * }, { trailingSlash: "never" }); // global default
 * ```
 */
export declare function route<const T extends RouteDefinition>(input: T, options?: RouteDefinitionOptions): ResolvedRouteMap<T> & {
    __trailingSlash?: Record<string, TrailingSlashMode>;
};
export type { AllUseItems, LayoutItem, RouteItem, ParallelItem, InterceptItem, MiddlewareItem, RevalidateItem, LoaderItem, ErrorBoundaryItem, NotFoundBoundaryItem, LayoutUseItem, RouteUseItem, ParallelUseItem, InterceptUseItem, WhenItem, CacheItem, } from "./route-types.js";
export type { InterceptSelectorContext, InterceptSegmentsState, InterceptWhenFn, } from "./server/context";
/**
 * Route helpers provided by map()
 * These are the only typed helpers users interact with
 */
export type RouteHelpers<T extends RouteDefinition, TEnv> = {
    /**
     * Define a route handler for a specific route pattern
     * ```typescript
     * route("products.detail", async (ctx) => {
     *   const product = await getProduct(ctx.params.slug);
     *   return <ProductPage product={product} />;
     * })
     *
     * // With nested use() for middleware, loaders, etc.
     * route("products.detail", ProductHandler, () => [
     *   loader(ProductLoader),
     *   loading(<ProductSkeleton />),
     * ])
     * ```
     * @param name - Route name matching a key from route definitions
     * @param handler - Async function that returns JSX for the route
     * @param use - Optional callback returning middleware, loaders, loading, etc.
     */
    route: <K extends keyof ResolvedRouteMap<T> & string>(name: K, handler: Handler<ExtractRouteParams<T, K & string>, {}, TEnv>, use?: () => RouteUseItem[]) => RouteItem;
    /**
     * Define a layout that wraps child routes
     * ```typescript
     * layout(<RootLayout />, () => [
     *   route("home", HomePage),
     *   route("about", AboutPage),
     * ])
     *
     * // With dynamic layout handler
     * layout(async (ctx) => {
     *   const user = ctx.get("user");
     *   return <DashboardShell user={user} />;
     * }, () => [
     *   middleware(authMiddleware),
     *   route("dashboard", DashboardPage),
     * ])
     * ```
     * @param component - Static JSX or async handler for the layout
     * @param use - Callback returning child routes, middleware, loaders, etc.
     */
    layout: (component: ReactNode | Handler<any, any, TEnv>, use?: () => LayoutUseItem[]) => LayoutItem;
    /**
     * Define parallel routes that render simultaneously in named slots
     * ```typescript
     * parallel({
     *   "@sidebar": <Sidebar />,
     *   "@main": async (ctx) => <MainContent data={ctx.use(DataLoader)} />,
     * })
     *
     * // With loaders and loading states
     * parallel({
     *   "@analytics": AnalyticsPanel,
     *   "@metrics": MetricsPanel,
     * }, () => [
     *   loader(DashboardLoader),
     *   loading(<DashboardSkeleton />),
     * ])
     * ```
     * @param slots - Object with slot names (prefixed with @) mapped to handlers
     * @param use - Optional callback for loaders, loading, revalidate, etc.
     */
    parallel: <TSlots extends Record<`@${string}`, Handler<any, any, TEnv> | ReactNode>>(slots: TSlots, use?: () => ParallelUseItem[]) => ParallelItem;
    /**
     * Define an intercepting route for soft navigation
     *
     * When soft-navigating to the target route from within the current layout,
     * the intercept handler renders in the named slot instead of the route's
     * default handler. Direct navigation uses the route's handler.
     *
     * ```typescript
     * // In a layout - intercept "card" route as modal
     * layout(<KanbanLayout />, () => [
     *   intercept("@modal", "card", () => <CardModal />),
     * ])
     *
     * // With loaders and revalidation
     * intercept("@modal", "card", () => <CardModal />, () => [
     *   loader(CardModalLoader),
     *   revalidate(() => false),
     * ])
     * ```
     * @param slotName - Named slot (prefixed with @) where intercept renders
     * @param routeName - Route name to intercept
     * @param handler - Component or handler for intercepted render
     * @param use - Optional callback for loaders, middleware, revalidate, etc.
     */
    intercept: <K extends keyof ResolvedRouteMap<T> & string>(slotName: `@${string}`, routeName: K, handler: ReactNode | Handler<ExtractRouteParams<T, K>, {}, TEnv>, use?: () => InterceptUseItem[]) => InterceptItem;
    /**
     * Attach middleware to the current route/layout
     * ```typescript
     * middleware(async (ctx, next) => {
     *   const session = await getSession(ctx.request);
     *   if (!session) return redirect("/login");
     *   ctx.set("user", session.user);
     *   next();
     * })
     *
     * // Chain multiple middleware
     * middleware(authMiddleware, loggingMiddleware, rateLimitMiddleware)
     * ```
     * @param fns - One or more middleware functions to execute in order
     */
    middleware: (...fns: MiddlewareFn<TEnv>[]) => MiddlewareItem;
    /**
     * Control when a segment should revalidate during navigation
     * ```typescript
     * // Revalidate when params change
     * revalidate(({ currentParams, nextParams }) =>
     *   currentParams.slug !== nextParams.slug
     * )
     *
     * // Revalidate after specific actions (actionId format: "path/to/file.ts#exportName")
     * revalidate(({ actionId }) =>
     *   actionId?.includes("Cart") ?? false
     * )
     *
     * // Soft decision (suggest but allow override)
     * revalidate(({ defaultShouldRevalidate }) =>
     *   ({ defaultShouldRevalidate: true })
     * )
     * ```
     * @param fn - Function that returns boolean (hard) or { defaultShouldRevalidate } (soft)
     */
    revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
    /**
     * Attach a data loader to the current route/layout
     * ```typescript
     * loader(ProductLoader)
     *
     * // With loader-specific revalidation (match by file or export name)
     * loader(CartLoader, () => [
     *   revalidate(({ actionId }) => actionId?.includes("Cart") ?? false),
     * ])
     *
     * // Access loader data in handlers via ctx.use()
     * route("products.detail", async (ctx) => {
     *   const product = await ctx.use(ProductLoader);
     *   return <ProductPage product={product} />;
     * })
     * ```
     * @param loaderDef - Loader created with createLoader()
     * @param use - Optional callback for loader-specific revalidation rules
     */
    loader: <TData>(loaderDef: LoaderDefinition<TData>, use?: () => LoaderUseItem[]) => LoaderItem;
    /**
     * Attach a loading component to the current route/layout
     * ```typescript
     * // Show loading on all requests (including SSR)
     * loading(<Skeleton />)
     *
     * // Skip loading on SSR, only show on client navigation
     * loading(<Skeleton />, { ssr: false })
     * ```
     * @param component - The loading UI to show during navigation
     * @param options - Configuration options
     * @param options.ssr - If false, skip showing loading on document requests (SSR)
     */
    loading: (component: ReactNode, options?: {
        ssr?: boolean;
    }) => LoadingItem;
    /**
     * Attach an error boundary to catch errors in this segment and children
     * ```typescript
     * errorBoundary(<ErrorFallback />)
     *
     * // With dynamic error handler
     * errorBoundary(({ error, reset }) => (
     *   <div>
     *     <h2>Something went wrong</h2>
     *     <p>{error.message}</p>
     *     <button onClick={reset}>Try again</button>
     *   </div>
     * ))
     * ```
     * @param fallback - Static JSX or handler receiving error info and reset function
     */
    errorBoundary: (fallback: ReactNode | ErrorBoundaryHandler) => ErrorBoundaryItem;
    /**
     * Attach a not-found boundary to handle notFound() calls in this segment
     * ```typescript
     * notFoundBoundary(<ProductNotFound />)
     *
     * // With dynamic handler
     * notFoundBoundary(({ notFound }) => (
     *   <div>
     *     <h2>{notFound.message}</h2>
     *     <a href="/products">Browse all products</a>
     *   </div>
     * ))
     * ```
     * @param fallback - Static JSX or handler receiving not-found info
     */
    notFoundBoundary: (fallback: ReactNode | NotFoundBoundaryHandler) => NotFoundBoundaryItem;
    /**
     * Define a condition for when an intercept should activate
     *
     * Only valid inside intercept() use() callback. When multiple when() calls
     * are present, ALL must return true for the intercept to activate.
     * If no when() is defined, the intercept always activates on soft navigation.
     *
     * Context properties:
     * - `from` - Source URL (where user is navigating from)
     * - `to` - Destination URL (where user is navigating to)
     * - `params` - Matched route params
     * - `segments` - Client's current segments with `path` and `ids`
     *
     * ```typescript
     * // Only intercept when coming from the board page
     * intercept("@modal", "card", <CardModal />, () => [
     *   when(({ from }) => from.pathname.startsWith("/board")),
     *   loader(CardDetailLoader),
     * ])
     *
     * // Use segments to check current route context
     * intercept("@modal", "card", <CardModal />, () => [
     *   when(({ segments }) => segments.path[0] === "kanban"),
     * ])
     *
     * // Multiple conditions (AND logic)
     * intercept("@modal", "card", <CardModal />, () => [
     *   when(({ from }) => from.pathname.startsWith("/board")),
     *   when(({ segments }) => segments.ids.includes("kanban-layout")),
     * ])
     * ```
     * @param fn - Selector function receiving navigation context, returns boolean
     */
    when: (fn: InterceptWhenFn) => WhenItem;
    /**
     * Define cache configuration for segments
     *
     * Creates a cache boundary that applies to all children unless overridden.
     * Cache config inherits down the route tree like middleware wrapping.
     *
     * When ttl is not specified, uses store defaults (explicit store first,
     * then app-level store). When store is not specified, uses app-level store.
     *
     * Note: Loaders are NOT cached by default. Use cache() inside loader()
     * to explicitly opt-in to loader caching.
     *
     * ```typescript
     * // Using app-level defaults (ttl inherited from store.defaults)
     * cache(() => [
     *   layout(<BlogLayout />),      // cached with default TTL
     *   route("post/:slug"),         // cached with default TTL
     * ])
     *
     * // Cache all segments with explicit 60s TTL
     * cache({ ttl: 60 }, () => [
     *   layout(<BlogLayout />),      // cached
     *   route("post/:slug"),         // cached
     * ])
     *
     * // With stale-while-revalidate
     * cache({ ttl: 60, swr: 300 }, () => [
     *   route("product/:id"),
     * ])
     *
     * // Override for specific section
     * cache({ ttl: 60 }, () => [
     *   layout(<RootLayout />),
     *   cache({ ttl: 300 }, () => [
     *     route("static-page"),     // longer TTL
     *   ]),
     *   cache(false, () => [
     *     route("admin"),           // not cached
     *   ]),
     * ])
     *
     * // Use different store for specific routes
     * cache({ store: kvStore, ttl: 3600 }, () => [
     *   route("archive/:year"),     // uses KV store
     * ])
     *
     * // Opt-in loader caching
     * route("product/:id", ProductHandler, () => [
     *   loader(ProductLoader),               // NOT cached (default)
     *   loader(StaticMetadata, () => [
     *     cache({ ttl: 3600 }),              // cached for 1 hour
     *   ]),
     * ])
     * ```
     * @param optionsOrChildren - Cache options, false to disable, or children callback
     * @param children - Optional callback returning child segments (when first arg is options)
     */
    cache: {
        (): CacheItem;
        (children: () => AllUseItems[]): CacheItem;
        (options: PartialCacheOptions | false, use?: () => AllUseItems[]): CacheItem;
    };
};
/**
 * Branded type for route handlers that carries the route type info.
 * This enables type-safe verification that imported handlers match route definitions.
 */
export interface RouteHandlers<T extends RouteDefinition> {
    (): Array<AllUseItems>;
    /** Brand to carry route type info for type checking */
    readonly __routes: T;
}
/**
 * Type-safe handler definition helper
 *
 */
export declare function map<const T extends RouteDefinition, TEnv = DefaultEnv>(builder: (helpers: RouteHelpers<T, TEnv>) => Array<AllUseItems>): RouteHandlers<T>;
/**
 * Create RouteHelpers for inline route definitions
 * Used internally by router.map() for inline handler syntax
 */
export declare function createRouteHelpers<T extends RouteDefinition, TEnv>(): RouteHelpers<T, TEnv>;
/**
 * Create a loader definition
 *
 * Loaders are RSC-compatible data fetchers that:
 * - Run after middleware, before handlers
 * - Are scoped to where attached (layout/route subtree)
 * - Revalidate independently from UI segments
 * - Are memoized per request (multiple ctx.use() calls return same value)
 *
 * Use the `"use server"` directive inside the loader function to ensure
 * the function is stripped from client bundles.
 *
 * Return type is automatically inferred from the callback.
 *
 * @param fn - Async function that fetches data (should contain "use server" directive)
 * @param fetchable - Optional flag to make the loader fetchable via useFetchLoader
 *
 * @example
 * ```typescript
 * // loaders/cart.ts - return type inferred from callback
 * export const CartLoader = createLoader(async (ctx) => {
 *   "use server";
 *   const user = ctx.get("user");
 *   return await db.cart.get(user.id); // Return type inferred!
 * });
 *
 * // loaders/product.ts - return type inferred
 * export const ProductLoader = createLoader(async (ctx) => {
 *   "use server";
 *   const { slug } = ctx.params;
 *   return await db.products.findBySlug(slug); // Return type inferred!
 * });
 *
 * // Usage in handlers
 * layout(<ShopLayout />, () => [
 *   loader(CartLoader),
 *   loader(CartLoader, () => [
 *     revalidate(({ actionId }) => actionId?.includes("Cart") ?? false),
 *   ]),
 * ])
 *
 * // Server-side access
 * route("cart", (ctx) => {
 *   const cart = ctx.use(CartLoader);
 *   return <CartPage cart={cart} />;
 * });
 *
 * // Client-side access
 * const cart = useLoader(CartLoader);
 * ```
 */
export { createLoader } from "./loader.rsc.js";
/**
 * Create a soft redirect Response for middleware short-circuit
 *
 * Returns a Response that signals a client-side navigation to the target URL.
 * Unlike Response.redirect() which causes a full page reload, this redirect
 * is handled by the router for SPA-style navigation.
 *
 * @param url - The URL to redirect to
 * @param status - HTTP status code (default: 302)
 *
 * @example
 * ```typescript
 * middleware((ctx, next) => {
 *   if (!ctx.get('user')) {
 *     return redirect('/login');
 *   }
 *   next();
 * })
 * ```
 */
export declare function redirect(url: string, status?: number): Response;
//# sourceMappingURL=route-definition.d.ts.map