@studiolambda/router 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/matcher-CSJ3hjzA.cjs +2 -0
  4. package/dist/matcher-CSJ3hjzA.cjs.map +1 -0
  5. package/dist/matcher-XNPYU-tD.js +69 -0
  6. package/dist/matcher-XNPYU-tD.js.map +1 -0
  7. package/dist/router.cjs +1 -0
  8. package/dist/router.js +2 -0
  9. package/dist/router_react.cjs +6 -0
  10. package/dist/router_react.cjs.map +1 -0
  11. package/dist/router_react.js +506 -0
  12. package/dist/router_react.js.map +1 -0
  13. package/dist/src/react/ExampleMain.d.ts +7 -0
  14. package/dist/src/react/components/Link.d.ts +91 -0
  15. package/dist/src/react/components/Middlewares.d.ts +28 -0
  16. package/dist/src/react/components/NotFound.d.ts +6 -0
  17. package/dist/src/react/components/Router.d.ts +81 -0
  18. package/dist/src/react/context/MatcherContext.d.ts +12 -0
  19. package/dist/src/react/context/NavigationContext.d.ts +11 -0
  20. package/dist/src/react/context/NavigationSignalContext.d.ts +7 -0
  21. package/dist/src/react/context/NavigationTypeContext.d.ts +6 -0
  22. package/dist/src/react/context/PathnameContext.d.ts +10 -0
  23. package/dist/src/react/context/PropsContext.d.ts +10 -0
  24. package/dist/src/react/context/TransitionContext.d.ts +19 -0
  25. package/dist/src/react/createRouter.d.ts +187 -0
  26. package/dist/src/react/example.d.ts +1 -0
  27. package/dist/src/react/examples/Auth.d.ts +11 -0
  28. package/dist/src/react/examples/HelloWorld.d.ts +5 -0
  29. package/dist/src/react/examples/Other.d.ts +6 -0
  30. package/dist/src/react/examples/User.d.ts +6 -0
  31. package/dist/src/react/extractPathname.d.ts +17 -0
  32. package/dist/src/react/hooks/useActiveLinkProps.d.ts +73 -0
  33. package/dist/src/react/hooks/useBack.d.ts +47 -0
  34. package/dist/src/react/hooks/useForward.d.ts +47 -0
  35. package/dist/src/react/hooks/useIsPending.d.ts +29 -0
  36. package/dist/src/react/hooks/useNavigate.d.ts +10 -0
  37. package/dist/src/react/hooks/useNavigation.d.ts +13 -0
  38. package/dist/src/react/hooks/useNavigationEvents.d.ts +43 -0
  39. package/dist/src/react/hooks/useNavigationHandlers.d.ts +47 -0
  40. package/dist/src/react/hooks/useNavigationSignal.d.ts +13 -0
  41. package/dist/src/react/hooks/useNavigationType.d.ts +12 -0
  42. package/dist/src/react/hooks/useNextMatch.d.ts +26 -0
  43. package/dist/src/react/hooks/useParams.d.ts +19 -0
  44. package/dist/src/react/hooks/usePathname.d.ts +23 -0
  45. package/dist/src/react/hooks/usePrefetch.d.ts +27 -0
  46. package/dist/src/react/hooks/usePrefetchEffect.d.ts +69 -0
  47. package/dist/src/react/hooks/useSearchParams.d.ts +58 -0
  48. package/dist/src/react/index.d.ts +31 -0
  49. package/dist/src/react/navigation/createMemoryNavigation.d.ts +52 -0
  50. package/dist/src/react/router.d.ts +139 -0
  51. package/dist/src/react/test-helpers.d.ts +50 -0
  52. package/dist/src/router/index.d.ts +1 -0
  53. package/dist/src/router/matcher.d.ts +127 -0
  54. package/package.json +107 -0
@@ -0,0 +1,27 @@
1
+ import { Handler } from '../router';
2
+ import { Matcher } from '../../router/matcher';
3
+ /**
4
+ * Options for the `usePrefetch` hook.
5
+ */
6
+ export interface PrefetchOptions {
7
+ /**
8
+ * Optional matcher override. When omitted the hook reads
9
+ * from `MatcherContext`.
10
+ */
11
+ matcher?: Matcher<Handler>;
12
+ }
13
+ /**
14
+ * Returns a function that triggers the prefetch logic for a
15
+ * given URL by resolving it against the matcher and calling
16
+ * the route's prefetch function. Used by the Link component
17
+ * for hover and viewport prefetch strategies.
18
+ *
19
+ * Since prefetch triggered from Link happens outside of a
20
+ * navigation event, a stub NavigationPrecommitController is
21
+ * passed (the redirect capability is not meaningful here).
22
+ *
23
+ * @param options - Optional matcher override.
24
+ * @returns A function that accepts a URL string and invokes
25
+ * the matched route's prefetch handler, if any.
26
+ */
27
+ export declare function usePrefetch(options?: PrefetchOptions): (url: string) => void | Promise<void>;
@@ -0,0 +1,69 @@
1
+ import { RefObject } from 'react';
2
+ import { Handler } from '../router';
3
+ import { Matcher } from '../../router/matcher';
4
+ /**
5
+ * Prefetch trigger strategy. Determines which DOM event
6
+ * activates the prefetch for the target element.
7
+ *
8
+ * - `viewport` — prefetch fires when the element enters
9
+ * the viewport via an IntersectionObserver.
10
+ * - `hover` — prefetch fires on `mouseenter`.
11
+ */
12
+ export type PrefetchStrategy = 'viewport' | 'hover';
13
+ /**
14
+ * Options for the `usePrefetchEffect` hook.
15
+ */
16
+ export interface PrefetchEffectOptions {
17
+ /**
18
+ * The URL to prefetch. When undefined, the effect is
19
+ * a no-op (no observer or listener is attached).
20
+ */
21
+ href: string | undefined;
22
+ /**
23
+ * Prefetch trigger strategy. When undefined, the effect
24
+ * is a no-op — no proactive prefetch is set up.
25
+ */
26
+ on: PrefetchStrategy | undefined;
27
+ /**
28
+ * Whether to only prefetch once. When true, hover
29
+ * listeners use the `{ once }` option and viewport
30
+ * observers disconnect after the first intersection.
31
+ * Defaults to `true`.
32
+ */
33
+ once?: boolean;
34
+ /**
35
+ * Optional matcher override. When omitted, reads from
36
+ * `MatcherContext` via `usePrefetch`.
37
+ */
38
+ matcher?: Matcher<Handler>;
39
+ }
40
+ /**
41
+ * Attaches prefetch behavior to a DOM element via a ref.
42
+ * Sets up an IntersectionObserver (for `viewport` strategy)
43
+ * or a mouseenter listener (for `hover` strategy) that
44
+ * triggers route prefetching when activated.
45
+ *
46
+ * When `on` is undefined or `href` is undefined, no
47
+ * observer or listener is attached — the hook is a no-op.
48
+ *
49
+ * This hook is used internally by the Link component and
50
+ * can also be used standalone to add prefetch behavior to
51
+ * any DOM element.
52
+ *
53
+ * @param ref - A ref to the DOM element to observe. The
54
+ * element must be mounted before the effect runs.
55
+ * @param options - Configuration for the prefetch behavior
56
+ * including the URL, trigger strategy, and matcher.
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * function Card({ href }: { href: string }) {
61
+ * const ref = useRef<HTMLDivElement>(null)
62
+ *
63
+ * usePrefetchEffect(ref, { href, on: 'viewport' })
64
+ *
65
+ * return <div ref={ref}>...</div>
66
+ * }
67
+ * ```
68
+ */
69
+ export declare function usePrefetchEffect(ref: RefObject<Element | null>, options: PrefetchEffectOptions): void;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Updater function signature for setting search params.
3
+ * Accepts either a new URLSearchParams instance, a plain
4
+ * record of string key-value pairs, or a function that
5
+ * receives the current params and returns updated params.
6
+ */
7
+ export type SearchParamsUpdater = URLSearchParams | Record<string, string> | ((current: URLSearchParams) => URLSearchParams | Record<string, string>);
8
+ /**
9
+ * Options for the search params navigation performed by
10
+ * the setter function returned from `useSearchParams`.
11
+ */
12
+ export interface SetSearchParamsOptions {
13
+ /**
14
+ * History behavior for the navigation. Defaults to
15
+ * `'replace'` since search param changes typically
16
+ * should not create new history entries.
17
+ */
18
+ history?: NavigationHistoryBehavior;
19
+ }
20
+ /**
21
+ * Returns the current URL's search parameters as a
22
+ * `URLSearchParams` instance and a setter function to
23
+ * update them via navigation.
24
+ *
25
+ * The getter reads from `navigation.currentEntry.url`
26
+ * on each render, so it always reflects the committed
27
+ * URL. The setter performs a navigation with the updated
28
+ * search string, defaulting to `history: 'replace'` to
29
+ * avoid polluting the history stack with parameter changes.
30
+ *
31
+ * The React Compiler handles memoization of the setter,
32
+ * so no manual `useCallback` is needed.
33
+ *
34
+ * Must be used inside a `<Router>` component tree.
35
+ *
36
+ * @returns A tuple of `[searchParams, setSearchParams]`.
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * function SearchPage() {
41
+ * const [searchParams, setSearchParams] = useSearchParams()
42
+ * const query = searchParams.get('q') ?? ''
43
+ *
44
+ * return (
45
+ * <input
46
+ * value={query}
47
+ * onChange={function (event) {
48
+ * setSearchParams({ q: event.target.value })
49
+ * }}
50
+ * />
51
+ * )
52
+ * }
53
+ * ```
54
+ */
55
+ export declare function useSearchParams(): [
56
+ URLSearchParams,
57
+ (updater: SearchParamsUpdater, options?: SetSearchParamsOptions) => NavigationResult
58
+ ];
@@ -0,0 +1,31 @@
1
+ export * from './components/Middlewares';
2
+ export * from './components/Router';
3
+ export * from './components/NotFound';
4
+ export * from './components/Link';
5
+ export * from './context/MatcherContext';
6
+ export * from './context/TransitionContext';
7
+ export * from './context/PropsContext';
8
+ export * from './context/NavigationContext';
9
+ export * from './context/NavigationSignalContext';
10
+ export * from './context/NavigationTypeContext';
11
+ export * from './context/PathnameContext';
12
+ export * from './hooks/useNavigation';
13
+ export * from './hooks/useNavigate';
14
+ export * from './hooks/useNavigationSignal';
15
+ export * from './hooks/useNavigationType';
16
+ export * from './hooks/usePrefetch';
17
+ export * from './hooks/useNextMatch';
18
+ export * from './hooks/useNavigationHandlers';
19
+ export * from './hooks/useParams';
20
+ export * from './hooks/useIsPending';
21
+ export * from './hooks/usePathname';
22
+ export * from './hooks/useSearchParams';
23
+ export * from './hooks/useBack';
24
+ export * from './hooks/useForward';
25
+ export * from './hooks/useNavigationEvents';
26
+ export * from './hooks/useActiveLinkProps';
27
+ export * from './hooks/usePrefetchEffect';
28
+ export * from './navigation/createMemoryNavigation';
29
+ export * from './extractPathname';
30
+ export * from './createRouter';
31
+ export * from './router';
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Options for creating a memory navigation instance.
3
+ */
4
+ export interface MemoryNavigationOptions {
5
+ /**
6
+ * The initial URL for the memory navigation. This is the
7
+ * URL that `currentEntry.url` will return. Typically the
8
+ * request URL from the server for SSR, or a test URL.
9
+ *
10
+ * @example `'https://example.com/user/42?tab=posts'`
11
+ */
12
+ readonly url: string;
13
+ }
14
+ /**
15
+ * Creates a minimal in-memory Navigation object suitable for
16
+ * server-side rendering and testing environments where the
17
+ * browser Navigation API is unavailable.
18
+ *
19
+ * The returned object satisfies the subset of the `Navigation`
20
+ * interface consumed by the Router component:
21
+ *
22
+ * - `currentEntry.url` — returns the initial URL
23
+ * - `addEventListener` / `removeEventListener` — no-ops
24
+ * (no events fire in a memory environment)
25
+ * - `navigate()` — no-op that returns a NavigationResult
26
+ * with immediately-resolved promises
27
+ * - `canGoBack` / `canGoForward` — always false
28
+ * - `entries()` — returns a single-entry array
29
+ *
30
+ * The object is cast to `Navigation` for compatibility with
31
+ * the Router's `navigation` prop and `NavigationContext`.
32
+ * Properties not listed above are not implemented and will
33
+ * throw if accessed by consumer code outside the Router.
34
+ *
35
+ * @param options - Configuration including the initial URL.
36
+ * @returns A Navigation-compatible object for SSR or testing.
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * // Server-side rendering
41
+ * const navigation = createMemoryNavigation({
42
+ * url: request.url,
43
+ * })
44
+ *
45
+ * const html = renderToString(
46
+ * <Router navigation={navigation} matcher={matcher}>
47
+ * <App />
48
+ * </Router>
49
+ * )
50
+ * ```
51
+ */
52
+ export declare function createMemoryNavigation(options: MemoryNavigationOptions): Navigation;
@@ -0,0 +1,139 @@
1
+ import { ReactNode, ComponentType } from 'react';
2
+ /**
3
+ * Defines the route handler configuration for a matched route.
4
+ * Contains the component to render, optional prefetch logic,
5
+ * middleware components, scroll/focus behavior, and form handling.
6
+ */
7
+ export interface Handler {
8
+ /**
9
+ * The React component to render for this route.
10
+ * Can be a regular component or a `lazy()` component
11
+ * for code-split routes.
12
+ */
13
+ readonly component: ComponentType;
14
+ /**
15
+ * Optional prefetch function invoked during the precommit phase.
16
+ * Receives a context with matched route params, destination URL,
17
+ * and the precommit controller for redirects.
18
+ */
19
+ readonly prefetch?: PrefetchFunc;
20
+ /**
21
+ * Middleware components that wrap the route component.
22
+ * Applied via reduceRight so the first middleware in
23
+ * the array wraps outermost, and the last wraps innermost.
24
+ */
25
+ readonly middlewares?: ComponentType<MiddlewareProps>[];
26
+ /**
27
+ * Controls whether the browser performs scroll restoration
28
+ * after the navigation handler completes.
29
+ * - `after-transition` (default): browser handles scrolling
30
+ * after the handler promise resolves.
31
+ * - `manual`: disables automatic scrolling so the route
32
+ * component can call `event.scroll()` manually.
33
+ */
34
+ readonly scroll?: NavigationScrollBehavior;
35
+ /**
36
+ * Controls whether the browser resets focus after navigation.
37
+ * - `after-transition` (default): focuses the first autofocus
38
+ * element or the body after the handler resolves.
39
+ * - `manual`: disables automatic focus reset so the route
40
+ * component can manage focus manually.
41
+ */
42
+ readonly focusReset?: NavigationFocusReset;
43
+ /**
44
+ * Optional handler for form submissions (POST navigations).
45
+ * When a navigation includes FormData and the matched route
46
+ * has a formHandler, it is called instead of the normal
47
+ * component render flow.
48
+ */
49
+ readonly formHandler?: FormHandler;
50
+ }
51
+ /**
52
+ * Context passed to prefetch functions during the precommit
53
+ * phase of a navigation. Provides the matched route parameters,
54
+ * the destination URL, and the Navigation API's precommit
55
+ * controller for redirects.
56
+ */
57
+ export interface PrefetchContext {
58
+ /**
59
+ * Dynamic route parameters extracted from the matched URL
60
+ * pattern. For example, a route registered as `/user/:id`
61
+ * matching `/user/42` produces `{ id: '42' }`.
62
+ */
63
+ readonly params: Record<string, string>;
64
+ /**
65
+ * The full destination URL being navigated to. Includes
66
+ * the pathname, search parameters, and hash. Useful for
67
+ * constructing query keys or reading search params during
68
+ * prefetch.
69
+ */
70
+ readonly url: URL;
71
+ /**
72
+ * The precommit controller from the Navigation API,
73
+ * providing `redirect()` to abort the current navigation
74
+ * and redirect elsewhere, and `addHandler()` to register
75
+ * additional post-commit handlers. When prefetch is
76
+ * triggered outside a real navigation (e.g. Link hover),
77
+ * this is a stub with no-op methods.
78
+ */
79
+ readonly controller: NavigationPrecommitController;
80
+ }
81
+ /**
82
+ * Function invoked during the precommit phase of a navigation.
83
+ * Receives a context object with the matched route parameters,
84
+ * destination URL, and the Navigation API's precommit controller
85
+ * for redirects or additional handler registration.
86
+ *
87
+ * @param context - The prefetch context containing route params,
88
+ * destination URL, and the precommit controller.
89
+ * @returns Void or a promise that resolves when prefetching
90
+ * is complete.
91
+ */
92
+ export type PrefetchFunc = {
93
+ (context: PrefetchContext): void | Promise<void>;
94
+ };
95
+ /**
96
+ * Target for a redirect route. Can be a static absolute path
97
+ * string, or a callback that receives the prefetch context and
98
+ * returns the path to redirect to. The callback form enables
99
+ * dynamic redirects that use matched route parameters or the
100
+ * destination URL to compute the target.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * // Static redirect
105
+ * route('/old').redirect('/new')
106
+ *
107
+ * // Dynamic redirect using route params
108
+ * route('/old-user/:id').redirect(({ params }) => `/user/${params.id}`)
109
+ * ```
110
+ */
111
+ export type RedirectTarget = string | ((context: PrefetchContext) => string);
112
+ /**
113
+ * Handler invoked when a form submission navigation matches
114
+ * this route. Receives the submitted FormData and the original
115
+ * NavigateEvent for full access to the navigation context.
116
+ *
117
+ * @param formData - The FormData from the submitted form.
118
+ * @param event - The original NavigateEvent that triggered
119
+ * the form submission.
120
+ * @returns Void or a promise that resolves when the form
121
+ * submission handling is complete.
122
+ */
123
+ export type FormHandler = {
124
+ (formData: FormData, event: NavigateEvent): void | Promise<void>;
125
+ };
126
+ /**
127
+ * Props passed to middleware wrapper components. Each middleware
128
+ * receives `children` and decides whether to render them,
129
+ * enabling patterns like authentication guards and layout
130
+ * wrappers.
131
+ */
132
+ export interface MiddlewareProps {
133
+ /**
134
+ * The downstream content to render. A middleware can choose
135
+ * to render this directly, wrap it in additional providers,
136
+ * or omit it entirely (e.g. for auth redirects).
137
+ */
138
+ children: ReactNode;
139
+ }
@@ -0,0 +1,50 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Result returned by `renderHook`. Provides access to the
4
+ * current hook return value and a cleanup function.
5
+ *
6
+ * @typeParam T - The return type of the hook under test.
7
+ */
8
+ export interface RenderHookResult<T> {
9
+ /**
10
+ * The current return value of the hook. Updated after
11
+ * each render.
12
+ */
13
+ readonly current: T;
14
+ /**
15
+ * Unmounts the test component and removes it from the
16
+ * DOM. Must be called after each test to avoid leaks.
17
+ */
18
+ readonly unmount: () => void;
19
+ }
20
+ /**
21
+ * Options for `renderHook`.
22
+ *
23
+ * @typeParam T - The return type of the hook under test.
24
+ */
25
+ export interface RenderHookOptions {
26
+ /**
27
+ * Optional wrapper component that provides context
28
+ * providers around the hook test component.
29
+ */
30
+ wrapper?: (props: {
31
+ children: ReactNode;
32
+ }) => ReactNode;
33
+ }
34
+ /**
35
+ * Renders a React hook inside a minimal test component and
36
+ * returns the hook's current value. Mimics the API of
37
+ * `@testing-library/react`'s `renderHook` without requiring
38
+ * that dependency.
39
+ *
40
+ * The hook is rendered inside an `act()` boundary. The
41
+ * returned `current` property always reflects the latest
42
+ * hook return value.
43
+ *
44
+ * @typeParam T - The return type of the hook.
45
+ * @param hook - A function that calls the hook under test
46
+ * and returns its result.
47
+ * @param options - Optional wrapper for context providers.
48
+ * @returns The hook result and an unmount function.
49
+ */
50
+ export declare function renderHook<T>(hook: () => T, options?: RenderHookOptions): RenderHookResult<T>;
@@ -0,0 +1 @@
1
+ export * from './matcher';
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Describes a route matcher that maps URL path patterns to
3
+ * handlers. Supports static segments, dynamic `:param`
4
+ * segments, and wildcard `*param` segments with a trie-based
5
+ * lookup.
6
+ *
7
+ * @typeParam T - The handler type associated with each route.
8
+ */
9
+ export interface Matcher<T> {
10
+ /**
11
+ * Registers a route pattern with a corresponding handler.
12
+ * Patterns use `/`-separated segments where `:name` denotes
13
+ * a dynamic parameter (e.g. `/user/:id/posts`) and `*name`
14
+ * denotes a wildcard that captures the rest of the path
15
+ * (e.g. `/files/*path`). A bare `*` captures into a param
16
+ * named `'*'`.
17
+ *
18
+ * @param pattern - The URL path pattern to register.
19
+ * @param handler - The handler to associate with this pattern.
20
+ */
21
+ readonly register: (pattern: string, handler: T) => void;
22
+ /**
23
+ * Attempts to match a URL path against registered routes.
24
+ * Static segments take priority over dynamic ones, which
25
+ * take priority over wildcard segments. Returns the matched
26
+ * handler and extracted parameters, or `null` if no route
27
+ * matches.
28
+ *
29
+ * @param path - The URL path to match (e.g. `/user/42`).
30
+ * @returns The resolved match with handler and params, or null.
31
+ */
32
+ readonly match: (path: string) => Resolved<T> | null;
33
+ }
34
+ /**
35
+ * The result of a successful route match. Contains the handler
36
+ * registered for the matched pattern and a record of extracted
37
+ * dynamic parameters.
38
+ *
39
+ * @typeParam T - The handler type associated with the route.
40
+ */
41
+ export interface Resolved<T> {
42
+ /**
43
+ * The handler that was registered for the matched route pattern.
44
+ */
45
+ readonly handler: T;
46
+ /**
47
+ * Dynamic path parameters extracted from the URL. Keys are the
48
+ * parameter names from the pattern (without the `:` prefix),
49
+ * values are the corresponding URL segments.
50
+ *
51
+ * @example
52
+ * Pattern `/user/:id` matched against `/user/42`
53
+ * produces `{ id: "42" }`.
54
+ */
55
+ readonly params: Record<string, string>;
56
+ }
57
+ /**
58
+ * Configuration options for creating a new matcher instance.
59
+ *
60
+ * @typeParam T - The handler type associated with each route.
61
+ */
62
+ export interface Options<T> {
63
+ /**
64
+ * An existing trie root node to use instead of creating
65
+ * an empty one. Useful for pre-built or shared route trees.
66
+ */
67
+ readonly root?: Node<T>;
68
+ }
69
+ /**
70
+ * A node in the route-matching trie. Each node represents a
71
+ * single URL path segment and may hold a handler (indicating
72
+ * a complete route), static children (keyed by segment string),
73
+ * a single dynamic child (for `:param` segments), and/or a
74
+ * wildcard child (for `*param` segments that capture the rest
75
+ * of the path).
76
+ *
77
+ * @typeParam T - The handler type associated with each route.
78
+ */
79
+ export interface Node<T> {
80
+ /**
81
+ * Map of static child segments. Each key is a literal path
82
+ * segment string (e.g. `"user"`, `"posts"`).
83
+ */
84
+ readonly children: Map<string, Node<T>>;
85
+ /**
86
+ * The handler registered at this node, or `undefined` if
87
+ * this node is only an intermediate segment in a longer
88
+ * pattern.
89
+ */
90
+ handler?: T;
91
+ /**
92
+ * The single dynamic child node for `:param` segments.
93
+ * Only one dynamic segment is allowed per trie level.
94
+ */
95
+ child?: Node<T>;
96
+ /**
97
+ * The parameter name for this dynamic segment (without the
98
+ * `:` prefix). Only set on nodes created from `:param`
99
+ * patterns.
100
+ */
101
+ readonly name?: string;
102
+ /**
103
+ * The wildcard child node for `*param` segments. Captures
104
+ * all remaining path segments into a single parameter.
105
+ * Only one wildcard is allowed per trie level and it must
106
+ * be the last segment in the pattern.
107
+ */
108
+ wildcard?: Node<T>;
109
+ }
110
+ /**
111
+ * Creates a new trie-based route matcher. Routes are registered
112
+ * with patterns containing static segments, dynamic (`:param`)
113
+ * segments, and wildcard (`*param`) segments. Matching
114
+ * prioritises static segments over dynamic ones, and dynamic
115
+ * over wildcards, performing a depth-first search through the
116
+ * trie.
117
+ *
118
+ * Wildcard segments capture all remaining path segments into a
119
+ * single parameter joined by `/`. A bare `*` captures into
120
+ * a param named `'*'`. Wildcards must be the last segment
121
+ * in a pattern.
122
+ *
123
+ * @typeParam T - The handler type associated with each route.
124
+ * @param options - Optional configuration with a pre-built root node.
125
+ * @returns A matcher instance with `register` and `match` methods.
126
+ */
127
+ export declare function createMatcher<T>(options?: Options<T>): Matcher<T>;
package/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@studiolambda/router",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "keywords": [
6
+ "router",
7
+ "react-router",
8
+ "isomorphic",
9
+ "routing",
10
+ "url",
11
+ "management",
12
+ "history",
13
+ "location"
14
+ ],
15
+ "description": "Lightweight, isomorphic and framework agnostic router for modern UIs",
16
+ "author": {
17
+ "name": "Erik C. Forés",
18
+ "email": "soc@erik.cat",
19
+ "url": "https://erik.cat"
20
+ },
21
+ "homepage": "https://erik.cat/blog/router-docs",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/StudioLambda/Router.git"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "type": "module",
30
+ "types": "./dist/src/router/index.d.ts",
31
+ "main": "./dist/router.cjs",
32
+ "module": "./dist/router.js",
33
+ "exports": {
34
+ "./package.json": "./package.json",
35
+ ".": {
36
+ "types": "./dist/src/router/index.d.ts",
37
+ "import": "./dist/router.js",
38
+ "require": "./dist/router.cjs"
39
+ },
40
+ "./react": {
41
+ "types": "./dist/src/react/index.d.ts",
42
+ "import": "./dist/router_react.js",
43
+ "require": "./dist/router_react.cjs"
44
+ }
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "package.json"
49
+ ],
50
+ "scripts": {
51
+ "build:only": "vite build",
52
+ "build": "npm run build:only",
53
+ "prebuild": "npm run format:check && npm run lint",
54
+ "lint": "oxlint",
55
+ "format": "oxfmt --write .",
56
+ "format:check": "oxfmt --check .",
57
+ "dev": "vite .",
58
+ "test": "vitest run",
59
+ "test:ui": "vitest --ui --coverage",
60
+ "test:cover": "vitest run --coverage",
61
+ "prepack": "npm run build"
62
+ },
63
+ "devEngines": {
64
+ "packageManager": {
65
+ "name": "npm",
66
+ "version": ">=11.0.0"
67
+ },
68
+ "runtime": {
69
+ "name": "node",
70
+ "version": ">=24.0.0"
71
+ }
72
+ },
73
+ "peerDependencies": {
74
+ "react": "^19.2.0",
75
+ "react-dom": "^19.2.0"
76
+ },
77
+ "peerDependenciesMeta": {
78
+ "react": {
79
+ "optional": true
80
+ },
81
+ "react-dom": {
82
+ "optional": true
83
+ }
84
+ },
85
+ "publishConfig": {
86
+ "access": "public"
87
+ },
88
+ "sideEffects": false,
89
+ "devDependencies": {
90
+ "@rolldown/plugin-babel": "^0.2.2",
91
+ "@types/node": "^25.5.0",
92
+ "@types/react": "^19.2.2",
93
+ "@types/react-dom": "^19.2.3",
94
+ "@vitejs/plugin-react": "^6.0.1",
95
+ "@vitest/coverage-v8": "^4.0.7",
96
+ "babel-plugin-react-compiler": "^1.0.0",
97
+ "happy-dom": "^20.0.10",
98
+ "oxfmt": "^0.42.0",
99
+ "oxlint": "^1.57.0",
100
+ "react": "^19.2.0",
101
+ "react-dom": "^19.2.0",
102
+ "typescript": "^6.0.2",
103
+ "vite": "^8.0.3",
104
+ "vite-plugin-dts": "^4.5.4",
105
+ "vitest": "^4.0.7"
106
+ }
107
+ }