@real-router/preact 0.0.1

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.
package/README.md ADDED
@@ -0,0 +1,194 @@
1
+ # @real-router/preact
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](../../LICENSE)
4
+
5
+ > Preact integration for [Real-Router](https://github.com/greydragon888/real-router) — hooks, components, and context providers.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @real-router/preact @real-router/core @real-router/browser-plugin
11
+ ```
12
+
13
+ **Peer dependency:** `preact` >= 10.0.0
14
+
15
+ ## Quick Start
16
+
17
+ ```tsx
18
+ import { createRouter } from "@real-router/core";
19
+ import { browserPluginFactory } from "@real-router/browser-plugin";
20
+ import { RouterProvider, RouteView, Link } from "@real-router/preact";
21
+
22
+ const router = createRouter([
23
+ { name: "home", path: "/" },
24
+ {
25
+ name: "users",
26
+ path: "/users",
27
+ children: [{ name: "profile", path: "/:id" }],
28
+ },
29
+ ]);
30
+
31
+ router.usePlugin(browserPluginFactory());
32
+ router.start();
33
+
34
+ function App() {
35
+ return (
36
+ <RouterProvider router={router}>
37
+ <nav>
38
+ <Link routeName="home">Home</Link>
39
+ <Link routeName="users">Users</Link>
40
+ </nav>
41
+ <RouteView nodeName="">
42
+ <RouteView.Match segment="home">
43
+ <HomePage />
44
+ </RouteView.Match>
45
+ <RouteView.Match segment="users">
46
+ <UsersPage />
47
+ </RouteView.Match>
48
+ <RouteView.NotFound>
49
+ <NotFoundPage />
50
+ </RouteView.NotFound>
51
+ </RouteView>
52
+ </RouterProvider>
53
+ );
54
+ }
55
+ ```
56
+
57
+ ## Hooks
58
+
59
+ | Hook | Returns | Re-renders |
60
+ | ----------------------- | ----------------------------------------- | --------------------------------------- |
61
+ | `useRouter()` | `Router` | Never |
62
+ | `useNavigator()` | `Navigator` | Never (stable ref, safe to destructure) |
63
+ | `useRoute()` | `{ navigator, route, previousRoute }` | Every navigation |
64
+ | `useRouteNode(name)` | `{ navigator, route, previousRoute }` | Only when node activates/deactivates |
65
+ | `useRouteUtils()` | `RouteUtils` | Never |
66
+ | `useRouterTransition()` | `{ isTransitioning, toRoute, fromRoute }` | On transition start/end |
67
+
68
+ ```tsx
69
+ // useRouteNode — re-renders only when "users.*" changes
70
+ function UsersLayout() {
71
+ const { route } = useRouteNode("users");
72
+ if (!route) return null;
73
+
74
+ switch (route.name) {
75
+ case "users":
76
+ return <UsersList />;
77
+ case "users.profile":
78
+ return <UserProfile id={route.params.id} />;
79
+ default:
80
+ return null;
81
+ }
82
+ }
83
+
84
+ // useNavigator — stable reference, never causes re-renders
85
+ function BackButton() {
86
+ const navigator = useNavigator();
87
+ return <button onClick={() => navigator.navigate("home")}>Back</button>;
88
+ }
89
+
90
+ // useRouterTransition — progress bars, loading states
91
+ function GlobalProgress() {
92
+ const { isTransitioning } = useRouterTransition();
93
+ if (!isTransitioning) return null;
94
+ return <div className="progress-bar" />;
95
+ }
96
+ ```
97
+
98
+ ## Components
99
+
100
+ ### `<Link>`
101
+
102
+ Navigation link with automatic active state detection. Re-renders only when its active status changes.
103
+
104
+ ```tsx
105
+ <Link
106
+ routeName="users.profile"
107
+ routeParams={{ id: "123" }}
108
+ activeClassName="active" // default: "active"
109
+ activeStrict={false} // default: false (ancestor match)
110
+ ignoreQueryParams={true} // default: true
111
+ routeOptions={{ replace: true }}
112
+ >
113
+ View Profile
114
+ </Link>
115
+ ```
116
+
117
+ ### `<RouteView>`
118
+
119
+ Declarative route matching. Renders the first matching `<RouteView.Match>` child.
120
+
121
+ ```tsx
122
+ <RouteView nodeName="">
123
+ <RouteView.Match segment="users">
124
+ <UsersPage />
125
+ </RouteView.Match>
126
+ <RouteView.Match segment="settings">
127
+ <SettingsPage />
128
+ </RouteView.Match>
129
+ <RouteView.NotFound>
130
+ <NotFoundPage />
131
+ </RouteView.NotFound>
132
+ </RouteView>
133
+ ```
134
+
135
+ > **Note:** Unlike the React adapter, `keepAlive` is not supported. Preact has no equivalent of React's `<Activity>` API. Components unmount completely when navigating away.
136
+
137
+ #### `RouteView.Match` props
138
+
139
+ | Prop | Type | Description |
140
+ | ---------- | ------------------- | --------------------------------------------------------------------------- |
141
+ | `segment` | `string` | Route segment to match |
142
+ | `fallback` | `ComponentChildren` | Shown while children suspend. Wraps children in `<Suspense>` when provided. |
143
+
144
+ #### Lazy loading with `fallback` (experimental)
145
+
146
+ Preact's `lazy` and `Suspense` come from `preact/compat`. Support is experimental — test before shipping to production.
147
+
148
+ ```tsx
149
+ import { lazy } from "preact/compat";
150
+
151
+ const LazyDashboard = lazy(() => import("./Dashboard"));
152
+
153
+ <RouteView nodeName="">
154
+ <RouteView.Match segment="dashboard" fallback={<Spinner />}>
155
+ <LazyDashboard />
156
+ </RouteView.Match>
157
+ </RouteView>;
158
+ ```
159
+
160
+ ## Accessibility
161
+
162
+ Enable screen reader announcements for route changes:
163
+
164
+ ```tsx
165
+ <RouterProvider router={router} announceNavigation>
166
+ {/* Your app */}
167
+ </RouterProvider>
168
+ ```
169
+
170
+ When enabled, a visually hidden `aria-live` region announces each navigation. Focus moves to the first `<h1>` on the new page. See [Accessibility guide](https://github.com/greydragon888/real-router/wiki/Accessibility) for details.
171
+
172
+ ## Documentation
173
+
174
+ Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
175
+
176
+ - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [Link](https://github.com/greydragon888/real-router/wiki/Link)
177
+ - [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator) · [useRouteUtils](https://github.com/greydragon888/real-router/wiki/useRouteUtils) · [useRouterTransition](https://github.com/greydragon888/real-router/wiki/useRouterTransition)
178
+
179
+ ## Related Packages
180
+
181
+ | Package | Description |
182
+ | ---------------------------------------------------------------------------------------- | ------------------------------------ |
183
+ | [@real-router/core](https://www.npmjs.com/package/@real-router/core) | Core router (required dependency) |
184
+ | [@real-router/browser-plugin](https://www.npmjs.com/package/@real-router/browser-plugin) | Browser History API integration |
185
+ | [@real-router/sources](https://www.npmjs.com/package/@real-router/sources) | Subscription layer (used internally) |
186
+ | [@real-router/route-utils](https://www.npmjs.com/package/@real-router/route-utils) | Route tree queries (`useRouteUtils`) |
187
+
188
+ ## Contributing
189
+
190
+ See [contributing guidelines](../../CONTRIBUTING.md) for development setup and PR process.
191
+
192
+ ## License
193
+
194
+ [MIT](../../LICENSE) © [Oleg Ivanov](https://github.com/greydragon888)
@@ -0,0 +1,84 @@
1
+ import * as preact from 'preact';
2
+ import { ComponentChildren, VNode, JSX, FunctionComponent } from 'preact';
3
+ import { Params, NavigationOptions, Navigator, State, Router } from '@real-router/core';
4
+ export { Navigator } from '@real-router/core';
5
+ import { RouteUtils } from '@real-router/route-utils';
6
+ import { RouterTransitionSnapshot } from '@real-router/sources';
7
+ export { RouterTransitionSnapshot } from '@real-router/sources';
8
+
9
+ interface RouteViewProps {
10
+ readonly nodeName: string;
11
+ readonly children: ComponentChildren;
12
+ }
13
+ interface MatchProps {
14
+ readonly segment: string;
15
+ readonly exact?: boolean;
16
+ readonly fallback?: ComponentChildren;
17
+ readonly children: ComponentChildren;
18
+ }
19
+ interface NotFoundProps {
20
+ readonly children: ComponentChildren;
21
+ }
22
+
23
+ declare function Match(_props: MatchProps): null;
24
+ declare namespace Match {
25
+ var displayName: string;
26
+ }
27
+ declare function NotFound(_props: NotFoundProps): null;
28
+ declare namespace NotFound {
29
+ var displayName: string;
30
+ }
31
+
32
+ declare function RouteViewRoot({ nodeName, children, }: Readonly<RouteViewProps>): VNode | null;
33
+ declare namespace RouteViewRoot {
34
+ var displayName: string;
35
+ }
36
+ declare const RouteView: typeof RouteViewRoot & {
37
+ Match: typeof Match;
38
+ NotFound: typeof NotFound;
39
+ };
40
+
41
+ interface RouteState<P extends Params = Params, MP extends Params = Params> {
42
+ route: State<P, MP> | undefined;
43
+ previousRoute?: State | undefined;
44
+ }
45
+ type RouteContext$1 = {
46
+ navigator: Navigator;
47
+ } & RouteState;
48
+ interface LinkProps<P extends Params = Params> extends Omit<JSX.HTMLAttributes<HTMLAnchorElement>, "className"> {
49
+ routeName: string;
50
+ routeParams?: P;
51
+ routeOptions?: NavigationOptions;
52
+ className?: string;
53
+ activeClassName?: string;
54
+ activeStrict?: boolean;
55
+ ignoreQueryParams?: boolean;
56
+ target?: string;
57
+ }
58
+
59
+ declare const Link: FunctionComponent<LinkProps>;
60
+
61
+ declare const useRouter: () => Router;
62
+
63
+ declare const useNavigator: () => Navigator;
64
+
65
+ declare const useRouteUtils: () => RouteUtils;
66
+
67
+ declare const useRoute: () => RouteContext$1;
68
+
69
+ declare function useRouteNode(nodeName: string): RouteContext$1;
70
+
71
+ declare function useRouterTransition(): RouterTransitionSnapshot;
72
+
73
+ interface RouteProviderProps {
74
+ router: Router;
75
+ children: ComponentChildren;
76
+ announceNavigation?: boolean;
77
+ }
78
+ declare const RouterProvider: FunctionComponent<RouteProviderProps>;
79
+
80
+ declare const RouteContext: preact.Context<RouteContext$1 | null>;
81
+ declare const RouterContext: preact.Context<Router<object> | null>;
82
+ declare const NavigatorContext: preact.Context<Navigator | null>;
83
+
84
+ export { Link, type LinkProps, NavigatorContext, RouteContext, RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps, RouterContext, RouterProvider, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition };
@@ -0,0 +1 @@
1
+ var e=require("@real-router/core"),t=require("@real-router/route-utils"),r=require("preact"),o=require("preact/compat"),u=require("preact/jsx-runtime"),n=require("@real-router/sources"),s=require("preact/hooks"),i=require("dom-utils"),a=require("@real-router/core/api");function c(e){return null}function l(e){return null}function d(e,r,o){return o?e===r:t.startsWithSegment(e,r)}function p(e,t){for(const o of r.toChildArray(e))r.isValidElement(o)&&(o.type===c||o.type===l?t.push(o):p(o.props.children,t))}function m(e,t,r){const[o,u]=s.useState(t);return s.useEffect(()=>(u(t()),e(()=>{u(t())})),[e,t]),o}c.displayName="RouteView.Match",l.displayName="RouteView.NotFound";var v=r.createContext(null),f=r.createContext(null),g=r.createContext(null),h=()=>{const e=s.useContext(f);if(!e)throw new Error("useRouter must be used within a RouterProvider");return e};function N(t){const r=h(),o=s.useMemo(()=>n.createRouteNodeSource(r,t),[r,t]),{route:u,previousRoute:i}=m(o.subscribe,o.getSnapshot),a=s.useMemo(()=>e.getNavigator(r),[r]);return s.useMemo(()=>({navigator:a,route:u,previousRoute:i}),[a,u,i])}function x({nodeName:t,children:n}){const{route:s}=N(t);if(!s)return null;const i=[];p(n,i);const{rendered:a}=function(t,n,s){let i=null,a=!1;const c=[];for(const e of t){if(e.type===l){i=e.props.children;continue}const{segment:t,exact:p=!1,fallback:m}=e.props,v=s?`${s}.${t}`:t;if(!a&&d(n,v,p)){a=!0;const t=e.props.children;c.push(u.jsx(r.Fragment,{children:void 0===m?t:u.jsx(o.Suspense,{fallback:m,children:t})},v))}}return a||n!==e.UNKNOWN_ROUTE||null===i||c.push(u.jsx(r.Fragment,{children:i},"__route-view-not-found__")),{rendered:c,activeMatchFound:a}}(i,s.name,t);return a.length>0?u.jsx(u.Fragment,{children:a}):null}x.displayName="RouteView";var R=Object.assign(x,{Match:c,NotFound:l}),b=Object.freeze({}),y=Object.freeze({});function C(e){const t=JSON.stringify(e);return s.useMemo(()=>e,[t])}var S=o.memo(({routeName:e,routeParams:t=b,routeOptions:r=y,className:o,activeClassName:a="active",activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:d,target:p,children:v,...f})=>{const g=h(),N=C(t),x=C(r),R=function(e,t,r=!1,o=!0){const u=h(),i=C(t),a=s.useMemo(()=>n.createActiveRouteSource(u,e,i,{strict:r,ignoreQueryParams:o}),[u,e,i,r,o]);return m(a.subscribe,a.getSnapshot)}(e,N,c,l),S=s.useMemo(()=>i.buildHref(g,e,N),[g,e,N]),P=s.useCallback(t=>{d&&(d(t),t.defaultPrevented)||i.shouldNavigate(t)&&"_blank"!==p&&(t.preventDefault(),g.navigate(e,N,x).catch(()=>{}))},[d,p,g,e,N,x]),w=s.useMemo(()=>i.buildActiveClassName(R,a,o),[R,a,o]);return u.jsx("a",{...f,href:S,className:w,onClick:P,children:v})},function(e,t){return e.routeName===t.routeName&&e.className===t.className&&e.activeClassName===t.activeClassName&&e.activeStrict===t.activeStrict&&e.ignoreQueryParams===t.ignoreQueryParams&&e.onClick===t.onClick&&e.target===t.target&&e.style===t.style&&e.children===t.children&&JSON.stringify(e.routeParams)===JSON.stringify(t.routeParams)&&JSON.stringify(e.routeOptions)===JSON.stringify(t.routeOptions)});S.displayName="Link",exports.Link=S,exports.NavigatorContext=g,exports.RouteContext=v,exports.RouteView=R,exports.RouterContext=f,exports.RouterProvider=({router:t,children:r,announceNavigation:o})=>{s.useEffect(()=>{if(!o)return;const e=i.createRouteAnnouncer(t);return()=>{e.destroy()}},[o,t]);const a=s.useMemo(()=>e.getNavigator(t),[t]),c=s.useMemo(()=>n.createRouteSource(t),[t]),{route:l,previousRoute:d}=m(c.subscribe,c.getSnapshot),p=s.useMemo(()=>({navigator:a,route:l,previousRoute:d}),[a,l,d]);return u.jsx(f.Provider,{value:t,children:u.jsx(g.Provider,{value:a,children:u.jsx(v.Provider,{value:p,children:r})})})},exports.useNavigator=()=>{const e=s.useContext(g);if(!e)throw new Error("useNavigator must be used within a RouterProvider");return e},exports.useRoute=()=>{const e=s.useContext(v);if(!e)throw new Error("useRoute must be used within a RouteProvider");return e},exports.useRouteNode=N,exports.useRouteUtils=()=>{const e=h();return t.getRouteUtils(a.getPluginApi(e).getTree())},exports.useRouter=h,exports.useRouterTransition=function(){const e=h(),t=s.useMemo(()=>n.createTransitionSource(e),[e]);return m(t.subscribe,t.getSnapshot)};//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/RouteView/components.tsx","../../src/components/RouteView/helpers.tsx","../../src/useSyncExternalStore.ts","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/components/RouteView/RouteView.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["startsWithSegment","toChildArray","isValidElement","jsx","Suspense","Fragment","UNKNOWN_ROUTE","useState","useEffect","createContext","useContext","useMemo","createRouteNodeSource","getNavigator","createActiveRouteSource","memo","buildHref","useCallback","shouldNavigate","buildActiveClassName","getRouteUtils","getPluginApi","createTransitionSource","createRouteAnnouncer","createRouteSource"],"mappings":"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","file":"index.js","sourcesContent":["import type { MatchProps, NotFoundProps } from \"./types\";\n\nexport function Match(_props: MatchProps): null {\n return null;\n}\n\nMatch.displayName = \"RouteView.Match\";\n\nexport function NotFound(_props: NotFoundProps): null {\n return null;\n}\n\nNotFound.displayName = \"RouteView.NotFound\";\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Fragment, isValidElement, toChildArray } from \"preact\";\nimport { Suspense } from \"preact/compat\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { MatchProps, NotFoundProps } from \"./types\";\nimport type { VNode, ComponentChildren } from \"preact\";\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nexport function collectElements(\n children: ComponentChildren,\n result: VNode[],\n): void {\n for (const child of toChildArray(children)) {\n if (!isValidElement(child)) {\n continue;\n }\n\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else {\n collectElements(\n (child.props as { readonly children: ComponentChildren }).children,\n result,\n );\n }\n }\n}\n\nexport function buildRenderList(\n elements: VNode[],\n routeName: string,\n nodeName: string,\n): { rendered: VNode[]; activeMatchFound: boolean } {\n let notFoundChildren: ComponentChildren = null;\n let activeMatchFound = false;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = (child.props as NotFoundProps).children;\n continue;\n }\n\n const { segment, exact = false, fallback } = child.props as MatchProps;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n const matchChildren = (child.props as MatchProps).children;\n const content =\n fallback === undefined ? (\n matchChildren\n ) : (\n <Suspense fallback={fallback}>{matchChildren}</Suspense>\n );\n\n rendered.push(<Fragment key={fullSegmentName}>{content}</Fragment>);\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n rendered.push(\n <Fragment key=\"__route-view-not-found__\">{notFoundChildren}</Fragment>,\n );\n }\n\n return { rendered, activeMatchFound };\n}\n","import { useEffect, useState } from \"preact/hooks\";\n\n/**\n * Polyfill for React's useSyncExternalStore.\n *\n * Preact does not provide a native useSyncExternalStore.\n * This implementation uses useState + useEffect to subscribe\n * to external stores.\n *\n * Race condition handling: the value may change between\n * `useState(getSnapshot)` (render) and `useEffect` (commit).\n * We synchronize by calling `setValue(getSnapshot())` before\n * subscribing in the effect.\n */\nexport function useSyncExternalStore<T>(\n subscribe: (onStoreChange: () => void) => () => void,\n getSnapshot: () => T,\n _getServerSnapshot?: () => T,\n): T {\n const [value, setValue] = useState(getSnapshot);\n\n useEffect(() => {\n // Synchronize before subscribing to handle race condition\n setValue(getSnapshot());\n\n return subscribe(() => {\n setValue(getSnapshot());\n });\n }, [subscribe, getSnapshot]);\n\n return value;\n}\n","import { createContext } from \"preact\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","import { useContext } from \"preact/hooks\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo } from \"preact/hooks\";\n\nimport { useSyncExternalStore } from \"../useSyncExternalStore\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","import { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../hooks/useRouteNode\";\n\nimport type { RouteViewProps } from \"./types\";\nimport type { VNode } from \"preact\";\n\nfunction RouteViewRoot({\n nodeName,\n children,\n}: Readonly<RouteViewProps>): VNode | null {\n const { route } = useRouteNode(nodeName);\n\n if (!route) {\n return null;\n }\n\n const elements: VNode[] = [];\n\n collectElements(children, elements);\n\n const { rendered } = buildRenderList(elements, route.name, nodeName);\n\n if (rendered.length > 0) {\n return <>{rendered}</>;\n }\n\n return null;\n}\n\nRouteViewRoot.displayName = \"RouteView\";\n\nexport const RouteView = Object.assign(RouteViewRoot, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\n","/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","import { useMemo } from \"preact/hooks\";\n\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo } from \"preact/hooks\";\n\nimport { useSyncExternalStore } from \"../useSyncExternalStore\";\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { memo } from \"preact/compat\";\nimport { useCallback, useMemo } from \"preact/hooks\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FunctionComponent, JSX } from \"preact\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FunctionComponent<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(\n () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\n\n const handleClick = useCallback(\n (evt: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(\n () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { useContext } from \"preact/hooks\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","import { getPluginApi } from \"@real-router/core/api\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { useContext } from \"preact/hooks\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo } from \"preact/hooks\";\n\nimport { useSyncExternalStore } from \"../useSyncExternalStore\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, useMemo } from \"preact/hooks\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\nimport { useSyncExternalStore } from \"./useSyncExternalStore\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FunctionComponent, ComponentChildren } from \"preact\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ComponentChildren;\n announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FunctionComponent<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext.Provider value={router}>\n <NavigatorContext.Provider value={navigator}>\n <RouteContext.Provider value={routeContextValue}>\n {children}\n </RouteContext.Provider>\n </NavigatorContext.Provider>\n </RouterContext.Provider>\n );\n};\n"]}
@@ -0,0 +1 @@
1
+ {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/components/RouteView/components.tsx":{"bytes":286,"imports":[{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/RouteView/helpers.tsx":{"bytes":2348,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"preact","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"src/components/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/useSyncExternalStore.ts":{"bytes":911,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/context.ts":{"bytes":379,"imports":[{"path":"preact","kind":"import-statement","external":true},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":338,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":831,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"../useSyncExternalStore"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/RouteView/RouteView.tsx":{"bytes":905,"imports":[{"path":"src/components/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"src/components/RouteView/helpers.tsx","kind":"import-statement","original":"./helpers"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"../../hooks/useRouteNode"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/RouteView/index.ts":{"bytes":145,"imports":[{"path":"src/components/RouteView/RouteView.tsx","kind":"import-statement","original":"./RouteView"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/constants.ts":{"bytes":185,"imports":[{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":240,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":854,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"../useSyncExternalStore"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":2766,"imports":[{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":365,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":355,"imports":[{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":378,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouterTransition.tsx":{"bytes":557,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"../useSyncExternalStore"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1815,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"./useSyncExternalStore"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":874,"imports":[{"path":"src/components/RouteView/index.ts","kind":"import-statement","original":"./components/RouteView"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/Users/olegivanov/WebstormProjects/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":21097},"dist/cjs/index.js":{"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"preact","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouteView","RouterContext","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/components/RouteView/components.tsx":{"bytesInOutput":171},"src/components/RouteView/helpers.tsx":{"bytesInOutput":1879},"src/hooks/useRouteNode.tsx":{"bytesInOutput":627},"src/useSyncExternalStore.ts":{"bytesInOutput":346},"src/hooks/useRouter.tsx":{"bytesInOutput":223},"src/context.ts":{"bytesInOutput":165},"src/components/RouteView/RouteView.tsx":{"bytesInOutput":567},"src/components/RouteView/index.ts":{"bytesInOutput":0},"src/index.ts":{"bytesInOutput":0},"src/components/Link.tsx":{"bytesInOutput":2315},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":597},"src/hooks/useStableValue.tsx":{"bytesInOutput":177},"src/hooks/useNavigator.tsx":{"bytesInOutput":257},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRoute.tsx":{"bytesInOutput":253},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":356},"src/RouterProvider.tsx":{"bytesInOutput":1298}},"bytes":10368}}}
@@ -0,0 +1,84 @@
1
+ import * as preact from 'preact';
2
+ import { ComponentChildren, VNode, JSX, FunctionComponent } from 'preact';
3
+ import { Params, NavigationOptions, Navigator, State, Router } from '@real-router/core';
4
+ export { Navigator } from '@real-router/core';
5
+ import { RouteUtils } from '@real-router/route-utils';
6
+ import { RouterTransitionSnapshot } from '@real-router/sources';
7
+ export { RouterTransitionSnapshot } from '@real-router/sources';
8
+
9
+ interface RouteViewProps {
10
+ readonly nodeName: string;
11
+ readonly children: ComponentChildren;
12
+ }
13
+ interface MatchProps {
14
+ readonly segment: string;
15
+ readonly exact?: boolean;
16
+ readonly fallback?: ComponentChildren;
17
+ readonly children: ComponentChildren;
18
+ }
19
+ interface NotFoundProps {
20
+ readonly children: ComponentChildren;
21
+ }
22
+
23
+ declare function Match(_props: MatchProps): null;
24
+ declare namespace Match {
25
+ var displayName: string;
26
+ }
27
+ declare function NotFound(_props: NotFoundProps): null;
28
+ declare namespace NotFound {
29
+ var displayName: string;
30
+ }
31
+
32
+ declare function RouteViewRoot({ nodeName, children, }: Readonly<RouteViewProps>): VNode | null;
33
+ declare namespace RouteViewRoot {
34
+ var displayName: string;
35
+ }
36
+ declare const RouteView: typeof RouteViewRoot & {
37
+ Match: typeof Match;
38
+ NotFound: typeof NotFound;
39
+ };
40
+
41
+ interface RouteState<P extends Params = Params, MP extends Params = Params> {
42
+ route: State<P, MP> | undefined;
43
+ previousRoute?: State | undefined;
44
+ }
45
+ type RouteContext$1 = {
46
+ navigator: Navigator;
47
+ } & RouteState;
48
+ interface LinkProps<P extends Params = Params> extends Omit<JSX.HTMLAttributes<HTMLAnchorElement>, "className"> {
49
+ routeName: string;
50
+ routeParams?: P;
51
+ routeOptions?: NavigationOptions;
52
+ className?: string;
53
+ activeClassName?: string;
54
+ activeStrict?: boolean;
55
+ ignoreQueryParams?: boolean;
56
+ target?: string;
57
+ }
58
+
59
+ declare const Link: FunctionComponent<LinkProps>;
60
+
61
+ declare const useRouter: () => Router;
62
+
63
+ declare const useNavigator: () => Navigator;
64
+
65
+ declare const useRouteUtils: () => RouteUtils;
66
+
67
+ declare const useRoute: () => RouteContext$1;
68
+
69
+ declare function useRouteNode(nodeName: string): RouteContext$1;
70
+
71
+ declare function useRouterTransition(): RouterTransitionSnapshot;
72
+
73
+ interface RouteProviderProps {
74
+ router: Router;
75
+ children: ComponentChildren;
76
+ announceNavigation?: boolean;
77
+ }
78
+ declare const RouterProvider: FunctionComponent<RouteProviderProps>;
79
+
80
+ declare const RouteContext: preact.Context<RouteContext$1 | null>;
81
+ declare const RouterContext: preact.Context<Router<object> | null>;
82
+ declare const NavigatorContext: preact.Context<Navigator | null>;
83
+
84
+ export { Link, type LinkProps, NavigatorContext, RouteContext, RouteView, type MatchProps as RouteViewMatchProps, type NotFoundProps as RouteViewNotFoundProps, type RouteViewProps, RouterContext, RouterProvider, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter, useRouterTransition };
@@ -0,0 +1 @@
1
+ import{getNavigator as r,UNKNOWN_ROUTE as e}from"@real-router/core";import{startsWithSegment as t,getRouteUtils as o}from"@real-router/route-utils";import{createContext as n,toChildArray as i,isValidElement as u,Fragment as a}from"preact";import{memo as s,Suspense as c}from"preact/compat";import{jsx as l,Fragment as m}from"preact/jsx-runtime";import{createActiveRouteSource as p,createRouteNodeSource as f,createTransitionSource as d,createRouteSource as h}from"@real-router/sources";import{useMemo as v,useCallback as g,useContext as N,useState as y,useEffect as b}from"preact/hooks";import{buildHref as P,shouldNavigate as w,buildActiveClassName as R,createRouteAnnouncer as S}from"dom-utils";import{getPluginApi as O}from"@real-router/core/api";function k(r){return null}function C(r){return null}function J(r,e,o){return o?r===e:t(r,e)}function _(r,e){for(const t of i(r))u(t)&&(t.type===k||t.type===C?e.push(t):_(t.props.children,e))}function j(r,e,t){const[o,n]=y(e);return b(()=>(n(e()),r(()=>{n(e())})),[r,e]),o}k.displayName="RouteView.Match",C.displayName="RouteView.NotFound";var F=n(null),Q=n(null),x=n(null),E=()=>{const r=N(Q);if(!r)throw new Error("useRouter must be used within a RouterProvider");return r};function M(e){const t=E(),o=v(()=>f(t,e),[t,e]),{route:n,previousRoute:i}=j(o.subscribe,o.getSnapshot),u=v(()=>r(t),[t]);return v(()=>({navigator:u,route:n,previousRoute:i}),[u,n,i])}function V({nodeName:r,children:t}){const{route:o}=M(r);if(!o)return null;const n=[];_(t,n);const{rendered:i}=function(r,t,o){let n=null,i=!1;const u=[];for(const e of r){if(e.type===C){n=e.props.children;continue}const{segment:r,exact:s=!1,fallback:m}=e.props,p=o?`${o}.${r}`:r;if(!i&&J(t,p,s)){i=!0;const r=e.props.children;u.push(l(a,{children:void 0===m?r:l(c,{fallback:m,children:r})},p))}}return i||t!==e||null===n||u.push(l(a,{children:n},"__route-view-not-found__")),{rendered:u,activeMatchFound:i}}(n,o.name,r);return i.length>0?l(m,{children:i}):null}V.displayName="RouteView";var z=Object.assign(V,{Match:k,NotFound:C}),$=Object.freeze({}),D=Object.freeze({});function L(r){const e=JSON.stringify(r);return v(()=>r,[e])}var T=s(({routeName:r,routeParams:e=$,routeOptions:t=D,className:o,activeClassName:n="active",activeStrict:i=!1,ignoreQueryParams:u=!0,onClick:a,target:s,children:c,...m})=>{const f=E(),d=L(e),h=L(t),N=function(r,e,t=!1,o=!0){const n=E(),i=L(e),u=v(()=>p(n,r,i,{strict:t,ignoreQueryParams:o}),[n,r,i,t,o]);return j(u.subscribe,u.getSnapshot)}(r,d,i,u),y=v(()=>P(f,r,d),[f,r,d]),b=g(e=>{a&&(a(e),e.defaultPrevented)||w(e)&&"_blank"!==s&&(e.preventDefault(),f.navigate(r,d,h).catch(()=>{}))},[a,s,f,r,d,h]),S=v(()=>R(N,n,o),[N,n,o]);return l("a",{...m,href:y,className:S,onClick:b,children:c})},function(r,e){return r.routeName===e.routeName&&r.className===e.className&&r.activeClassName===e.activeClassName&&r.activeStrict===e.activeStrict&&r.ignoreQueryParams===e.ignoreQueryParams&&r.onClick===e.onClick&&r.target===e.target&&r.style===e.style&&r.children===e.children&&JSON.stringify(r.routeParams)===JSON.stringify(e.routeParams)&&JSON.stringify(r.routeOptions)===JSON.stringify(e.routeOptions)});T.displayName="Link";var q=()=>{const r=N(x);if(!r)throw new Error("useNavigator must be used within a RouterProvider");return r},A=()=>{const r=E();return o(O(r).getTree())},B=()=>{const r=N(F);if(!r)throw new Error("useRoute must be used within a RouteProvider");return r};function G(){const r=E(),e=v(()=>d(r),[r]);return j(e.subscribe,e.getSnapshot)}var H=({router:e,children:t,announceNavigation:o})=>{b(()=>{if(!o)return;const r=S(e);return()=>{r.destroy()}},[o,e]);const n=v(()=>r(e),[e]),i=v(()=>h(e),[e]),{route:u,previousRoute:a}=j(i.subscribe,i.getSnapshot),s=v(()=>({navigator:n,route:u,previousRoute:a}),[n,u,a]);return l(Q.Provider,{value:e,children:l(x.Provider,{value:n,children:l(F.Provider,{value:s,children:t})})})};export{T as Link,x as NavigatorContext,F as RouteContext,z as RouteView,Q as RouterContext,H as RouterProvider,q as useNavigator,B as useRoute,M as useRouteNode,A as useRouteUtils,E as useRouter,G as useRouterTransition};//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/RouteView/components.tsx","../../src/components/RouteView/helpers.tsx","../../src/useSyncExternalStore.ts","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/components/RouteView/RouteView.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["Fragment","jsx","useMemo","useContext","useEffect","getNavigator"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { MatchProps, NotFoundProps } from \"./types\";\n\nexport function Match(_props: MatchProps): null {\n return null;\n}\n\nMatch.displayName = \"RouteView.Match\";\n\nexport function NotFound(_props: NotFoundProps): null {\n return null;\n}\n\nNotFound.displayName = \"RouteView.NotFound\";\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Fragment, isValidElement, toChildArray } from \"preact\";\nimport { Suspense } from \"preact/compat\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { MatchProps, NotFoundProps } from \"./types\";\nimport type { VNode, ComponentChildren } from \"preact\";\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nexport function collectElements(\n children: ComponentChildren,\n result: VNode[],\n): void {\n for (const child of toChildArray(children)) {\n if (!isValidElement(child)) {\n continue;\n }\n\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else {\n collectElements(\n (child.props as { readonly children: ComponentChildren }).children,\n result,\n );\n }\n }\n}\n\nexport function buildRenderList(\n elements: VNode[],\n routeName: string,\n nodeName: string,\n): { rendered: VNode[]; activeMatchFound: boolean } {\n let notFoundChildren: ComponentChildren = null;\n let activeMatchFound = false;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = (child.props as NotFoundProps).children;\n continue;\n }\n\n const { segment, exact = false, fallback } = child.props as MatchProps;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n const matchChildren = (child.props as MatchProps).children;\n const content =\n fallback === undefined ? (\n matchChildren\n ) : (\n <Suspense fallback={fallback}>{matchChildren}</Suspense>\n );\n\n rendered.push(<Fragment key={fullSegmentName}>{content}</Fragment>);\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n rendered.push(\n <Fragment key=\"__route-view-not-found__\">{notFoundChildren}</Fragment>,\n );\n }\n\n return { rendered, activeMatchFound };\n}\n","import { useEffect, useState } from \"preact/hooks\";\n\n/**\n * Polyfill for React's useSyncExternalStore.\n *\n * Preact does not provide a native useSyncExternalStore.\n * This implementation uses useState + useEffect to subscribe\n * to external stores.\n *\n * Race condition handling: the value may change between\n * `useState(getSnapshot)` (render) and `useEffect` (commit).\n * We synchronize by calling `setValue(getSnapshot())` before\n * subscribing in the effect.\n */\nexport function useSyncExternalStore<T>(\n subscribe: (onStoreChange: () => void) => () => void,\n getSnapshot: () => T,\n _getServerSnapshot?: () => T,\n): T {\n const [value, setValue] = useState(getSnapshot);\n\n useEffect(() => {\n // Synchronize before subscribing to handle race condition\n setValue(getSnapshot());\n\n return subscribe(() => {\n setValue(getSnapshot());\n });\n }, [subscribe, getSnapshot]);\n\n return value;\n}\n","import { createContext } from \"preact\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","import { useContext } from \"preact/hooks\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo } from \"preact/hooks\";\n\nimport { useSyncExternalStore } from \"../useSyncExternalStore\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","import { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../hooks/useRouteNode\";\n\nimport type { RouteViewProps } from \"./types\";\nimport type { VNode } from \"preact\";\n\nfunction RouteViewRoot({\n nodeName,\n children,\n}: Readonly<RouteViewProps>): VNode | null {\n const { route } = useRouteNode(nodeName);\n\n if (!route) {\n return null;\n }\n\n const elements: VNode[] = [];\n\n collectElements(children, elements);\n\n const { rendered } = buildRenderList(elements, route.name, nodeName);\n\n if (rendered.length > 0) {\n return <>{rendered}</>;\n }\n\n return null;\n}\n\nRouteViewRoot.displayName = \"RouteView\";\n\nexport const RouteView = Object.assign(RouteViewRoot, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\n","/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","import { useMemo } from \"preact/hooks\";\n\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo } from \"preact/hooks\";\n\nimport { useSyncExternalStore } from \"../useSyncExternalStore\";\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { memo } from \"preact/compat\";\nimport { useCallback, useMemo } from \"preact/hooks\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FunctionComponent, JSX } from \"preact\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FunctionComponent<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(\n () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\n\n const handleClick = useCallback(\n (evt: JSX.TargetedMouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(\n () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { useContext } from \"preact/hooks\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","import { getPluginApi } from \"@real-router/core/api\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { useContext } from \"preact/hooks\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo } from \"preact/hooks\";\n\nimport { useSyncExternalStore } from \"../useSyncExternalStore\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, useMemo } from \"preact/hooks\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\nimport { useSyncExternalStore } from \"./useSyncExternalStore\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FunctionComponent, ComponentChildren } from \"preact\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ComponentChildren;\n announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FunctionComponent<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext.Provider value={router}>\n <NavigatorContext.Provider value={navigator}>\n <RouteContext.Provider value={routeContextValue}>\n {children}\n </RouteContext.Provider>\n </NavigatorContext.Provider>\n </RouterContext.Provider>\n );\n};\n"]}
@@ -0,0 +1 @@
1
+ {"inputs":{"src/components/RouteView/components.tsx":{"bytes":286,"imports":[],"format":"esm"},"src/components/RouteView/helpers.tsx":{"bytes":2348,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"preact","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"src/components/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/useSyncExternalStore.ts":{"bytes":911,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true}],"format":"esm"},"src/context.ts":{"bytes":379,"imports":[{"path":"preact","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":338,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":831,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"../useSyncExternalStore"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/components/RouteView/RouteView.tsx":{"bytes":905,"imports":[{"path":"src/components/RouteView/components.tsx","kind":"import-statement","original":"./components"},{"path":"src/components/RouteView/helpers.tsx","kind":"import-statement","original":"./helpers"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"../../hooks/useRouteNode"},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/RouteView/index.ts":{"bytes":145,"imports":[{"path":"src/components/RouteView/RouteView.tsx","kind":"import-statement","original":"./RouteView"}],"format":"esm"},"src/constants.ts":{"bytes":185,"imports":[],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":240,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":854,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"../useSyncExternalStore"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"}],"format":"esm"},"src/components/Link.tsx":{"bytes":2766,"imports":[{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":365,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":355,"imports":[{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":378,"imports":[{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouterTransition.tsx":{"bytes":557,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"../useSyncExternalStore"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1815,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"src/useSyncExternalStore.ts","kind":"import-statement","original":"./useSyncExternalStore"},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":874,"imports":[{"path":"src/components/RouteView/index.ts","kind":"import-statement","original":"./components/RouteView"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":21097},"dist/esm/index.mjs":{"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"preact","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/compat","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"preact/hooks","kind":"import-statement","external":true},{"path":"preact/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouteView","RouterContext","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/components/RouteView/components.tsx":{"bytesInOutput":171},"src/components/RouteView/helpers.tsx":{"bytesInOutput":1879},"src/hooks/useRouteNode.tsx":{"bytesInOutput":627},"src/useSyncExternalStore.ts":{"bytesInOutput":346},"src/hooks/useRouter.tsx":{"bytesInOutput":223},"src/context.ts":{"bytesInOutput":165},"src/components/RouteView/RouteView.tsx":{"bytesInOutput":567},"src/components/RouteView/index.ts":{"bytesInOutput":0},"src/index.ts":{"bytesInOutput":0},"src/components/Link.tsx":{"bytesInOutput":2315},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":597},"src/hooks/useStableValue.tsx":{"bytesInOutput":177},"src/hooks/useNavigator.tsx":{"bytesInOutput":257},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRoute.tsx":{"bytesInOutput":253},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":356},"src/RouterProvider.tsx":{"bytesInOutput":1298}},"bytes":10368}}}