/**
* Public type surface for the AbsoluteJS Svelte router.
*
* `ExtractRouteParams
` walks a path-pattern string literal and produces
* a typed `params` shape:
*
* ExtractRouteParams<'/users/:id'> → { id: string }
* ExtractRouteParams<'/users/:id/posts/:pid'> → { id: string; pid: string }
* ExtractRouteParams<'/users/:id?'> → { id: string | undefined }
* ExtractRouteParams<'/files/*'> → { wildcard: string }
* ExtractRouteParams<'/dashboard'> → Record
*
* Edge cases:
* - Optional params (`:name?`) appear as `string | undefined`
* - Wildcard tail (`*`) is exposed as the `wildcard` key
* - Same-name twice in one path is intentionally not detected at the type
* level (it's a logic bug in the user's pattern, not something the type
* system meaningfully rescues).
*/
type IsOptionalParamSegment =
Segment extends `${string}?` ? true : false;
type StripOptionalSuffix =
Segment extends `${infer Name}?` ? Name : Segment;
type WildcardSegment = '*' | `*${string}`;
type ParseSegment = Segment extends WildcardSegment
? { wildcard: string }
: Segment extends `:${infer Name}`
? IsOptionalParamSegment extends true
? { [K in StripOptionalSuffix]: string | undefined }
: { [K in Name]: string }
: Record;
type SplitPath = Path extends `/${infer Rest}`
? SplitPath
: Path extends `${infer Head}/${infer Tail}`
? ParseSegment & SplitPath
: ParseSegment;
type Simplify = { [K in keyof T]: T[K] } & {};
export type ExtractRouteParams = string extends Path
? Record
: Simplify> extends infer Result
? keyof Result extends never
? Record
: Result
: never;
export type RouteMatch> = {
matched: true;
params: Params;
};
export type RouteMiss = {
matched: false;
};
export type RouteMatchResult> =
| RouteMatch
| RouteMiss;
export type RouterMode = 'history' | 'hash';
export type GotoOptions = {
/** Use `history.replaceState` instead of `pushState`. */
replaceState?: boolean;
/** Don't reset focus to body on navigation. */
keepFocus?: boolean;
/** Don't scroll to top on navigation. */
noScroll?: boolean;
/** Value attached to `history.state`. */
state?: unknown;
};
export type LinkPrefetchMode = 'hover' | 'viewport' | 'none';
export type PageState = {
url: URL;
params: Record;
state: unknown;
};
export type RouterContextValue = {
/** Stacked basepath from outer to inner Router (joined). */
basepath: string;
mode: RouterMode;
};