@idealyst/navigation 1.0.24 → 1.0.25
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 +3 -3
- package/src/context/NavigatorContext.native.tsx +50 -50
- package/src/context/NavigatorContext.web.tsx +36 -36
- package/src/context/index.native.ts +1 -1
- package/src/context/index.ts +1 -1
- package/src/context/index.web.ts +1 -1
- package/src/context/types.ts +12 -12
- package/src/examples/ExampleDrawerRouter.tsx +158 -158
- package/src/examples/ExampleStackRouter.tsx +244 -244
- package/src/examples/ExampleTabRouter.tsx +156 -156
- package/src/examples/highContrastThemes.ts +582 -582
- package/src/examples/index.ts +2 -2
- package/src/examples/unistyles.ts +83 -83
- package/src/index.ts +4 -4
- package/src/layouts/GeneralLayout/GeneralLayout.styles.ts +55 -55
- package/src/layouts/GeneralLayout/GeneralLayout.tsx +144 -144
- package/src/layouts/GeneralLayout/index.ts +2 -2
- package/src/layouts/GeneralLayout/types.ts +98 -98
- package/src/routing/index.native.tsx +1 -1
- package/src/routing/index.ts +1 -1
- package/src/routing/index.web.tsx +1 -1
- package/src/routing/router.native.tsx +89 -89
- package/src/routing/router.web.tsx +73 -73
- package/src/routing/types.ts +14 -14
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface SidebarConfig {
|
|
4
|
-
/**
|
|
5
|
-
* Whether the sidebar is enabled
|
|
6
|
-
*/
|
|
7
|
-
enabled?: boolean;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Whether the sidebar is initially expanded
|
|
11
|
-
*/
|
|
12
|
-
initiallyExpanded?: boolean;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Width of the sidebar when expanded
|
|
16
|
-
*/
|
|
17
|
-
expandedWidth?: number;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Width of the sidebar when collapsed
|
|
21
|
-
*/
|
|
22
|
-
collapsedWidth?: number;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Whether the sidebar can be collapsed
|
|
26
|
-
*/
|
|
27
|
-
collapsible?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Position of the sidebar
|
|
31
|
-
*/
|
|
32
|
-
position?: 'left' | 'right';
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Content to display in the sidebar
|
|
36
|
-
*/
|
|
37
|
-
content?: ReactNode;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Custom styles for the sidebar
|
|
41
|
-
*/
|
|
42
|
-
style?: any;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface HeaderConfig {
|
|
46
|
-
/**
|
|
47
|
-
* Whether the header is enabled
|
|
48
|
-
*/
|
|
49
|
-
enabled?: boolean;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Height of the header
|
|
53
|
-
*/
|
|
54
|
-
height?: number;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Content to display in the header
|
|
58
|
-
*/
|
|
59
|
-
content?: ReactNode;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Custom styles for the header
|
|
63
|
-
*/
|
|
64
|
-
style?: any;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface GeneralLayoutProps {
|
|
68
|
-
/**
|
|
69
|
-
* The main content to display
|
|
70
|
-
*/
|
|
71
|
-
children?: ReactNode;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Sidebar configuration
|
|
75
|
-
*/
|
|
76
|
-
sidebar?: SidebarConfig;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Header configuration
|
|
80
|
-
*/
|
|
81
|
-
header?: HeaderConfig;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Additional styles for the layout container
|
|
85
|
-
*/
|
|
86
|
-
style?: any;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Test ID for testing
|
|
90
|
-
*/
|
|
91
|
-
testID?: string;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface GeneralLayoutState {
|
|
95
|
-
/**
|
|
96
|
-
* Whether the sidebar is currently expanded
|
|
97
|
-
*/
|
|
98
|
-
isSidebarExpanded: boolean;
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface SidebarConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the sidebar is enabled
|
|
6
|
+
*/
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Whether the sidebar is initially expanded
|
|
11
|
+
*/
|
|
12
|
+
initiallyExpanded?: boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Width of the sidebar when expanded
|
|
16
|
+
*/
|
|
17
|
+
expandedWidth?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Width of the sidebar when collapsed
|
|
21
|
+
*/
|
|
22
|
+
collapsedWidth?: number;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Whether the sidebar can be collapsed
|
|
26
|
+
*/
|
|
27
|
+
collapsible?: boolean;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Position of the sidebar
|
|
31
|
+
*/
|
|
32
|
+
position?: 'left' | 'right';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Content to display in the sidebar
|
|
36
|
+
*/
|
|
37
|
+
content?: ReactNode;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Custom styles for the sidebar
|
|
41
|
+
*/
|
|
42
|
+
style?: any;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface HeaderConfig {
|
|
46
|
+
/**
|
|
47
|
+
* Whether the header is enabled
|
|
48
|
+
*/
|
|
49
|
+
enabled?: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Height of the header
|
|
53
|
+
*/
|
|
54
|
+
height?: number;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Content to display in the header
|
|
58
|
+
*/
|
|
59
|
+
content?: ReactNode;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Custom styles for the header
|
|
63
|
+
*/
|
|
64
|
+
style?: any;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface GeneralLayoutProps {
|
|
68
|
+
/**
|
|
69
|
+
* The main content to display
|
|
70
|
+
*/
|
|
71
|
+
children?: ReactNode;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Sidebar configuration
|
|
75
|
+
*/
|
|
76
|
+
sidebar?: SidebarConfig;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Header configuration
|
|
80
|
+
*/
|
|
81
|
+
header?: HeaderConfig;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Additional styles for the layout container
|
|
85
|
+
*/
|
|
86
|
+
style?: any;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Test ID for testing
|
|
90
|
+
*/
|
|
91
|
+
testID?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface GeneralLayoutState {
|
|
95
|
+
/**
|
|
96
|
+
* Whether the sidebar is currently expanded
|
|
97
|
+
*/
|
|
98
|
+
isSidebarExpanded: boolean;
|
|
99
99
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './router.native';
|
|
1
|
+
export * from './router.native';
|
|
2
2
|
export * from './types';
|
package/src/routing/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './router.web';
|
|
1
|
+
export * from './router.web';
|
|
2
2
|
export * from './types';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './router.web';
|
|
1
|
+
export * from './router.web';
|
|
2
2
|
export * from './types';
|
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
4
|
-
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
|
5
|
-
import { createDrawerNavigator } from "@react-navigation/drawer";
|
|
6
|
-
|
|
7
|
-
import { RouteParam } from "./types"
|
|
8
|
-
import { TypedNavigator } from "@react-navigation/native";
|
|
9
|
-
|
|
10
|
-
export const buildRouter = (routeParam: RouteParam, path: string = '') => {
|
|
11
|
-
return () => buildNativeRouter(routeParam, path)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Create the router supporting React Navigation
|
|
16
|
-
* @param routeParam
|
|
17
|
-
* @param path
|
|
18
|
-
* @param LastNavigator
|
|
19
|
-
* @returns
|
|
20
|
-
*/
|
|
21
|
-
const buildNativeRouter = (routeParam: RouteParam, path: string = '', LastNavigator?: TypedNavigator<any>): React.ReactElement => {
|
|
22
|
-
const nextPath = (routeParam.path ? path + routeParam.path : path) || '';
|
|
23
|
-
const type = routeParam.layout?.type;
|
|
24
|
-
console.log('Registered routes', nextPath, routeParam.routes);
|
|
25
|
-
switch (type) {
|
|
26
|
-
case 'stack':
|
|
27
|
-
const Stack = createNativeStackNavigator();
|
|
28
|
-
return (
|
|
29
|
-
<Stack.Navigator
|
|
30
|
-
screenOptions={{
|
|
31
|
-
// Disable screen optimization to ensure theme updates
|
|
32
|
-
freezeOnBlur: false,
|
|
33
|
-
}}
|
|
34
|
-
>
|
|
35
|
-
<Stack.Screen name={nextPath} component={routeParam.component} />
|
|
36
|
-
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, Stack))}
|
|
37
|
-
</Stack.Navigator>
|
|
38
|
-
)
|
|
39
|
-
case 'tab':
|
|
40
|
-
const Tab = createBottomTabNavigator();
|
|
41
|
-
return (
|
|
42
|
-
<Tab.Navigator
|
|
43
|
-
screenOptions={{
|
|
44
|
-
// Disable screen optimization to ensure theme updates
|
|
45
|
-
lazy: false,
|
|
46
|
-
freezeOnBlur: false,
|
|
47
|
-
}}
|
|
48
|
-
>
|
|
49
|
-
<Tab.Screen name={nextPath} component={routeParam.component} />
|
|
50
|
-
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, Tab))}
|
|
51
|
-
</Tab.Navigator>
|
|
52
|
-
)
|
|
53
|
-
case 'drawer':
|
|
54
|
-
const Drawer = createDrawerNavigator();
|
|
55
|
-
return (
|
|
56
|
-
<Drawer.Navigator
|
|
57
|
-
screenOptions={{
|
|
58
|
-
// Disable screen optimization to ensure theme updates
|
|
59
|
-
lazy: false,
|
|
60
|
-
freezeOnBlur: false,
|
|
61
|
-
}}
|
|
62
|
-
>
|
|
63
|
-
<Drawer.Screen name={nextPath} component={routeParam.component} />
|
|
64
|
-
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, Drawer))}
|
|
65
|
-
</Drawer.Navigator>
|
|
66
|
-
)
|
|
67
|
-
case 'modal':
|
|
68
|
-
if (!LastNavigator) {
|
|
69
|
-
throw new Error('LastNavigator is required for modal layout');
|
|
70
|
-
}
|
|
71
|
-
return (
|
|
72
|
-
<>
|
|
73
|
-
<LastNavigator.Screen options={{ headerShown: false, presentation: 'modal' }} name={nextPath} component={routeParam.component} />
|
|
74
|
-
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, LastNavigator))}
|
|
75
|
-
</>
|
|
76
|
-
)
|
|
77
|
-
case undefined:
|
|
78
|
-
if (!LastNavigator) {
|
|
79
|
-
throw new Error('LastNavigator is required for undefined layout');
|
|
80
|
-
}
|
|
81
|
-
return (
|
|
82
|
-
<>
|
|
83
|
-
<LastNavigator.Screen name={nextPath} component={routeParam.component} />
|
|
84
|
-
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, LastNavigator))}
|
|
85
|
-
</>
|
|
86
|
-
)
|
|
87
|
-
default:
|
|
88
|
-
throw new Error(`Unknown layout type: ${type}`);
|
|
89
|
-
}
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
4
|
+
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
|
5
|
+
import { createDrawerNavigator } from "@react-navigation/drawer";
|
|
6
|
+
|
|
7
|
+
import { RouteParam } from "./types"
|
|
8
|
+
import { TypedNavigator } from "@react-navigation/native";
|
|
9
|
+
|
|
10
|
+
export const buildRouter = (routeParam: RouteParam, path: string = '') => {
|
|
11
|
+
return () => buildNativeRouter(routeParam, path)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create the router supporting React Navigation
|
|
16
|
+
* @param routeParam
|
|
17
|
+
* @param path
|
|
18
|
+
* @param LastNavigator
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
const buildNativeRouter = (routeParam: RouteParam, path: string = '', LastNavigator?: TypedNavigator<any>): React.ReactElement => {
|
|
22
|
+
const nextPath = (routeParam.path ? path + routeParam.path : path) || '';
|
|
23
|
+
const type = routeParam.layout?.type;
|
|
24
|
+
console.log('Registered routes', nextPath, routeParam.routes);
|
|
25
|
+
switch (type) {
|
|
26
|
+
case 'stack':
|
|
27
|
+
const Stack = createNativeStackNavigator();
|
|
28
|
+
return (
|
|
29
|
+
<Stack.Navigator
|
|
30
|
+
screenOptions={{
|
|
31
|
+
// Disable screen optimization to ensure theme updates
|
|
32
|
+
freezeOnBlur: false,
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
<Stack.Screen name={nextPath} component={routeParam.component} />
|
|
36
|
+
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, Stack))}
|
|
37
|
+
</Stack.Navigator>
|
|
38
|
+
)
|
|
39
|
+
case 'tab':
|
|
40
|
+
const Tab = createBottomTabNavigator();
|
|
41
|
+
return (
|
|
42
|
+
<Tab.Navigator
|
|
43
|
+
screenOptions={{
|
|
44
|
+
// Disable screen optimization to ensure theme updates
|
|
45
|
+
lazy: false,
|
|
46
|
+
freezeOnBlur: false,
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<Tab.Screen name={nextPath} component={routeParam.component} />
|
|
50
|
+
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, Tab))}
|
|
51
|
+
</Tab.Navigator>
|
|
52
|
+
)
|
|
53
|
+
case 'drawer':
|
|
54
|
+
const Drawer = createDrawerNavigator();
|
|
55
|
+
return (
|
|
56
|
+
<Drawer.Navigator
|
|
57
|
+
screenOptions={{
|
|
58
|
+
// Disable screen optimization to ensure theme updates
|
|
59
|
+
lazy: false,
|
|
60
|
+
freezeOnBlur: false,
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<Drawer.Screen name={nextPath} component={routeParam.component} />
|
|
64
|
+
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, Drawer))}
|
|
65
|
+
</Drawer.Navigator>
|
|
66
|
+
)
|
|
67
|
+
case 'modal':
|
|
68
|
+
if (!LastNavigator) {
|
|
69
|
+
throw new Error('LastNavigator is required for modal layout');
|
|
70
|
+
}
|
|
71
|
+
return (
|
|
72
|
+
<>
|
|
73
|
+
<LastNavigator.Screen options={{ headerShown: false, presentation: 'modal' }} name={nextPath} component={routeParam.component} />
|
|
74
|
+
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, LastNavigator))}
|
|
75
|
+
</>
|
|
76
|
+
)
|
|
77
|
+
case undefined:
|
|
78
|
+
if (!LastNavigator) {
|
|
79
|
+
throw new Error('LastNavigator is required for undefined layout');
|
|
80
|
+
}
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
<LastNavigator.Screen name={nextPath} component={routeParam.component} />
|
|
84
|
+
{routeParam.routes?.map((route) => buildNativeRouter(route, nextPath, LastNavigator))}
|
|
85
|
+
</>
|
|
86
|
+
)
|
|
87
|
+
default:
|
|
88
|
+
throw new Error(`Unknown layout type: ${type}`);
|
|
89
|
+
}
|
|
90
90
|
}
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Routes, Route, Outlet } from "react-router-dom";
|
|
3
|
-
import { RouteParam } from "./types";
|
|
4
|
-
|
|
5
|
-
export const buildRouter = (routeParam: RouteParam, path: string = '') => {
|
|
6
|
-
return () => (
|
|
7
|
-
<Routes>
|
|
8
|
-
{buildWebRoutes(routeParam, path)}
|
|
9
|
-
</Routes>
|
|
10
|
-
);
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Create React Router routes from RouteParam configuration
|
|
15
|
-
* @param routeParam The route parameter configuration
|
|
16
|
-
* @param parentPath The parent path for nested routes
|
|
17
|
-
* @returns Array of React Router Route elements
|
|
18
|
-
*/
|
|
19
|
-
const buildWebRoutes = (routeParam: RouteParam, parentPath: string = ''): React.ReactElement[] => {
|
|
20
|
-
const routes: React.ReactElement[] = [];
|
|
21
|
-
const currentPath = routeParam.path ? `${parentPath}${routeParam.path}` : parentPath;
|
|
22
|
-
|
|
23
|
-
// Handle layout wrapping
|
|
24
|
-
const LayoutComponent = routeParam.layout?.component;
|
|
25
|
-
const RouteComponent = routeParam.component;
|
|
26
|
-
|
|
27
|
-
if (LayoutComponent && routeParam.routes) {
|
|
28
|
-
// Create a wrapper component that renders the layout with Outlet
|
|
29
|
-
const LayoutWrapper: React.FC = () => (
|
|
30
|
-
<LayoutComponent>
|
|
31
|
-
<Outlet />
|
|
32
|
-
</LayoutComponent>
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
// Create parent route with layout
|
|
36
|
-
const layoutRoute = (
|
|
37
|
-
<Route
|
|
38
|
-
key={`layout-${currentPath || 'root'}`}
|
|
39
|
-
path={currentPath || '/'}
|
|
40
|
-
element={<LayoutWrapper />}
|
|
41
|
-
>
|
|
42
|
-
{/* Add index route for the main component */}
|
|
43
|
-
<Route
|
|
44
|
-
index
|
|
45
|
-
element={<RouteComponent />}
|
|
46
|
-
/>
|
|
47
|
-
{/* Add nested routes */}
|
|
48
|
-
{routeParam.routes.reduce((acc, nestedRoute) => {
|
|
49
|
-
return acc.concat(buildWebRoutes(nestedRoute, currentPath));
|
|
50
|
-
}, [] as React.ReactElement[])}
|
|
51
|
-
</Route>
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
routes.push(layoutRoute);
|
|
55
|
-
} else {
|
|
56
|
-
// Simple route without layout
|
|
57
|
-
routes.push(
|
|
58
|
-
<Route
|
|
59
|
-
key={currentPath || 'root'}
|
|
60
|
-
path={currentPath || '/'}
|
|
61
|
-
element={<RouteComponent />}
|
|
62
|
-
/>
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// Handle nested routes without layout
|
|
66
|
-
if (routeParam.routes) {
|
|
67
|
-
routeParam.routes.forEach(nestedRoute => {
|
|
68
|
-
routes.push(...buildWebRoutes(nestedRoute, currentPath));
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return routes;
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Routes, Route, Outlet } from "react-router-dom";
|
|
3
|
+
import { RouteParam } from "./types";
|
|
4
|
+
|
|
5
|
+
export const buildRouter = (routeParam: RouteParam, path: string = '') => {
|
|
6
|
+
return () => (
|
|
7
|
+
<Routes>
|
|
8
|
+
{buildWebRoutes(routeParam, path)}
|
|
9
|
+
</Routes>
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create React Router routes from RouteParam configuration
|
|
15
|
+
* @param routeParam The route parameter configuration
|
|
16
|
+
* @param parentPath The parent path for nested routes
|
|
17
|
+
* @returns Array of React Router Route elements
|
|
18
|
+
*/
|
|
19
|
+
const buildWebRoutes = (routeParam: RouteParam, parentPath: string = ''): React.ReactElement[] => {
|
|
20
|
+
const routes: React.ReactElement[] = [];
|
|
21
|
+
const currentPath = routeParam.path ? `${parentPath}${routeParam.path}` : parentPath;
|
|
22
|
+
|
|
23
|
+
// Handle layout wrapping
|
|
24
|
+
const LayoutComponent = routeParam.layout?.component;
|
|
25
|
+
const RouteComponent = routeParam.component;
|
|
26
|
+
|
|
27
|
+
if (LayoutComponent && routeParam.routes) {
|
|
28
|
+
// Create a wrapper component that renders the layout with Outlet
|
|
29
|
+
const LayoutWrapper: React.FC = () => (
|
|
30
|
+
<LayoutComponent>
|
|
31
|
+
<Outlet />
|
|
32
|
+
</LayoutComponent>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Create parent route with layout
|
|
36
|
+
const layoutRoute = (
|
|
37
|
+
<Route
|
|
38
|
+
key={`layout-${currentPath || 'root'}`}
|
|
39
|
+
path={currentPath || '/'}
|
|
40
|
+
element={<LayoutWrapper />}
|
|
41
|
+
>
|
|
42
|
+
{/* Add index route for the main component */}
|
|
43
|
+
<Route
|
|
44
|
+
index
|
|
45
|
+
element={<RouteComponent />}
|
|
46
|
+
/>
|
|
47
|
+
{/* Add nested routes */}
|
|
48
|
+
{routeParam.routes.reduce((acc, nestedRoute) => {
|
|
49
|
+
return acc.concat(buildWebRoutes(nestedRoute, currentPath));
|
|
50
|
+
}, [] as React.ReactElement[])}
|
|
51
|
+
</Route>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
routes.push(layoutRoute);
|
|
55
|
+
} else {
|
|
56
|
+
// Simple route without layout
|
|
57
|
+
routes.push(
|
|
58
|
+
<Route
|
|
59
|
+
key={currentPath || 'root'}
|
|
60
|
+
path={currentPath || '/'}
|
|
61
|
+
element={<RouteComponent />}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Handle nested routes without layout
|
|
66
|
+
if (routeParam.routes) {
|
|
67
|
+
routeParam.routes.forEach(nestedRoute => {
|
|
68
|
+
routes.push(...buildWebRoutes(nestedRoute, currentPath));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return routes;
|
|
74
74
|
};
|
package/src/routing/types.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
export type RouteParam = {
|
|
4
|
-
path?: string;
|
|
5
|
-
routes?: RouteParam[];
|
|
6
|
-
component: React.ComponentType;
|
|
7
|
-
layout?: LayoutParam;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type LayoutType = 'stack' | 'tab' | 'drawer' | 'modal';
|
|
11
|
-
|
|
12
|
-
export type LayoutParam = {
|
|
13
|
-
type: LayoutType;
|
|
14
|
-
component?: React.ComponentType<{ children?: React.ReactNode }>;
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export type RouteParam = {
|
|
4
|
+
path?: string;
|
|
5
|
+
routes?: RouteParam[];
|
|
6
|
+
component: React.ComponentType;
|
|
7
|
+
layout?: LayoutParam;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type LayoutType = 'stack' | 'tab' | 'drawer' | 'modal';
|
|
11
|
+
|
|
12
|
+
export type LayoutParam = {
|
|
13
|
+
type: LayoutType;
|
|
14
|
+
component?: React.ComponentType<{ children?: React.ReactNode }>;
|
|
15
15
|
}
|