@rnzeus/atlas 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/dist/README.md +21 -0
- package/dist/config/internal.d.ts +1 -0
- package/dist/config/internal.js +1 -0
- package/dist/config/navigation/index.d.ts +1 -0
- package/dist/config/navigation/index.js +1 -0
- package/dist/config/navigation/types.d.ts +55 -0
- package/dist/config/navigation/types.js +1 -0
- package/dist/config/navigation.types.d.ts +25 -0
- package/dist/config/navigation.types.js +1 -0
- package/dist/hooks/README.md +11 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/internal.d.ts +1 -0
- package/dist/hooks/internal.js +1 -0
- package/dist/hooks/use-path-navigation/README.md +66 -0
- package/dist/hooks/use-path-navigation/hook.d.ts +119 -0
- package/dist/hooks/use-path-navigation/hook.js +52 -0
- package/dist/hooks/use-path-navigation/index.d.ts +1 -0
- package/dist/hooks/use-path-navigation/index.js +1 -0
- package/dist/services/README.md +17 -0
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.js +3 -0
- package/dist/services/internal.d.ts +1 -0
- package/dist/services/internal.js +1 -0
- package/dist/services/navigation/README.md +131 -0
- package/dist/services/navigation/api.d.ts +5 -0
- package/dist/services/navigation/api.js +11 -0
- package/dist/services/navigation/chain-builder.d.ts +16 -0
- package/dist/services/navigation/chain-builder.js +31 -0
- package/dist/services/navigation/index.d.ts +3 -0
- package/dist/services/navigation/index.js +3 -0
- package/dist/services/navigation/service.d.ts +55 -0
- package/dist/services/navigation/service.js +536 -0
- package/dist/services/navigation/types.d.ts +13 -0
- package/dist/services/navigation/types.js +1 -0
- package/dist/services/navigation/zod-adapter.d.ts +22 -0
- package/dist/services/navigation/zod-adapter.js +36 -0
- package/dist/services/transport/README.md +79 -0
- package/dist/services/transport/build-query.d.ts +2 -0
- package/dist/services/transport/build-query.js +3 -0
- package/dist/services/transport/create-transport-methods.d.ts +8 -0
- package/dist/services/transport/create-transport-methods.js +34 -0
- package/dist/services/transport/error-exception.d.ts +8 -0
- package/dist/services/transport/error-exception.js +16 -0
- package/dist/services/transport/index.d.ts +3 -0
- package/dist/services/transport/index.js +2 -0
- package/dist/services/transport/read-response-body.d.ts +3 -0
- package/dist/services/transport/read-response-body.js +27 -0
- package/dist/services/transport/service.d.ts +22 -0
- package/dist/services/transport/service.js +102 -0
- package/dist/services/transport/types.d.ts +4 -0
- package/dist/services/transport/types.js +1 -0
- package/dist/ui/README.md +17 -0
- package/dist/ui/debug-dock/README.md +58 -0
- package/dist/ui/debug-dock/debug-dock.d.ts +13 -0
- package/dist/ui/debug-dock/debug-dock.js +20 -0
- package/dist/ui/debug-dock/index.d.ts +2 -0
- package/dist/ui/debug-dock/index.js +1 -0
- package/dist/ui/debug-dock/styles.d.ts +8 -0
- package/dist/ui/debug-dock/styles.js +25 -0
- package/dist/ui/debug-dock/use-debug-dock.d.ts +20 -0
- package/dist/ui/debug-dock/use-debug-dock.js +71 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +2 -0
- package/dist/ui/toast/README.md +62 -0
- package/dist/ui/toast/context.d.ts +7 -0
- package/dist/ui/toast/context.js +6 -0
- package/dist/ui/toast/index.d.ts +5 -0
- package/dist/ui/toast/index.js +2 -0
- package/dist/ui/toast/toast-plate/README.md +38 -0
- package/dist/ui/toast/toast-plate/index.d.ts +2 -0
- package/dist/ui/toast/toast-plate/index.js +1 -0
- package/dist/ui/toast/toast-plate/toast-plate.d.ts +9 -0
- package/dist/ui/toast/toast-plate/toast-plate.js +11 -0
- package/dist/ui/toast/toast-plate/use-toast-plate.d.ts +4 -0
- package/dist/ui/toast/toast-plate/use-toast-plate.js +33 -0
- package/dist/ui/toast/toast-provider.d.ts +10 -0
- package/dist/ui/toast/toast-provider.js +53 -0
- package/dist/ui/toast/toast-viewport/README.md +38 -0
- package/dist/ui/toast/toast-viewport/index.d.ts +2 -0
- package/dist/ui/toast/toast-viewport/index.js +1 -0
- package/dist/ui/toast/toast-viewport/styles.d.ts +5 -0
- package/dist/ui/toast/toast-viewport/styles.js +10 -0
- package/dist/ui/toast/toast-viewport/toast-viewport.d.ts +10 -0
- package/dist/ui/toast/toast-viewport/toast-viewport.js +13 -0
- package/dist/ui/toast/types.d.ts +25 -0
- package/dist/ui/toast/types.js +1 -0
- package/dist/ui/toast/use-toast.d.ts +1 -0
- package/dist/ui/toast/use-toast.js +5 -0
- package/dist/utils/README.md +23 -0
- package/dist/utils/create-typography/README.md +71 -0
- package/dist/utils/create-typography/helper.d.ts +23 -0
- package/dist/utils/create-typography/helper.js +72 -0
- package/dist/utils/create-typography/index.d.ts +1 -0
- package/dist/utils/create-typography/index.js +1 -0
- package/dist/utils/define-route/README.md +50 -0
- package/dist/utils/define-route/helper.d.ts +2 -0
- package/dist/utils/define-route/helper.js +1 -0
- package/dist/utils/define-route/index.d.ts +1 -0
- package/dist/utils/define-route/index.js +1 -0
- package/dist/utils/display-name/README.md +46 -0
- package/dist/utils/display-name/helper.d.ts +2 -0
- package/dist/utils/display-name/helper.js +91 -0
- package/dist/utils/display-name/index.d.ts +1 -0
- package/dist/utils/display-name/index.js +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/internal.d.ts +3 -0
- package/dist/utils/internal.js +3 -0
- package/package.json +74 -0
package/dist/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# `@rnzeus/atlas`
|
|
2
|
+
|
|
3
|
+
✨ A shared toolkit of services, utilities, helpers, and hooks.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- [`Services`](./services/README.md)
|
|
8
|
+
- [`Hooks`](./hooks/README.md)
|
|
9
|
+
- [`Utilities`](./utils/README.md)
|
|
10
|
+
- [`UI`](./ui/README.md)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
This package has peer dependencies that should be present in your app.
|
|
15
|
+
|
|
16
|
+
Install missing peers:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
# yarn
|
|
20
|
+
yarn add @react-navigation/native qs
|
|
21
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { LinkingOptions, NavigationContainerRef, ParamListBase } from '@react-navigation/native';
|
|
2
|
+
export type NavigationStrict = boolean;
|
|
3
|
+
export type NavigationErrorCtx = {
|
|
4
|
+
type: 'build';
|
|
5
|
+
route: RouteDef<any, any>;
|
|
6
|
+
input: unknown;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'query';
|
|
9
|
+
route: RouteDef<any, any>;
|
|
10
|
+
input: unknown;
|
|
11
|
+
};
|
|
12
|
+
export type NavigationOnError = (error: Error, ctx: NavigationErrorCtx) => void;
|
|
13
|
+
export type ConfigureNavigationOptions = {
|
|
14
|
+
ref: NavigationContainerRef<ParamListBase>;
|
|
15
|
+
linking: LinkingOptions<ParamListBase>;
|
|
16
|
+
strict?: NavigationStrict;
|
|
17
|
+
onError?: NavigationOnError;
|
|
18
|
+
};
|
|
19
|
+
export type SchemaLike<T> = {
|
|
20
|
+
safeParse: (input: unknown) => {
|
|
21
|
+
success: true;
|
|
22
|
+
data: T;
|
|
23
|
+
} | {
|
|
24
|
+
success: false;
|
|
25
|
+
error: unknown;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export type RouteDef<P = undefined, Q = undefined> = {
|
|
29
|
+
path: string;
|
|
30
|
+
name: string;
|
|
31
|
+
linking: string;
|
|
32
|
+
key?: string;
|
|
33
|
+
__params?: P;
|
|
34
|
+
__query?: Q;
|
|
35
|
+
paramsSchema?: SchemaLike<P>;
|
|
36
|
+
querySchema?: SchemaLike<Q>;
|
|
37
|
+
};
|
|
38
|
+
export type RouteParams<R> = R extends RouteDef<infer P, any> ? P : never;
|
|
39
|
+
export type RouteQuery<R> = R extends RouteDef<any, infer Q> ? Q : never;
|
|
40
|
+
export type BuiltPath<R extends RouteDef<any, any> = RouteDef<any, any>> = string & {
|
|
41
|
+
readonly __brand: 'BuiltPath';
|
|
42
|
+
readonly __route?: R;
|
|
43
|
+
};
|
|
44
|
+
export type QueryOptions = Partial<{
|
|
45
|
+
encode: boolean;
|
|
46
|
+
nested: 'json';
|
|
47
|
+
debug: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Keep `null` values in the output query string.
|
|
50
|
+
*
|
|
51
|
+
* When enabled, `null` is serialized as the string `"null"`,
|
|
52
|
+
* which can be safely round-tripped with `JSON.parse`.
|
|
53
|
+
*/
|
|
54
|
+
nullable: boolean;
|
|
55
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type RouteDef<P = undefined, Q = undefined> = {
|
|
2
|
+
path: string;
|
|
3
|
+
name: string;
|
|
4
|
+
linking: string;
|
|
5
|
+
key?: string;
|
|
6
|
+
__params?: P;
|
|
7
|
+
__query?: Q;
|
|
8
|
+
};
|
|
9
|
+
export type RouteParams<R> = R extends RouteDef<infer P, any> ? P : never;
|
|
10
|
+
export type RouteQuery<R> = R extends RouteDef<any, infer Q> ? Q : never;
|
|
11
|
+
export type BuiltPath<R extends RouteDef<any, any> = RouteDef<any, any>> = string & {
|
|
12
|
+
readonly __brand: 'BuiltPath';
|
|
13
|
+
readonly __route?: R;
|
|
14
|
+
};
|
|
15
|
+
export type StrictMode = 'off' | 'warn' | 'throw';
|
|
16
|
+
export type ValidationResult = {
|
|
17
|
+
ok: true;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
message: string;
|
|
21
|
+
};
|
|
22
|
+
export type NavigationValidator = {
|
|
23
|
+
validateBuild?: <R extends RouteDef<any, any>>(route: R, params: unknown) => ValidationResult;
|
|
24
|
+
validateQuery?: <R extends RouteDef<any, any>>(route: R, query: unknown) => ValidationResult;
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# `@rnzeus/atlas/hooks`
|
|
2
|
+
|
|
3
|
+
← [`@rnzeus/atlas`](../README.md)
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- **[`use-path-navigation`](./use-path-navigation/README.md)** — navigate by path strings using the Navigation service.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {usePathNavigation} from '@rnzeus/atlas/hooks';
|
|
11
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { usePathNavigation } from './use-path-navigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { usePathNavigation } from './use-path-navigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './use-path-navigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './use-path-navigation';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# `@rnzeus/atlas/hooks/use-path-navigation`
|
|
2
|
+
|
|
3
|
+
← [`@rnzeus/atlas/hooks`](../README.md)
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Navigate using **typed branded paths** from inside React components (React Navigation), powered by the Atlas `Navigation` service.
|
|
8
|
+
|
|
9
|
+
## Import
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import {usePathNavigation} from '@rnzeus/atlas/hooks';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## API (public surface)
|
|
16
|
+
|
|
17
|
+
`usePathNavigation<N extends NavigationProp<ParamListBase>>()` returns:
|
|
18
|
+
|
|
19
|
+
- Navigation (safe, path-based)
|
|
20
|
+
- `navigate(path: BuiltPath): void`
|
|
21
|
+
- `push(path: BuiltPath): void`
|
|
22
|
+
- `replace(path: BuiltPath): void`
|
|
23
|
+
- `popTo(path: BuiltPath): void`
|
|
24
|
+
- `reset(path: BuiltPath): void`
|
|
25
|
+
- `popToTop(): void`
|
|
26
|
+
- `goBack(): void`
|
|
27
|
+
- Builders
|
|
28
|
+
- `build(route, params?)` → `BuiltPath`
|
|
29
|
+
- `query(builtPath, query?, opts?)` → `BuiltPath`
|
|
30
|
+
- `chain(route, params?)` → `ChainBuilder` (fluent `query().navigate()/push()/reset()`)
|
|
31
|
+
- Raw (whitelist from React Navigation)
|
|
32
|
+
- `setParams(...)`
|
|
33
|
+
- `setOptions(...)` (typed based on `N`)
|
|
34
|
+
- `getState?()`, `addListener?()`, `removeListener?()`, `isFocused?()`, `canGoBack?()`, `getParent?()`, `dispatch?()`
|
|
35
|
+
|
|
36
|
+
## Usage (minimal)
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import {usePathNavigation} from '@rnzeus/atlas/hooks';
|
|
40
|
+
import {defineRoute} from '@rnzeus/atlas/utils';
|
|
41
|
+
|
|
42
|
+
export function GoToBooking() {
|
|
43
|
+
const nav = usePathNavigation();
|
|
44
|
+
|
|
45
|
+
const BOOKING = defineRoute()({
|
|
46
|
+
name: 'Booking',
|
|
47
|
+
path: 'non-tabbar/booking/:id',
|
|
48
|
+
linking: 'booking',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return <Button title="Go" onPress={() => nav.navigate(nav.build(BOOKING, {id: 42}))} />;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Notes
|
|
56
|
+
|
|
57
|
+
- **Requirements**:
|
|
58
|
+
- must be used inside a React Navigation tree (`useNavigation()` must work)
|
|
59
|
+
- `Navigation.linkingConfig` must be configured once at app bootstrap (path parsing depends on it)
|
|
60
|
+
- **How it works**: the hook dispatches actions via local `navigation`, so it does not require a global `navRef`.
|
|
61
|
+
- **Builders**: `build` / `query` / `chain` are built on top of the `Navigation` service. Prefer branded paths (`BuiltPath`) over raw strings.
|
|
62
|
+
|
|
63
|
+
## Sources
|
|
64
|
+
|
|
65
|
+
- [`hook`](./hook.js)
|
|
66
|
+
- [`index`](./index.js)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { NavigationProp, ParamListBase } from '@react-navigation/native';
|
|
2
|
+
import type { BuiltPath, QueryOptions, RouteDef, RouteParams, RouteQuery } from '../../config/internal';
|
|
3
|
+
import { ChainBuilder } from '../../services/internal';
|
|
4
|
+
/**
|
|
5
|
+
* N is the navigation type (NavigationProp / NativeStackNavigationProp / etc),
|
|
6
|
+
* so the consumer can pass the "correct" nav type and get the setOptions type.
|
|
7
|
+
*/
|
|
8
|
+
declare const usePathNavigation: <N extends NavigationProp<ParamListBase> = NavigationProp<ParamListBase>>() => {
|
|
9
|
+
getState: () => Readonly<{
|
|
10
|
+
key: string;
|
|
11
|
+
index: number;
|
|
12
|
+
routeNames: string[];
|
|
13
|
+
history?: unknown[];
|
|
14
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
15
|
+
type: string;
|
|
16
|
+
stale: false;
|
|
17
|
+
}>;
|
|
18
|
+
addListener: <EventName extends keyof import("@react-navigation/core").EventMapCore<Readonly<{
|
|
19
|
+
key: string;
|
|
20
|
+
index: number;
|
|
21
|
+
routeNames: string[];
|
|
22
|
+
history?: unknown[];
|
|
23
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
24
|
+
type: string;
|
|
25
|
+
stale: false;
|
|
26
|
+
}>>>(type: EventName, callback: import("@react-navigation/core").EventListenerCallback<import("@react-navigation/core").EventMapCore<Readonly<{
|
|
27
|
+
key: string;
|
|
28
|
+
index: number;
|
|
29
|
+
routeNames: string[];
|
|
30
|
+
history?: unknown[];
|
|
31
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
32
|
+
type: string;
|
|
33
|
+
stale: false;
|
|
34
|
+
}>>, EventName, import("@react-navigation/core").EventMapCore<Readonly<{
|
|
35
|
+
key: string;
|
|
36
|
+
index: number;
|
|
37
|
+
routeNames: string[];
|
|
38
|
+
history?: unknown[];
|
|
39
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
40
|
+
type: string;
|
|
41
|
+
stale: false;
|
|
42
|
+
}>>[EventName]["canPreventDefault"]>) => () => void;
|
|
43
|
+
removeListener: <EventName extends keyof import("@react-navigation/core").EventMapCore<Readonly<{
|
|
44
|
+
key: string;
|
|
45
|
+
index: number;
|
|
46
|
+
routeNames: string[];
|
|
47
|
+
history?: unknown[];
|
|
48
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
49
|
+
type: string;
|
|
50
|
+
stale: false;
|
|
51
|
+
}>>>(type: EventName, callback: import("@react-navigation/core").EventListenerCallback<import("@react-navigation/core").EventMapCore<Readonly<{
|
|
52
|
+
key: string;
|
|
53
|
+
index: number;
|
|
54
|
+
routeNames: string[];
|
|
55
|
+
history?: unknown[];
|
|
56
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
57
|
+
type: string;
|
|
58
|
+
stale: false;
|
|
59
|
+
}>>, EventName, import("@react-navigation/core").EventMapCore<Readonly<{
|
|
60
|
+
key: string;
|
|
61
|
+
index: number;
|
|
62
|
+
routeNames: string[];
|
|
63
|
+
history?: unknown[];
|
|
64
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
65
|
+
type: string;
|
|
66
|
+
stale: false;
|
|
67
|
+
}>>[EventName]["canPreventDefault"]>) => void;
|
|
68
|
+
isFocused: () => boolean;
|
|
69
|
+
canGoBack: () => boolean;
|
|
70
|
+
getParent: <T = NavigationProp<ParamListBase, string, string | undefined, Readonly<{
|
|
71
|
+
key: string;
|
|
72
|
+
index: number;
|
|
73
|
+
routeNames: string[];
|
|
74
|
+
history?: unknown[];
|
|
75
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
76
|
+
type: string;
|
|
77
|
+
stale: false;
|
|
78
|
+
}>, {}, {}> | undefined>(id?: string | undefined) => T;
|
|
79
|
+
dispatch: (action: Readonly<{
|
|
80
|
+
type: string;
|
|
81
|
+
payload?: object;
|
|
82
|
+
source?: string;
|
|
83
|
+
target?: string;
|
|
84
|
+
}> | ((state: Readonly<Readonly<{
|
|
85
|
+
key: string;
|
|
86
|
+
index: number;
|
|
87
|
+
routeNames: string[];
|
|
88
|
+
history?: unknown[];
|
|
89
|
+
routes: import("@react-navigation/routers").NavigationRoute<ParamListBase, string>[];
|
|
90
|
+
type: string;
|
|
91
|
+
stale: false;
|
|
92
|
+
}>>) => Readonly<{
|
|
93
|
+
type: string;
|
|
94
|
+
payload?: object;
|
|
95
|
+
source?: string;
|
|
96
|
+
target?: string;
|
|
97
|
+
}>)) => void;
|
|
98
|
+
setParams: N["setParams"];
|
|
99
|
+
replaceParams: N["replaceParams"];
|
|
100
|
+
setOptions: N extends {
|
|
101
|
+
setOptions: infer F;
|
|
102
|
+
} ? F : never;
|
|
103
|
+
navigate: (path: BuiltPath) => void;
|
|
104
|
+
push: (path: BuiltPath) => void;
|
|
105
|
+
replace: (path: BuiltPath) => void;
|
|
106
|
+
popTo: (path: BuiltPath) => void;
|
|
107
|
+
reset: (path: BuiltPath) => void;
|
|
108
|
+
popToTop: () => void;
|
|
109
|
+
goBack: () => void;
|
|
110
|
+
build: <R extends RouteDef<any, any>>(route: R, ...args: RouteParams<R> extends undefined ? [] : [params: RouteParams<R>]) => BuiltPath<R>;
|
|
111
|
+
query: {
|
|
112
|
+
<R extends RouteDef<any, undefined>>(url: BuiltPath<R>): BuiltPath<R>;
|
|
113
|
+
<R extends RouteDef<any, undefined>>(url: BuiltPath<R>, q: undefined, opts?: QueryOptions): BuiltPath<R>;
|
|
114
|
+
<R extends RouteDef<any, any>>(url: BuiltPath<R>, q: RouteQuery<R>, opts?: QueryOptions): BuiltPath<R>;
|
|
115
|
+
<R extends RouteDef<any, any>>(url: BuiltPath<R>, q?: RouteQuery<R>, opts?: QueryOptions): BuiltPath<R>;
|
|
116
|
+
};
|
|
117
|
+
chain: <R extends RouteDef<any, any>>(route: R, ...args: RouteParams<R> extends undefined ? [] : [params: RouteParams<R>]) => ChainBuilder<R>;
|
|
118
|
+
};
|
|
119
|
+
export default usePathNavigation;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useNavigation } from '@react-navigation/native';
|
|
2
|
+
import { ChainBuilder, Navigation } from '../../services/internal';
|
|
3
|
+
/**
|
|
4
|
+
* N is the navigation type (NavigationProp / NativeStackNavigationProp / etc),
|
|
5
|
+
* so the consumer can pass the "correct" nav type and get the setOptions type.
|
|
6
|
+
*/
|
|
7
|
+
const usePathNavigation = () => {
|
|
8
|
+
const navigation = useNavigation();
|
|
9
|
+
const build = (route, ...args) => {
|
|
10
|
+
if (args.length === 0)
|
|
11
|
+
return Navigation.build(route);
|
|
12
|
+
return Navigation.build(route, args[0]);
|
|
13
|
+
};
|
|
14
|
+
const query = ((url, q, opts) => Navigation.query(url, q, opts));
|
|
15
|
+
// chaining
|
|
16
|
+
const chain = (route, ...args) => {
|
|
17
|
+
const base = build(route, ...args);
|
|
18
|
+
return new ChainBuilder(base, navigation, query);
|
|
19
|
+
};
|
|
20
|
+
const raw = {
|
|
21
|
+
// state + events
|
|
22
|
+
getState: navigation.getState?.bind(navigation),
|
|
23
|
+
addListener: navigation.addListener?.bind(navigation),
|
|
24
|
+
removeListener: navigation.removeListener?.bind(navigation),
|
|
25
|
+
isFocused: navigation.isFocused?.bind(navigation),
|
|
26
|
+
canGoBack: navigation.canGoBack?.bind(navigation),
|
|
27
|
+
getParent: navigation.getParent?.bind(navigation),
|
|
28
|
+
// advanced
|
|
29
|
+
dispatch: navigation.dispatch?.bind(navigation),
|
|
30
|
+
// params/options (type depends on N)
|
|
31
|
+
setParams: navigation.setParams?.bind(navigation),
|
|
32
|
+
replaceParams: navigation.replaceParams?.bind(navigation),
|
|
33
|
+
setOptions: navigation.setOptions?.bind(navigation),
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
// navigation (safe, path-based)
|
|
37
|
+
navigate: (path) => Navigation.navigate(path, navigation),
|
|
38
|
+
push: (path) => Navigation.push(path),
|
|
39
|
+
replace: (path) => Navigation.replace(path),
|
|
40
|
+
popTo: (path) => Navigation.popTo(path, navigation),
|
|
41
|
+
reset: (path) => Navigation.reset(path),
|
|
42
|
+
popToTop: () => Navigation.popToTop(navigation),
|
|
43
|
+
goBack: () => Navigation.goBack(),
|
|
44
|
+
// builders
|
|
45
|
+
build,
|
|
46
|
+
query,
|
|
47
|
+
chain,
|
|
48
|
+
// raw (whitelist)
|
|
49
|
+
...raw,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export default usePathNavigation;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as usePathNavigation } from './hook';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as usePathNavigation } from './hook';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# `@rnzeus/atlas/services`
|
|
2
|
+
|
|
3
|
+
← [`@rnzeus/atlas`](../README.md)
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- **[`Transport`](./transport/README.md)** — a base `fetch` transport with query params, default headers, error normalization, and `get/post/put/delete`. Instantiate with base URL and defaults, then call verb methods from modules that own API paths.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {Transport} from '@rnzeus/atlas/services';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- **[`Navigation`](./navigation/README.md)** — programmatic path-based navigation on top of React Navigation (navigate/push/replace/popTo/reset + URL helpers). Call `configureNavigation()` once with a ref and linking config, then use `Navigation` (or `usePathNavigation`) with `defineRoute()` and `BuiltPath` for type-safe paths.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import {Navigation, configureNavigation} from '@rnzeus/atlas/services';
|
|
17
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navigation';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './navigation';
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# `@rnzeus/atlas/services/navigation`
|
|
2
|
+
|
|
3
|
+
← [`@rnzeus/atlas/services`](../README.md)
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Programmatic path-based navigation on top of React Navigation. Supports nested stacks, safe `popTo()` behavior, **branded typed paths** (`BuiltPath`), and optional runtime validation (schema-based, e.g. Zod).
|
|
8
|
+
|
|
9
|
+
## Import
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import {Navigation, configureNavigation} from '@rnzeus/atlas/services';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## API (public surface)
|
|
16
|
+
|
|
17
|
+
- Configuration (required for path parsing)
|
|
18
|
+
- `Navigation.linkingConfig = linking`
|
|
19
|
+
- Optional (required for “global” navigation outside React tree)
|
|
20
|
+
- `Navigation.navRef = navRef`
|
|
21
|
+
- Convenience configuration
|
|
22
|
+
- `configureNavigation({ ref, linking, strict?, onError? })`
|
|
23
|
+
- Navigation actions
|
|
24
|
+
- **Safe (preferred)**:
|
|
25
|
+
- `navigate(path: BuiltPath, navigation?)`
|
|
26
|
+
- `push(path: BuiltPath, navigation?)`
|
|
27
|
+
- `replace(path: BuiltPath, navigation?)`
|
|
28
|
+
- `popTo(path: BuiltPath, navigation?)`
|
|
29
|
+
- `reset(path: BuiltPath)`
|
|
30
|
+
- **Unsafe (strings)**:
|
|
31
|
+
- `navigateUnsafe(path: string, navigation?)`
|
|
32
|
+
- `pushUnsafe(path: string, navigation?)`
|
|
33
|
+
- `replaceUnsafe(path: string, navigation?)`
|
|
34
|
+
- `popToUnsafe(path: string, navigation?)`
|
|
35
|
+
- `resetUnsafe(path: string)`
|
|
36
|
+
- `popToTop(navigation?)`
|
|
37
|
+
- `goBack()`
|
|
38
|
+
- Helpers
|
|
39
|
+
- `getCurrentPath()`
|
|
40
|
+
- `build(route, params?)` → `BuiltPath`
|
|
41
|
+
- `query(url: BuiltPath, query?, opts?)` → `BuiltPath` (see `QueryOptions`)
|
|
42
|
+
|
|
43
|
+
## Usage (minimal)
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import {Navigation, configureNavigation} from '@rnzeus/atlas/services';
|
|
47
|
+
import {defineRoute} from '@rnzeus/atlas/utils';
|
|
48
|
+
|
|
49
|
+
// Configure once at app bootstrap (must include full nesting config).
|
|
50
|
+
configureNavigation({ref: navRef, linking, strict: false});
|
|
51
|
+
|
|
52
|
+
const BOOKING = defineRoute<{id: number}, {step?: string}>()({
|
|
53
|
+
name: 'Booking',
|
|
54
|
+
path: 'non-tabbar/booking/:id',
|
|
55
|
+
linking: 'booking',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const url = Navigation.query(Navigation.build(BOOKING, {id: 42}), {step: 'seats'});
|
|
59
|
+
Navigation.navigate(url);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage (optional validation: Zod)
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import {Navigation} from '@rnzeus/atlas/services';
|
|
66
|
+
import {defineRoute} from '@rnzeus/atlas/utils';
|
|
67
|
+
import {z} from 'zod';
|
|
68
|
+
|
|
69
|
+
const SCHEDULE_DETAIL = defineRoute<{id: string}>()({
|
|
70
|
+
name: 'ScheduleDetail',
|
|
71
|
+
path: 'schedule/:id',
|
|
72
|
+
linking: 'schedule-detail',
|
|
73
|
+
paramsSchema: z.object({id: z.string().min(1)}),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const SCHEDULE_LIST = defineRoute<undefined, {direction: 'inbound' | 'outbound'}>()({
|
|
77
|
+
name: 'ScheduleList',
|
|
78
|
+
path: 'schedule',
|
|
79
|
+
linking: 'schedule-list',
|
|
80
|
+
querySchema: z.object({direction: z.enum(['inbound', 'outbound'])}),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// strict=true is recommended only for development/test.
|
|
84
|
+
// In production builds prefer strict=false and report via onError.
|
|
85
|
+
Navigation.strict = true;
|
|
86
|
+
Navigation.onError = (error, ctx) => {
|
|
87
|
+
// send to your logger/sentry and decide how to handle it
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const url = Navigation.query(Navigation.build(SCHEDULE_LIST), {direction: 'inbound'});
|
|
91
|
+
Navigation.navigate(url);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Then, inside the target screen/component you can access the parsed values via React Navigation `route.params`:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import {useRoute} from '@react-navigation/native';
|
|
98
|
+
|
|
99
|
+
export function BookingScreen() {
|
|
100
|
+
const route = useRoute<any>();
|
|
101
|
+
const id = route.params?.id;
|
|
102
|
+
const step = route.params?.step;
|
|
103
|
+
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Notes
|
|
109
|
+
|
|
110
|
+
- **Linking is required**: all path-based methods rely on `linking.config` to parse a path into navigation state.
|
|
111
|
+
- **Inside vs outside React tree**:
|
|
112
|
+
- if you pass a `navigation` object (local navigation), `navRef` is not required
|
|
113
|
+
- if you do not pass `navigation`, `navRef` must be set and ready
|
|
114
|
+
- **`popTo(path)` behavior**: tries to pop within the current stack when possible, otherwise navigates to the nearest existing parent and then to the leaf.
|
|
115
|
+
- **URL helpers**:
|
|
116
|
+
- `build(route, params?)` replaces `:param` tokens in `route.path` and returns a **branded** `BuiltPath` tied to the route definition.
|
|
117
|
+
- `query(builtPath, query)` merges with existing query and drops empty values; returns `BuiltPath` again.
|
|
118
|
+
- `QueryOptions`: `{ encode?: boolean; nested?: 'json'; debug?: boolean; nullable?: boolean }`
|
|
119
|
+
- **Validation (optional)**:
|
|
120
|
+
- By default, the service validates using `route.paramsSchema` / `route.querySchema` if present (any schema with `safeParse()`).
|
|
121
|
+
- Validation is invoked inside `build()` and `query()` (when a route can be recovered from the branded `BuiltPath`).
|
|
122
|
+
- In **strict mode** (`strict=true`) validation failures throw; in non-strict mode they only call `onError` and log warnings.
|
|
123
|
+
- **Errors**: navigation methods do not throw for missing `linking`/`navRef` (they log warnings). Validation errors throw only when `strict=true`.
|
|
124
|
+
|
|
125
|
+
## Sources
|
|
126
|
+
|
|
127
|
+
- [`service`](./service.js)
|
|
128
|
+
- [`api`](./api.js)
|
|
129
|
+
- [`chain-builder`](./chain-builder.js)
|
|
130
|
+
- [`types`](./types.js)
|
|
131
|
+
- [`index`](./index.js)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Navigation from './service';
|
|
2
|
+
/**
|
|
3
|
+
* Configure the global Navigation service.
|
|
4
|
+
*/
|
|
5
|
+
export default function configureNavigation({ ref, linking, strict = false, onError }) {
|
|
6
|
+
Navigation.navRef = ref;
|
|
7
|
+
Navigation.linkingConfig = linking;
|
|
8
|
+
Navigation.strict = strict;
|
|
9
|
+
if (onError)
|
|
10
|
+
Navigation.onError = onError;
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NavigationProp } from '@react-navigation/native';
|
|
2
|
+
import type { BuiltPath, QueryOptions, RouteDef, RouteQuery } from '../../config/internal';
|
|
3
|
+
declare class ChainBuilder<R extends RouteDef<any, any>> {
|
|
4
|
+
private path;
|
|
5
|
+
private navigation;
|
|
6
|
+
private queryFn;
|
|
7
|
+
constructor(path: BuiltPath<R>, navigation: NavigationProp<any>, queryFn: <RR extends RouteDef<any, any>>(url: BuiltPath<RR>, q?: any, opts?: QueryOptions) => BuiltPath<RR>);
|
|
8
|
+
query(...args: RouteQuery<R> extends undefined ? [q?: undefined, opts?: QueryOptions] : [q: RouteQuery<R>, opts?: QueryOptions]): this;
|
|
9
|
+
value(): BuiltPath<R>;
|
|
10
|
+
navigate(): void;
|
|
11
|
+
push(): void;
|
|
12
|
+
replace(): void;
|
|
13
|
+
popTo(): void;
|
|
14
|
+
reset(): void;
|
|
15
|
+
}
|
|
16
|
+
export default ChainBuilder;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Navigation from './service';
|
|
2
|
+
class ChainBuilder {
|
|
3
|
+
constructor(path, navigation, queryFn) {
|
|
4
|
+
this.path = path;
|
|
5
|
+
this.navigation = navigation;
|
|
6
|
+
this.queryFn = queryFn;
|
|
7
|
+
}
|
|
8
|
+
query(...args) {
|
|
9
|
+
this.path = this.queryFn(this.path, args[0], args[1]);
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
value() {
|
|
13
|
+
return this.path;
|
|
14
|
+
}
|
|
15
|
+
navigate() {
|
|
16
|
+
Navigation.navigate(this.path, this.navigation);
|
|
17
|
+
}
|
|
18
|
+
push() {
|
|
19
|
+
Navigation.push(this.path);
|
|
20
|
+
}
|
|
21
|
+
replace() {
|
|
22
|
+
Navigation.replace(this.path);
|
|
23
|
+
}
|
|
24
|
+
popTo() {
|
|
25
|
+
Navigation.popTo(this.path, this.navigation);
|
|
26
|
+
}
|
|
27
|
+
reset() {
|
|
28
|
+
Navigation.reset(this.path);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export default ChainBuilder;
|