@teardown/navigation 2.0.43

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/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@teardown/navigation",
3
+ "version": "2.0.43",
4
+ "description": "Type-safe file-based navigation for React Native",
5
+ "private": false,
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "type": "module",
10
+ "main": "./src/index.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./src/index.ts",
14
+ "import": "./src/index.ts",
15
+ "default": "./src/index.ts"
16
+ },
17
+ "./hooks": {
18
+ "types": "./src/hooks/index.ts",
19
+ "import": "./src/hooks/index.ts",
20
+ "default": "./src/hooks/index.ts"
21
+ },
22
+ "./components": {
23
+ "types": "./src/components/index.ts",
24
+ "import": "./src/components/index.ts",
25
+ "default": "./src/components/index.ts"
26
+ },
27
+ "./primitives": {
28
+ "types": "./src/primitives/index.ts",
29
+ "import": "./src/primitives/index.ts",
30
+ "default": "./src/primitives/index.ts"
31
+ },
32
+ "./types": {
33
+ "types": "./src/types/index.ts",
34
+ "import": "./src/types/index.ts",
35
+ "default": "./src/types/index.ts"
36
+ },
37
+ "./utils": {
38
+ "types": "./src/utils/index.ts",
39
+ "import": "./src/utils/index.ts",
40
+ "default": "./src/utils/index.ts"
41
+ }
42
+ },
43
+ "files": [
44
+ "src/**/*"
45
+ ],
46
+ "scripts": {
47
+ "typecheck": "bun x tsgo --noEmit",
48
+ "lint": "bun x biome lint --write ./src",
49
+ "fmt": "bun x biome format --write ./src",
50
+ "check": "bun x biome check ./src",
51
+ "test": "bun test"
52
+ },
53
+ "peerDependencies": {
54
+ "@react-navigation/bottom-tabs": ">=7.0.0",
55
+ "@react-navigation/drawer": ">=7.0.0",
56
+ "@react-navigation/native": ">=7.0.0",
57
+ "@react-navigation/native-stack": ">=7.0.0",
58
+ "react": ">=18.0.0",
59
+ "react-native": ">=0.72.0",
60
+ "zod": "4.2.1"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@react-navigation/bottom-tabs": {
64
+ "optional": true
65
+ },
66
+ "@react-navigation/drawer": {
67
+ "optional": true
68
+ },
69
+ "zod": {
70
+ "optional": true
71
+ }
72
+ },
73
+ "devDependencies": {
74
+ "@biomejs/biome": "2.3.11",
75
+ "@teardown/tsconfig": "2.0.43",
76
+ "@types/react": "19.2.7",
77
+ "typescript": "5.9.3"
78
+ }
79
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Components for @teardown/navigation
3
+ *
4
+ * Note: These components are placeholders that will work with React Navigation.
5
+ * Full implementation requires React Navigation to be installed.
6
+ */
7
+
8
+ export {};
9
+
10
+ // Components will be added as the library matures:
11
+ // - NavigationContainer wrapper
12
+ // - TypedLink component
13
+ // - ScreenWrapper
14
+ // - ErrorBoundary
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hooks for @teardown/navigation
3
+ */
4
+
5
+ // Navigation hooks
6
+ export {
7
+ createTypedNavigation,
8
+ createUseTypedNavigation,
9
+ type TypedNavigation,
10
+ useTypedNavigation,
11
+ } from "./use-typed-navigation";
12
+ // Params hooks
13
+ export { createUseTypedParams, useTypedParams } from "./use-typed-params";
14
+ // Route hooks
15
+ export { createTypedRoute, createUseTypedRoute, type TypedRoute, useTypedRoute } from "./use-typed-route";
@@ -0,0 +1,195 @@
1
+ /**
2
+ * useTypedNavigation hook for @teardown/navigation
3
+ * Provides type-safe navigation functions
4
+ */
5
+
6
+ import type { NavigationState, ParamsFor, RegisteredRoutePath } from "../types/route-types";
7
+ import { pathToScreenName } from "../utils/build-url";
8
+
9
+ /**
10
+ * Type-safe navigation interface
11
+ * All methods are fully typed based on the registered route params
12
+ */
13
+ export interface TypedNavigation {
14
+ /**
15
+ * Navigate to a route
16
+ * For routes with params, the params argument is required
17
+ * For routes without params, the params argument is optional
18
+ */
19
+ navigate<T extends RegisteredRoutePath>(
20
+ ...args: ParamsFor<T> extends undefined ? [path: T] : [path: T, params: ParamsFor<T>]
21
+ ): void;
22
+
23
+ /**
24
+ * Push a new screen onto the stack
25
+ * Only available in stack navigators
26
+ */
27
+ push<T extends RegisteredRoutePath>(
28
+ ...args: ParamsFor<T> extends undefined ? [path: T] : [path: T, params: ParamsFor<T>]
29
+ ): void;
30
+
31
+ /**
32
+ * Replace the current screen
33
+ * Only available in stack navigators
34
+ */
35
+ replace<T extends RegisteredRoutePath>(
36
+ ...args: ParamsFor<T> extends undefined ? [path: T] : [path: T, params: ParamsFor<T>]
37
+ ): void;
38
+
39
+ /**
40
+ * Go back to the previous screen
41
+ */
42
+ goBack(): void;
43
+
44
+ /**
45
+ * Check if there's a screen to go back to
46
+ */
47
+ canGoBack(): boolean;
48
+
49
+ /**
50
+ * Reset the navigation state
51
+ */
52
+ reset<T extends RegisteredRoutePath>(state: NavigationState<T>): void;
53
+
54
+ /**
55
+ * Update the params of the current screen
56
+ */
57
+ setParams<T extends RegisteredRoutePath>(params: Partial<ParamsFor<T>>): void;
58
+
59
+ /**
60
+ * Get the parent navigator (if any)
61
+ */
62
+ getParent(): TypedNavigation | undefined;
63
+
64
+ /**
65
+ * Check if a route is focused
66
+ */
67
+ isFocused(): boolean;
68
+ }
69
+
70
+ /**
71
+ * Creates a typed navigation adapter from a React Navigation instance
72
+ * This is used internally and should not be called directly in most cases
73
+ */
74
+ export function createTypedNavigation(navigation: unknown): TypedNavigation {
75
+ // Cast to any to access React Navigation methods
76
+ // The type safety comes from our TypedNavigation interface
77
+ const nav = navigation as {
78
+ navigate: (name: string, params?: object) => void;
79
+ push?: (name: string, params?: object) => void;
80
+ replace?: (name: string, params?: object) => void;
81
+ goBack: () => void;
82
+ canGoBack: () => boolean;
83
+ reset: (state: object) => void;
84
+ setParams: (params: object) => void;
85
+ getParent?: () => unknown;
86
+ isFocused: () => boolean;
87
+ };
88
+
89
+ // Implementation uses runtime types, but TypedNavigation provides compile-time safety
90
+ const typedNav: TypedNavigation = {
91
+ navigate(path: string, params?: object) {
92
+ const screenName = pathToScreenName(path);
93
+ nav.navigate(screenName, params);
94
+ },
95
+
96
+ push(path: string, params?: object) {
97
+ const screenName = pathToScreenName(path);
98
+ if (nav.push) {
99
+ nav.push(screenName, params);
100
+ } else {
101
+ nav.navigate(screenName, params);
102
+ }
103
+ },
104
+
105
+ replace(path: string, params?: object) {
106
+ const screenName = pathToScreenName(path);
107
+ if (nav.replace) {
108
+ nav.replace(screenName, params);
109
+ } else {
110
+ nav.navigate(screenName, params);
111
+ }
112
+ },
113
+
114
+ goBack() {
115
+ nav.goBack();
116
+ },
117
+
118
+ canGoBack() {
119
+ return nav.canGoBack();
120
+ },
121
+
122
+ reset(state: object) {
123
+ nav.reset(state);
124
+ },
125
+
126
+ setParams(params: object) {
127
+ nav.setParams(params);
128
+ },
129
+
130
+ getParent() {
131
+ if (nav.getParent) {
132
+ const parent = nav.getParent();
133
+ if (parent) {
134
+ return createTypedNavigation(parent);
135
+ }
136
+ }
137
+ return undefined;
138
+ },
139
+
140
+ isFocused() {
141
+ return nav.isFocused();
142
+ },
143
+ // Cast to TypedNavigation since the implementation handles the type checking at compile time
144
+ } as TypedNavigation;
145
+
146
+ return typedNav;
147
+ }
148
+
149
+ /**
150
+ * Hook to get typed navigation functions
151
+ * Must be used within a NavigationContainer
152
+ *
153
+ * @example
154
+ * ```tsx
155
+ * import { useTypedNavigation } from '@teardown/navigation/hooks';
156
+ *
157
+ * function MyComponent() {
158
+ * const navigation = useTypedNavigation();
159
+ *
160
+ * const handlePress = () => {
161
+ * // Fully type-checked!
162
+ * navigation.navigate('/users/:userId', { userId: '123' });
163
+ * };
164
+ *
165
+ * return <Button onPress={handlePress} title="View User" />;
166
+ * }
167
+ * ```
168
+ */
169
+ export function useTypedNavigation(): TypedNavigation {
170
+ // This hook needs to be connected to React Navigation's useNavigation
171
+ // In a real implementation, you would import and use React Navigation's hook:
172
+ //
173
+ // import { useNavigation } from '@react-navigation/native';
174
+ // const navigation = useNavigation();
175
+ // return createTypedNavigation(navigation);
176
+ //
177
+ // For now, we provide the interface and adapter function
178
+ // The actual hook implementation depends on React Navigation being available
179
+
180
+ throw new Error(
181
+ "useTypedNavigation must be used within a NavigationContainer. " +
182
+ "Make sure @react-navigation/native is installed and you are within a Navigator."
183
+ );
184
+ }
185
+
186
+ /**
187
+ * Creates a typed navigation hook that can be used with React Navigation
188
+ * This is a factory function for creating the actual hook
189
+ */
190
+ export function createUseTypedNavigation(useNavigation: () => unknown): () => TypedNavigation {
191
+ return function useTypedNavigationImpl(): TypedNavigation {
192
+ const navigation = useNavigation();
193
+ return createTypedNavigation(navigation);
194
+ };
195
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * useTypedParams hook for @teardown/navigation
3
+ * Provides type-safe access to route params
4
+ */
5
+
6
+ import type { ParamsFor, RegisteredRoutePath } from "../types/route-types";
7
+
8
+ /**
9
+ * Hook to get just the route params, typed for the current route
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * import { useTypedParams } from '@teardown/navigation/hooks';
14
+ *
15
+ * function UserProfileScreen() {
16
+ * // Specify the route path for type inference
17
+ * const params = useTypedParams<'/users/:userId'>();
18
+ *
19
+ * // params.userId is typed as string
20
+ * return <Text>User ID: {params.userId}</Text>;
21
+ * }
22
+ * ```
23
+ */
24
+ export function useTypedParams<T extends RegisteredRoutePath>(): ParamsFor<T> {
25
+ // This hook needs to be connected to React Navigation's useRoute
26
+ // In a real implementation:
27
+ //
28
+ // import { useRoute } from '@react-navigation/native';
29
+ // const route = useRoute();
30
+ // return (route.params ?? {}) as ParamsFor<T>;
31
+
32
+ throw new Error(
33
+ "useTypedParams must be used within a Navigator screen. " +
34
+ "Make sure @react-navigation/native is installed and you are within a Navigator."
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Creates a typed params hook that can be used with React Navigation
40
+ */
41
+ export function createUseTypedParams(useRoute: () => unknown): <T extends RegisteredRoutePath>() => ParamsFor<T> {
42
+ return function useTypedParamsImpl<T extends RegisteredRoutePath>(): ParamsFor<T> {
43
+ const route = useRoute() as { params?: object };
44
+ return (route.params ?? {}) as ParamsFor<T>;
45
+ };
46
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * useTypedRoute hook for @teardown/navigation
3
+ * Provides type-safe access to the current route
4
+ */
5
+
6
+ import type { ParamsFor, RegisteredRoutePath } from "../types/route-types";
7
+
8
+ /**
9
+ * Type-safe route interface
10
+ */
11
+ export interface TypedRoute<T extends RegisteredRoutePath = RegisteredRoutePath> {
12
+ /**
13
+ * The route path/name
14
+ */
15
+ name: T;
16
+
17
+ /**
18
+ * The route params (typed based on the route)
19
+ */
20
+ params: ParamsFor<T>;
21
+
22
+ /**
23
+ * Unique key for this route instance
24
+ */
25
+ key: string;
26
+ }
27
+
28
+ /**
29
+ * Creates a typed route object from a React Navigation route
30
+ */
31
+ export function createTypedRoute<T extends RegisteredRoutePath>(route: unknown): TypedRoute<T> {
32
+ const r = route as {
33
+ name: string;
34
+ params?: object;
35
+ key: string;
36
+ };
37
+
38
+ return {
39
+ name: r.name as T,
40
+ params: (r.params ?? {}) as ParamsFor<T>,
41
+ key: r.key,
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Hook to get the current route with type-safe params
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * import { useTypedRoute } from '@teardown/navigation/hooks';
51
+ *
52
+ * function UserProfileScreen() {
53
+ * // Specify the route path for type inference
54
+ * const route = useTypedRoute<'/users/:userId'>();
55
+ *
56
+ * // params.userId is typed as string
57
+ * return <Text>User ID: {route.params.userId}</Text>;
58
+ * }
59
+ * ```
60
+ */
61
+ export function useTypedRoute<T extends RegisteredRoutePath>(): TypedRoute<T> {
62
+ // This hook needs to be connected to React Navigation's useRoute
63
+ // In a real implementation:
64
+ //
65
+ // import { useRoute } from '@react-navigation/native';
66
+ // const route = useRoute();
67
+ // return createTypedRoute<T>(route);
68
+
69
+ throw new Error(
70
+ "useTypedRoute must be used within a Navigator screen. " +
71
+ "Make sure @react-navigation/native is installed and you are within a Navigator."
72
+ );
73
+ }
74
+
75
+ /**
76
+ * Creates a typed route hook that can be used with React Navigation
77
+ */
78
+ export function createUseTypedRoute(useRoute: () => unknown): <T extends RegisteredRoutePath>() => TypedRoute<T> {
79
+ return function useTypedRouteImpl<T extends RegisteredRoutePath>(): TypedRoute<T> {
80
+ const route = useRoute();
81
+ return createTypedRoute<T>(route);
82
+ };
83
+ }
package/src/index.ts ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @teardown/navigation
3
+ * Type-safe file-based navigation for React Native
4
+ */
5
+
6
+ export type { TypedNavigation, TypedRoute } from "./hooks";
7
+ // Hooks
8
+ export {
9
+ createTypedNavigation,
10
+ createTypedRoute,
11
+ createUseTypedNavigation,
12
+ createUseTypedParams,
13
+ createUseTypedRoute,
14
+ useTypedNavigation,
15
+ useTypedParams,
16
+ useTypedRoute,
17
+ } from "./hooks";
18
+ export type {
19
+ BaseScreenOptions,
20
+ DrawerLayoutConfig,
21
+ DrawerScreenOptions,
22
+ InferParamSchemaOutput,
23
+ LayoutConfig,
24
+ LayoutDefinition,
25
+ ParamSchema,
26
+ ParamSchemaShape,
27
+ PerScreenOptions,
28
+ ScreenConfig,
29
+ ScreenDefinition,
30
+ ScreenOptions,
31
+ StackLayoutConfig,
32
+ StackScreenOptions,
33
+ TabScreenOptions,
34
+ TabsLayoutConfig,
35
+ } from "./primitives";
36
+ // Primitives
37
+ export {
38
+ createParamSchema,
39
+ defineLayout,
40
+ defineScreen,
41
+ isLayoutDefinition,
42
+ isScreenDefinition,
43
+ paramValidators,
44
+ } from "./primitives";
45
+ // Types
46
+ export type {
47
+ NavigationState,
48
+ NavigatorType,
49
+ ParamsFor,
50
+ Register,
51
+ RegisteredRouteParams,
52
+ RegisteredRoutePath,
53
+ RouteConfig,
54
+ RouteWithParams,
55
+ } from "./types/route-types";
56
+ export type {
57
+ ExtractAllParams,
58
+ ExtractParam,
59
+ ExtractParamName,
60
+ HasRequiredParams,
61
+ InferParams,
62
+ IsCatchAllSegment,
63
+ IsDynamicSegment,
64
+ IsOptionalSegment,
65
+ NavigateArgs,
66
+ Simplify,
67
+ } from "./types/type-utils";
68
+ export type { MatchResult, ParsedPath } from "./utils";
69
+ // Utils
70
+ export { buildUrl, matchPath, parsePath, pathToScreenName } from "./utils";