@farbenmeer/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.
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # @farbenmeer/router Documentation
2
+
3
+ A lightweight, React-based client-side router with support for nested routes, path parameters, and immutable search parameter handling.
4
+
5
+ ## Overview
6
+
7
+ The `@farbenmeer/router` package provides a very lightweight routing solution for React applications with the following key features:
8
+
9
+ - **Declarative routing** with React components
10
+ - **Nested routes** with parameter inheritance
11
+ - **Path parameters** with bracket notation (`[id]`)
12
+ - **Immutable search parameters** for predictable state management
13
+ - **Client-side navigation** with history management
14
+ - **TypeScript support** for better development experience
15
+ - **Testing-friendly** with customizable location and history
16
+
17
+ ## Quick Start
18
+
19
+ ```tsx
20
+ import { Router, Route, Link } from "@farbenmeer/router";
21
+
22
+ function App() {
23
+ return (
24
+ <Router>
25
+ <nav>
26
+ <Link href="/">Home</Link>
27
+ <Link href="/users">Users</Link>
28
+ <Link href="/about">About</Link>
29
+ </nav>
30
+
31
+ <main>
32
+ <Route path="/">
33
+ <HomePage />
34
+ </Route>
35
+
36
+ <Route path="/users">
37
+ <UsersLayout />
38
+ <Route exact>
39
+ <UsersList />
40
+ </Route>
41
+ <Route path="[id]">
42
+ <UserProfile />
43
+ </Route>
44
+ </Route>
45
+
46
+ <Route path="/about">
47
+ <AboutPage />
48
+ </Route>
49
+ </main>
50
+ </Router>
51
+ );
52
+ }
53
+ ```
54
+
55
+ ## Components
56
+
57
+ ### [Router](./docs/Router.md)
58
+ The root component that provides routing context to your application.
59
+
60
+ - Manages current location state
61
+ - Provides navigation methods
62
+ - Supports custom location and history for testing
63
+ - Normalizes pathnames (removes trailing slashes)
64
+
65
+ ### [Route](./docs/Route.md)
66
+ Conditionally renders content based on the current pathname.
67
+
68
+ - Path matching with parameters (`/users/[id]`)
69
+ - Exact matching option
70
+ - Nested route support
71
+ - Parameter inheritance from parent routes
72
+
73
+ ### [Link](./docs/Link.md)
74
+ Declarative navigation component that renders as an anchor element.
75
+
76
+ - Client-side navigation with history management
77
+ - Supports absolute and relative paths
78
+ - Query parameter handling
79
+
80
+ ## Hooks
81
+
82
+ ### [useRouter](./docs/useRouter.md)
83
+ Provides programmatic navigation methods.
84
+
85
+ ```tsx
86
+ const router = useRouter();
87
+ router.push("/users/123"); // Navigate with history
88
+ router.replace("/login"); // Replace current entry
89
+ ```
90
+
91
+ ### [usePathname](./docs/usePathname.md)
92
+ Access the current pathname for conditional rendering and active states.
93
+
94
+ ```tsx
95
+ const pathname = usePathname();
96
+ const isActive = pathname === "/users";
97
+ ```
98
+
99
+ ### [useSearchParams](./docs/useSearchParams.md)
100
+ Access and manipulate URL search parameters with immutable methods.
101
+
102
+ ```tsx
103
+ const searchParams = useSearchParams();
104
+ const query = searchParams.get("q");
105
+ const newParams = searchParams.set("filter", "active");
106
+ ```
107
+
108
+ ### [useParams](./docs/useParams.md)
109
+ Extract parameters from dynamic route segments.
110
+
111
+ ```tsx
112
+ // Route: /users/[id]/posts/[postId]
113
+ const params = useParams(); // { id: "123", postId: "456" }
114
+ ```
115
+
116
+ ### [useHash](./docs/useHash.md)
117
+ Access the current URL hash fragment for tab navigation and anchor linking.
118
+
119
+ ```tsx
120
+ const hash = useHash();
121
+ const activeTab = hash.slice(1) || "overview";
122
+ ```
123
+
124
+ ## Key Features
125
+
126
+ ### Nested Routing
127
+
128
+ Create hierarchical route structures with parameter inheritance:
129
+
130
+ ```tsx
131
+ <Route path="/organizations/[orgId]">
132
+ <OrganizationLayout />
133
+
134
+ <Route path="teams/[teamId]">
135
+ <TeamLayout />
136
+
137
+ <Route path="members/[memberId]">
138
+ <MemberProfile />
139
+ </Route>
140
+ </Route>
141
+ </Route>
142
+ ```
143
+
144
+ ### Path Parameters
145
+
146
+ Define dynamic segments with bracket notation:
147
+
148
+ ```tsx
149
+ <Route path="/users/[id]"> {/* /users/123 */}
150
+ <Route path="/posts/[slug]"> {/* /posts/hello-world */}
151
+ <Route path="/api/[version]"> {/* /api/v1 */}
152
+ ```
153
+
154
+ ### Immutable Search Parameters
155
+
156
+ Safely update URL search parameters without mutations:
157
+
158
+ ```tsx
159
+ const searchParams = useSearchParams();
160
+ const withFilter = searchParams.set("category", "electronics");
161
+ const withSort = withFilter.set("sort", "price");
162
+ ```
163
+
164
+ ### Testing Support
165
+
166
+ Provide custom location and history for predictable tests:
167
+
168
+ ```tsx
169
+ <Router
170
+ location={{ pathname: "/users/123", search: "?tab=profile", hash: "#bio" }}
171
+ history={mockHistory}
172
+ >
173
+ <App />
174
+ </Router>
175
+ ```
176
+
177
+ ## Common Patterns
178
+
179
+ ### Active Navigation Links
180
+
181
+ ```tsx
182
+ function NavLink({ href, children }) {
183
+ const pathname = usePathname();
184
+ const isActive = pathname === href;
185
+
186
+ return (
187
+ <Link
188
+ href={href}
189
+ className={isActive ? 'nav-link active' : 'nav-link'}
190
+ >
191
+ {children}
192
+ </Link>
193
+ );
194
+ }
195
+ ```
196
+
197
+ ### Search and Filtering
198
+
199
+ ```tsx
200
+ function ProductSearch() {
201
+ const router = useRouter();
202
+ const pathname = usePathname();
203
+ const searchParams = useSearchParams();
204
+
205
+ const updateFilter = (key: string, value: string) => {
206
+ const newParams = searchParams.set(key, value);
207
+ router.push(`${pathname}?${newParams.toString()}`);
208
+ };
209
+
210
+ return (
211
+ <select onChange={(e) => updateFilter("category", e.target.value)}>
212
+ <option value="">All Categories</option>
213
+ <option value="electronics">Electronics</option>
214
+ </select>
215
+ );
216
+ }
217
+ ```
218
+
219
+
220
+ ## API Reference
221
+
222
+ For detailed API documentation, see the individual component and hook documentation files linked above.
@@ -0,0 +1,14 @@
1
+ import { ImmutableSearchParams } from "./immutable-search-params";
2
+ export declare const PathnameContext: import("react").Context<string>;
3
+ export declare const SearchParamsContext: import("react").Context<ImmutableSearchParams>;
4
+ export declare const HashContext: import("react").Context<string>;
5
+ export declare const RouterContext: import("react").Context<{
6
+ push: (href: string) => void;
7
+ replace: (href: string) => void;
8
+ }>;
9
+ export declare const RouteContext: import("react").Context<{
10
+ path: string;
11
+ params: Record<string, string | string[]>;
12
+ matchedPathname: string;
13
+ }>;
14
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,eAAO,MAAM,eAAe,iCAA6B,CAAC;AAE1D,eAAO,MAAM,mBAAmB,gDAE/B,CAAC;AAEF,eAAO,MAAM,WAAW,iCAA4B,CAAC;AAErD,eAAO,MAAM,aAAa;UAClB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;aACnB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;EAI/B,CAAC;AAEH,eAAO,MAAM,YAAY;UACjB,MAAM;YACJ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;qBACxB,MAAM;EAKvB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { createContext } from "react";
2
+ import { ImmutableSearchParams } from "./immutable-search-params";
3
+ export const PathnameContext = createContext("/");
4
+ export const SearchParamsContext = createContext(new ImmutableSearchParams());
5
+ export const HashContext = createContext("");
6
+ export const RouterContext = createContext({
7
+ push: () => { },
8
+ replace: () => { },
9
+ });
10
+ export const RouteContext = createContext({
11
+ path: "/",
12
+ params: {},
13
+ matchedPathname: "/",
14
+ });
@@ -0,0 +1,6 @@
1
+ export declare class ImmutableSearchParams extends URLSearchParams {
2
+ set(key: string, value: string): ImmutableSearchParams;
3
+ append(name: string, value: string): ImmutableSearchParams;
4
+ delete(key: string): ImmutableSearchParams;
5
+ }
6
+ //# sourceMappingURL=immutable-search-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"immutable-search-params.d.ts","sourceRoot":"","sources":["../src/immutable-search-params.ts"],"names":[],"mappings":"AAAA,qBAAa,qBAAsB,SAAQ,eAAe;IAC/C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAM9B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAMlC,MAAM,CAAC,GAAG,EAAE,MAAM;CAK5B"}
@@ -0,0 +1,17 @@
1
+ export class ImmutableSearchParams extends URLSearchParams {
2
+ set(key, value) {
3
+ const newSearchParams = new URLSearchParams(this);
4
+ newSearchParams.set(key, value);
5
+ return new ImmutableSearchParams(newSearchParams);
6
+ }
7
+ append(name, value) {
8
+ const newSearchParams = new URLSearchParams(this);
9
+ newSearchParams.append(name, value);
10
+ return new ImmutableSearchParams(newSearchParams);
11
+ }
12
+ delete(key) {
13
+ const newSearchParams = new URLSearchParams(this);
14
+ newSearchParams.delete(key);
15
+ return new ImmutableSearchParams(newSearchParams);
16
+ }
17
+ }
@@ -0,0 +1,9 @@
1
+ export { Router } from "./router";
2
+ export { Route } from "./route";
3
+ export { Link } from "./link";
4
+ export { useRouter } from "./use-router";
5
+ export { usePathname } from "./use-pathname";
6
+ export { useSearchParams } from "./use-search-params";
7
+ export { useHash } from "./use-hash";
8
+ export { useParams } from "./use-params";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { Router } from "./router";
2
+ export { Route } from "./route";
3
+ export { Link } from "./link";
4
+ export { useRouter } from "./use-router";
5
+ export { usePathname } from "./use-pathname";
6
+ export { useSearchParams } from "./use-search-params";
7
+ export { useHash } from "./use-hash";
8
+ export { useParams } from "./use-params";
package/dist/link.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { type HTMLProps } from "react";
2
+ interface Props extends HTMLProps<HTMLAnchorElement> {
3
+ href: string;
4
+ replace?: boolean;
5
+ }
6
+ export declare function Link({ href, replace, children, onClick, ...rawProps }: Props): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAQrE,UAAU,KAAM,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE,KAAK,2CA4C5E"}
package/dist/link.js ADDED
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { use, useMemo } from "react";
3
+ import { PathnameContext, RouteContext, RouterContext, SearchParamsContext, } from "./context";
4
+ export function Link({ href, replace, children, onClick, ...rawProps }) {
5
+ const { matchedPathname: parentPathname } = use(RouteContext);
6
+ const router = use(RouterContext);
7
+ const pathname = use(PathnameContext);
8
+ const searchParams = use(SearchParamsContext);
9
+ const target = useMemo(() => {
10
+ if (href.startsWith("/")) {
11
+ return href;
12
+ }
13
+ if (href.startsWith("?")) {
14
+ return pathname + href;
15
+ }
16
+ if (href.startsWith("#")) {
17
+ return (pathname +
18
+ (searchParams.size > 0 ? "?" + searchParams.toString() : "") +
19
+ href);
20
+ }
21
+ if (!href) {
22
+ return parentPathname;
23
+ }
24
+ return parentPathname + "/" + href;
25
+ }, [href, parentPathname, pathname]);
26
+ return (_jsx("a", { href: target, onClick: (event) => {
27
+ onClick?.(event);
28
+ if (event.defaultPrevented)
29
+ return;
30
+ event.preventDefault();
31
+ if (replace) {
32
+ router.replace(target);
33
+ }
34
+ else {
35
+ router.push(target);
36
+ }
37
+ }, ...rawProps, children: children }));
38
+ }
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ path?: string;
3
+ exact?: boolean;
4
+ children: React.ReactNode;
5
+ }
6
+ export declare function Route({ path, exact, children }: Props): import("react/jsx-runtime").JSX.Element | null;
7
+ export {};
8
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.tsx"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,kDA0BrD"}
package/dist/route.js ADDED
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { use, useMemo } from "react";
3
+ import { PathnameContext, RouteContext } from "./context";
4
+ export function Route({ path, exact, children }) {
5
+ const parentRoute = use(RouteContext);
6
+ const pathname = use(PathnameContext);
7
+ const fullPath = useMemo(() => buildFullPath(parentRoute.path, path ?? ""), [parentRoute.path, path]);
8
+ const pathRegex = useMemo(() => exact ? compileExactPathRegex(fullPath) : compilePathRegex(fullPath), [fullPath, exact]);
9
+ const match = useMemo(() => pathname.match(pathRegex), [pathname, pathRegex]);
10
+ const routeContextValue = useMemo(() => ({
11
+ path: fullPath,
12
+ params: match?.groups ?? {},
13
+ matchedPathname: match?.[1] ?? "",
14
+ }), [fullPath, match]);
15
+ if (!match)
16
+ return null;
17
+ return _jsx(RouteContext, { value: routeContextValue, children: children });
18
+ }
19
+ function compilePathRegex(path) {
20
+ if (path === "/") {
21
+ return /^\//;
22
+ }
23
+ return new RegExp(`^(${path.replaceAll(/\[(\w+)\]/g, "(?<$1>[\\w-]+)")})(/.*)?$`);
24
+ }
25
+ function compileExactPathRegex(path) {
26
+ if (path === "/") {
27
+ return /^\/$/;
28
+ }
29
+ return new RegExp(`^(${path.replaceAll(/\[(\w+)\]/g, "(?<$1>[\\w-]+)")})$`);
30
+ }
31
+ function buildFullPath(parentPath, path) {
32
+ if (path?.startsWith("/")) {
33
+ return path;
34
+ }
35
+ if (path) {
36
+ return parentPath + "/" + path;
37
+ }
38
+ return parentPath;
39
+ }
@@ -0,0 +1,16 @@
1
+ import { type ReactNode } from "react";
2
+ interface Props {
3
+ children: ReactNode;
4
+ location?: {
5
+ pathname: string;
6
+ search: string;
7
+ hash: string;
8
+ };
9
+ history?: {
10
+ pushState: (state: any, title: string, url: string) => void;
11
+ replaceState: (state: any, title: string, url: string) => void;
12
+ };
13
+ }
14
+ export declare function Router(props: Props): import("react/jsx-runtime").JSX.Element;
15
+ export {};
16
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAS3E,UAAU,KAAK;IACb,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,CAAC,EAAE;QACR,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAC5D,YAAY,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;KAChE,CAAC;CACH;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,2CAwDlC"}
package/dist/router.js ADDED
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { startTransition, useMemo, useState } from "react";
3
+ import { HashContext, PathnameContext, RouterContext, SearchParamsContext, } from "./context";
4
+ import { ImmutableSearchParams } from "./immutable-search-params";
5
+ export function Router(props) {
6
+ const [pathname, setPathname] = useState(removeTrailingSlash(props.location?.pathname ?? window.location.pathname));
7
+ const [search, setSearch] = useState(props.location?.search ?? window.location.search);
8
+ const [hash, setHash] = useState(props.location?.hash ?? window.location.hash);
9
+ const searchParams = useMemo(() => new ImmutableSearchParams(props.location?.search ?? search), [props.location?.search, search]);
10
+ const routerContextValue = useMemo(() => ({
11
+ push: (url) => {
12
+ (props.history ?? window.history).pushState(null, "", url);
13
+ if (!props.location) {
14
+ startTransition(() => {
15
+ setPathname(removeTrailingSlash(window.location.pathname));
16
+ setSearch(window.location.search);
17
+ setHash(window.location.hash);
18
+ });
19
+ }
20
+ },
21
+ replace: (url) => {
22
+ (props.history ?? window.history).replaceState(null, "", url);
23
+ if (!props.location) {
24
+ startTransition(() => {
25
+ setPathname(removeTrailingSlash(window.location.pathname));
26
+ setSearch(window.location.search);
27
+ setHash(window.location.hash);
28
+ });
29
+ }
30
+ },
31
+ }), []);
32
+ return (_jsx(RouterContext, { value: routerContextValue, children: _jsx(PathnameContext, { value: props.location?.pathname
33
+ ? removeTrailingSlash(props.location.pathname)
34
+ : pathname, children: _jsx(SearchParamsContext, { value: searchParams, children: _jsx(HashContext, { value: hash, children: props.children }) }) }) }));
35
+ }
36
+ function removeTrailingSlash(path) {
37
+ if (path === "/")
38
+ return path;
39
+ return path.endsWith("/") ? path.slice(0, -1) : path;
40
+ }
@@ -0,0 +1,2 @@
1
+ export declare function useHash(): string;
2
+ //# sourceMappingURL=use-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-hash.d.ts","sourceRoot":"","sources":["../src/use-hash.ts"],"names":[],"mappings":"AAGA,wBAAgB,OAAO,WAEtB"}
@@ -0,0 +1,5 @@
1
+ import { use } from "react";
2
+ import { HashContext } from "./context";
3
+ export function useHash() {
4
+ return use(HashContext);
5
+ }
@@ -0,0 +1,2 @@
1
+ export declare function useParams<T extends Record<string, string[]> = Record<string, string[]>>(): T;
2
+ //# sourceMappingURL=use-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-params.d.ts","sourceRoot":"","sources":["../src/use-params.ts"],"names":[],"mappings":"AAGA,wBAAgB,SAAS,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,KAI5C,CAAC,CACnB"}
@@ -0,0 +1,6 @@
1
+ import { use } from "react";
2
+ import { RouteContext } from "./context";
3
+ export function useParams() {
4
+ const { params } = use(RouteContext);
5
+ return params;
6
+ }
@@ -0,0 +1,2 @@
1
+ export declare function usePathname(): string;
2
+ //# sourceMappingURL=use-pathname.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-pathname.d.ts","sourceRoot":"","sources":["../src/use-pathname.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,WAE1B"}
@@ -0,0 +1,5 @@
1
+ import { use } from "react";
2
+ import { PathnameContext } from "./context";
3
+ export function usePathname() {
4
+ return use(PathnameContext);
5
+ }
@@ -0,0 +1,5 @@
1
+ export declare function useRouter(): {
2
+ push: (href: string) => void;
3
+ replace: (href: string) => void;
4
+ };
5
+ //# sourceMappingURL=use-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-router.d.ts","sourceRoot":"","sources":["../src/use-router.ts"],"names":[],"mappings":"AAGA,wBAAgB,SAAS;;;EAExB"}
@@ -0,0 +1,5 @@
1
+ import { use } from "react";
2
+ import { RouterContext } from "./context";
3
+ export function useRouter() {
4
+ return use(RouterContext);
5
+ }
@@ -0,0 +1,2 @@
1
+ export declare function useSearchParams(): import("./immutable-search-params").ImmutableSearchParams;
2
+ //# sourceMappingURL=use-search-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-search-params.d.ts","sourceRoot":"","sources":["../src/use-search-params.ts"],"names":[],"mappings":"AAGA,wBAAgB,eAAe,8DAE9B"}
@@ -0,0 +1,5 @@
1
+ import { use } from "react";
2
+ import { SearchParamsContext } from "./context";
3
+ export function useSearchParams() {
4
+ return use(SearchParamsContext);
5
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@farbenmeer/router",
3
+ "version": "0.1.0",
4
+ "author": {
5
+ "name": "Michel Smola",
6
+ "email": "michel.smola@farbenmeer.de"
7
+ },
8
+ "type": "module",
9
+ "module": "dist/index.js",
10
+ "main": "dist/index.js",
11
+ "private": false,
12
+ "license": "MIT",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.build.json",
18
+ "release": "bun run build && bun publish"
19
+ },
20
+ "dependencies": {},
21
+ "devDependencies": {
22
+ "@happy-dom/global-registrator": "^18.0.1",
23
+ "@testing-library/dom": "^10.4.1",
24
+ "@testing-library/jest-dom": "^6.8.0",
25
+ "@testing-library/react": "^16.3.0",
26
+ "@types/bun": "latest",
27
+ "react": "^19.1.1"
28
+ },
29
+ "peerDependencies": {
30
+ "typescript": "^5",
31
+ "react": "^19.1.1"
32
+ }
33
+ }