@sigmela/router 0.2.7 → 0.3.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.
Files changed (39) hide show
  1. package/README.md +41 -0
  2. package/lib/module/Drawer/Drawer.js +250 -0
  3. package/lib/module/Drawer/DrawerContext.js +4 -0
  4. package/lib/module/Drawer/DrawerIcon.web.js +47 -0
  5. package/lib/module/Drawer/RenderDrawer.native.js +241 -0
  6. package/lib/module/Drawer/RenderDrawer.web.js +197 -0
  7. package/lib/module/Drawer/useDrawer.js +11 -0
  8. package/lib/module/Navigation.js +4 -2
  9. package/lib/module/NavigationStack.js +22 -5
  10. package/lib/module/Router.js +214 -60
  11. package/lib/module/RouterContext.js +1 -1
  12. package/lib/module/ScreenStack/ScreenStack.web.js +78 -12
  13. package/lib/module/ScreenStackItem/ScreenStackItem.js +7 -7
  14. package/lib/module/ScreenStackItem/ScreenStackItem.web.js +65 -6
  15. package/lib/module/ScreenStackSheetItem/ScreenStackSheetItem.native.js +4 -5
  16. package/lib/module/SplitView/RenderSplitView.web.js +5 -7
  17. package/lib/module/SplitView/SplitView.js +10 -2
  18. package/lib/module/StackRenderer.js +10 -4
  19. package/lib/module/TabBar/RenderTabBar.native.js +10 -9
  20. package/lib/module/TabBar/RenderTabBar.web.js +25 -2
  21. package/lib/module/TabBar/TabBar.js +8 -1
  22. package/lib/module/TabBar/TabIcon.web.js +12 -7
  23. package/lib/module/index.js +2 -0
  24. package/lib/module/styles.css +247 -106
  25. package/lib/typescript/src/Drawer/Drawer.d.ts +100 -0
  26. package/lib/typescript/src/Drawer/DrawerContext.d.ts +3 -0
  27. package/lib/typescript/src/Drawer/DrawerIcon.web.d.ts +7 -0
  28. package/lib/typescript/src/Drawer/RenderDrawer.native.d.ts +8 -0
  29. package/lib/typescript/src/Drawer/RenderDrawer.web.d.ts +8 -0
  30. package/lib/typescript/src/Drawer/useDrawer.d.ts +2 -0
  31. package/lib/typescript/src/NavigationStack.d.ts +6 -4
  32. package/lib/typescript/src/Router.d.ts +13 -0
  33. package/lib/typescript/src/ScreenStack/ScreenStackContext.d.ts +1 -1
  34. package/lib/typescript/src/ScreenStack/animationHelpers.d.ts +1 -1
  35. package/lib/typescript/src/SplitView/SplitView.d.ts +2 -0
  36. package/lib/typescript/src/TabBar/TabBar.d.ts +1 -0
  37. package/lib/typescript/src/index.d.ts +5 -0
  38. package/lib/typescript/src/types.d.ts +10 -1
  39. package/package.json +15 -4
@@ -0,0 +1,100 @@
1
+ import type { ImageSourcePropType } from 'react-native';
2
+ import { NavigationStack } from '../NavigationStack';
3
+ import type { ComponentType } from 'react';
4
+ import React from 'react';
5
+ import type { NavigationNode, NodeChild, NodeRoute } from '../navigationNode';
6
+ import type { PlatformIcon } from 'react-native-screens';
7
+ type LegacyIOSIconShape = {
8
+ sfSymbolName: string;
9
+ } | {
10
+ imageSource: ImageSourcePropType;
11
+ } | {
12
+ templateSource: ImageSourcePropType;
13
+ };
14
+ type ExtendedIcon = ImageSourcePropType | LegacyIOSIconShape | PlatformIcon;
15
+ export type DrawerItemInternal = {
16
+ tabKey: string;
17
+ title?: string;
18
+ icon?: ExtendedIcon;
19
+ selectedIcon?: ExtendedIcon;
20
+ badgeValue?: string;
21
+ tabPrefix?: string;
22
+ };
23
+ export type DrawerProps = {
24
+ onItemPress: (index: number) => void;
25
+ items: DrawerItemInternal[];
26
+ activeIndex: number;
27
+ isOpen: boolean;
28
+ onClose: () => void;
29
+ };
30
+ export type DrawerDescriptor = {
31
+ renderer?: ComponentType<DrawerProps>;
32
+ };
33
+ type DrawerItemConfig = Omit<DrawerItemInternal, 'tabKey'> & {
34
+ stack?: NavigationStack;
35
+ node?: NavigationNode;
36
+ screen?: React.ComponentType<any>;
37
+ prefix?: string;
38
+ component?: ComponentType<DrawerProps>;
39
+ };
40
+ type DrawerOptions = {
41
+ component?: ComponentType<DrawerProps>;
42
+ initialIndex?: number;
43
+ width?: number;
44
+ };
45
+ export declare class Drawer implements NavigationNode {
46
+ private readonly drawerId;
47
+ screens: Record<string, React.ComponentType<any>>;
48
+ stacks: Record<string, NavigationStack>;
49
+ nodes: Record<string, NavigationNode>;
50
+ readonly width: number;
51
+ private listeners;
52
+ private openListeners;
53
+ private state;
54
+ constructor(options?: DrawerOptions);
55
+ getId(): string;
56
+ addTab(tab: Omit<DrawerItemConfig, 'tabKey'> & {
57
+ key: string;
58
+ }): Drawer;
59
+ setBadge(tabIndex: number, badge: string | null): void;
60
+ setTabBarConfig(config: Partial<{
61
+ component?: ComponentType<DrawerProps>;
62
+ }>): void;
63
+ onIndexChange(index: number): void;
64
+ open(): void;
65
+ close(): void;
66
+ toggle(): void;
67
+ getIsOpen(): boolean;
68
+ subscribeOpenState(listener: (isOpen: boolean) => void): () => void;
69
+ private notifyOpenListeners;
70
+ getState: () => {
71
+ tabs: DrawerItemInternal[];
72
+ config: {
73
+ component?: ComponentType<DrawerProps>;
74
+ };
75
+ index: number;
76
+ isOpen: boolean;
77
+ };
78
+ private setState;
79
+ private notifyListeners;
80
+ subscribe(listener: () => void): () => void;
81
+ getTabs(): DrawerItemInternal[];
82
+ getInitialIndex(): number;
83
+ getActiveChildId(): string | undefined;
84
+ switchToRoute(routeId: string): void;
85
+ hasRoute(routeId: string): boolean;
86
+ setActiveChildByRoute(routeId: string): void;
87
+ getNodeRoutes(): NodeRoute[];
88
+ getNodeChildren(): NodeChild[];
89
+ getRenderer(): React.ComponentType<any>;
90
+ seed(): {
91
+ routeId: string;
92
+ params?: Record<string, unknown>;
93
+ path: string;
94
+ stackId?: string;
95
+ } | null;
96
+ private findTabIndexByRoute;
97
+ private nodeHasRoute;
98
+ }
99
+ export {};
100
+ //# sourceMappingURL=Drawer.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { Drawer } from './Drawer';
2
+ export declare const DrawerContext: import("react").Context<Drawer | null>;
3
+ //# sourceMappingURL=DrawerContext.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { type ImageSourcePropType } from 'react-native';
2
+ export interface DrawerIconProps {
3
+ source: ImageSourcePropType;
4
+ tintColor?: string;
5
+ }
6
+ export declare const DrawerIcon: import("react").MemoExoticComponent<({ source, tintColor }: DrawerIconProps) => import("react/jsx-runtime").JSX.Element>;
7
+ //# sourceMappingURL=DrawerIcon.web.d.ts.map
@@ -0,0 +1,8 @@
1
+ import type { Drawer } from './Drawer';
2
+ import type { NavigationAppearance } from '../types';
3
+ export interface RenderDrawerProps {
4
+ drawer: Drawer;
5
+ appearance?: NavigationAppearance;
6
+ }
7
+ export declare const RenderDrawer: import("react").NamedExoticComponent<RenderDrawerProps>;
8
+ //# sourceMappingURL=RenderDrawer.native.d.ts.map
@@ -0,0 +1,8 @@
1
+ import type { NavigationAppearance } from '../types';
2
+ import type { Drawer } from './Drawer';
3
+ export interface RenderDrawerProps {
4
+ drawer: Drawer;
5
+ appearance?: NavigationAppearance;
6
+ }
7
+ export declare const RenderDrawer: import("react").NamedExoticComponent<RenderDrawerProps>;
8
+ //# sourceMappingURL=RenderDrawer.web.d.ts.map
@@ -0,0 +1,2 @@
1
+ export declare const useDrawer: () => import("./Drawer").Drawer;
2
+ //# sourceMappingURL=useDrawer.d.ts.map
@@ -1,4 +1,4 @@
1
- import type { ScreenOptions } from './types';
1
+ import type { ScreenOptions, NavigationStackOptions } from './types';
2
2
  import React from 'react';
3
3
  import { type MixedComponent } from './createController';
4
4
  import type { NavigationNode, NodeRoute, NodeChild } from './navigationNode';
@@ -10,11 +10,13 @@ export declare class NavigationStack implements NavigationNode {
10
10
  private readonly children;
11
11
  private readonly defaultOptions;
12
12
  private readonly debugEnabled;
13
+ private readonly provider;
14
+ private _cachedRenderer;
13
15
  constructor();
14
16
  constructor(id: string);
15
- constructor(defaultOptions: ScreenOptions);
16
- constructor(id: string, defaultOptions: ScreenOptions);
17
- constructor(id: string, defaultOptions: ScreenOptions, debug: boolean);
17
+ constructor(defaultOptions: NavigationStackOptions);
18
+ constructor(id: string, defaultOptions: NavigationStackOptions);
19
+ constructor(id: string, defaultOptions: NavigationStackOptions, debug: boolean);
18
20
  private log;
19
21
  getId(): string;
20
22
  addScreen(pathPattern: string, mixedComponent: MixedComponent | NavigationNode, options?: ScreenOptions): NavigationStack;
@@ -26,14 +26,22 @@ export declare class Router {
26
26
  private stackById;
27
27
  private routeById;
28
28
  private stackActivators;
29
+ private compiledRouteById;
29
30
  private stackHistories;
30
31
  private activeRoute;
32
+ private activeRouteListeners;
31
33
  private rootListeners;
32
34
  private rootTransition?;
33
35
  private suppressRootTransitionOnNextRead;
34
36
  private lastBrowserIndex;
35
37
  private suppressHistorySyncCount;
38
+ private abortController?;
36
39
  private navigationToken;
40
+ private lastParsedPath;
41
+ private lastParsedResult;
42
+ private lastMatchedPathname;
43
+ private lastMatchedQuery;
44
+ private lastMatchedResult;
37
45
  constructor(config: RouterConfig);
38
46
  isDebugEnabled(): boolean;
39
47
  isStackBeingDismissed(stackId?: string): boolean;
@@ -61,6 +69,7 @@ export declare class Router {
61
69
  dismiss: () => void;
62
70
  getState: () => RouterState;
63
71
  subscribe(listener: Listener): () => void;
72
+ subscribeActiveRoute: (listener: Listener) => (() => void);
64
73
  getStackHistory: (stackId?: string) => HistoryItem[];
65
74
  /**
66
75
  * Returns all history items in navigation order.
@@ -174,6 +183,7 @@ export declare class Router {
174
183
  private activateStack;
175
184
  private ensureStackHasSeed;
176
185
  private updateActiveRouteFromStack;
186
+ private emitDepth;
177
187
  private emit;
178
188
  private getTopOfStack;
179
189
  private findExistingRoute;
@@ -193,6 +203,7 @@ export declare class Router {
193
203
  private parsePath;
194
204
  private mergeOptions;
195
205
  private findStackById;
206
+ private getCompiledRoute;
196
207
  private areShallowEqual;
197
208
  private matchQueryPattern;
198
209
  private isWebEnv;
@@ -210,6 +221,8 @@ export declare class Router {
210
221
  private buildUrlFromActiveRoute;
211
222
  private patchBrowserHistoryOnce;
212
223
  private setupBrowserHistory;
224
+ private destroyed;
225
+ destroy(): void;
213
226
  private syncUrlAfterInternalPop;
214
227
  private popFromActiveStack;
215
228
  private buildHistoryFromUrl;
@@ -1,7 +1,7 @@
1
1
  import type { ScreenStackItemPhase } from '../ScreenStackItem/ScreenStackItem.types';
2
2
  import type { TransitionStatus } from 'react-transition-state';
3
3
  export type PresentationTypeClass = 'push' | 'modal' | 'modal-right' | 'transparent-modal' | 'contained-modal' | 'contained-transparent-modal' | 'fullscreen-modal' | 'formsheet' | 'pagesheet' | 'sheet';
4
- export type AnimationType = 'push-enter' | 'push-exit' | 'push-background' | 'pop-enter' | 'pop-exit' | 'pop-background' | 'modal-enter' | 'modal-exit' | 'modal-right-enter' | 'modal-right-exit' | 'transparent-modal-enter' | 'transparent-modal-exit' | 'contained-modal-enter' | 'contained-modal-exit' | 'fullscreen-modal-enter' | 'fullscreen-modal-exit' | 'formsheet-enter' | 'formsheet-exit' | 'pagesheet-enter' | 'pagesheet-exit' | 'sheet-enter' | 'sheet-exit' | 'no-animate' | 'none';
4
+ export type AnimationType = 'push-enter' | 'push-exit' | 'push-background' | 'pop-enter' | 'pop-exit' | 'pop-background' | 'modal-enter' | 'modal-exit' | 'modal-right-enter' | 'modal-right-exit' | 'transparent-modal-enter' | 'transparent-modal-exit' | 'contained-modal-enter' | 'contained-modal-exit' | 'contained-transparent-modal-enter' | 'contained-transparent-modal-exit' | 'fullscreen-modal-enter' | 'fullscreen-modal-exit' | 'formsheet-enter' | 'formsheet-exit' | 'pagesheet-enter' | 'pagesheet-exit' | 'sheet-enter' | 'sheet-exit' | 'no-animate' | 'none';
5
5
  export type ScreenStackItemState = {
6
6
  presentationType: PresentationTypeClass;
7
7
  animationType: AnimationType;
@@ -1,6 +1,6 @@
1
1
  import type { StackPresentationTypes } from '../types';
2
2
  import type { PresentationTypeClass, AnimationType } from './ScreenStackContext';
3
3
  export declare function getPresentationTypeClass(presentation: StackPresentationTypes): PresentationTypeClass;
4
- export declare function getAnimationTypeForPresentation(presentation: StackPresentationTypes, isEntering: boolean, direction: 'forward' | 'back'): string;
4
+ export declare function getAnimationTypeForPresentation(presentation: StackPresentationTypes, isEntering: boolean, direction: 'forward' | 'back'): AnimationType;
5
5
  export declare function computeAnimationType(_key: string, isInStack: boolean, isTop: boolean, direction: 'forward' | 'back', presentation: StackPresentationTypes, isInitialPhase: boolean, animated?: boolean, isBulkRemoval?: boolean): AnimationType;
6
6
  //# sourceMappingURL=animationHelpers.d.ts.map
@@ -9,10 +9,12 @@ export type SplitViewOptions = {
9
9
  };
10
10
  export declare class SplitView implements NavigationNode {
11
11
  private readonly splitViewId;
12
+ private readonly secondaryWrapper;
12
13
  readonly primary: NavigationStack;
13
14
  readonly secondary: NavigationStack;
14
15
  readonly minWidth: number;
15
16
  readonly primaryMaxWidth: number;
17
+ private _cachedRenderer;
16
18
  constructor(options: SplitViewOptions);
17
19
  getId(): string;
18
20
  getNodeRoutes(): NodeRoute[];
@@ -64,6 +64,7 @@ export declare class TabBar implements NavigationNode {
64
64
  stacks: Record<string, NavigationStack>;
65
65
  nodes: Record<string, NavigationNode>;
66
66
  private listeners;
67
+ private _cachedRenderer;
67
68
  private state;
68
69
  constructor(options?: TabBarOptions);
69
70
  getId(): string;
@@ -2,13 +2,18 @@ export { useTabBar } from './TabBar/useTabBar';
2
2
  export { useTabBarHeight, TAB_BAR_HEIGHT } from './TabBar/useTabBarHeight';
3
3
  export { TabBar } from './TabBar/TabBar';
4
4
  export type { TabBarProps } from './TabBar/TabBar';
5
+ export { Drawer } from './Drawer/Drawer';
6
+ export type { DrawerProps } from './Drawer/Drawer';
7
+ export { useDrawer } from './Drawer/useDrawer';
5
8
  export { SplitView } from './SplitView/SplitView';
6
9
  export type { SplitViewOptions } from './SplitView/SplitView';
7
10
  export { useSplitView } from './SplitView/useSplitView';
8
11
  export type { NavigationAppearance } from './types';
12
+ export type { ScreenOptions, ActiveRoute, StackPresentationTypes, NavigationStackOptions, } from './types';
9
13
  export { Router } from './Router';
10
14
  export { Navigation } from './Navigation';
11
15
  export { createController } from './createController';
16
+ export type { Controller, ComponentWithController } from './createController';
12
17
  export { NavigationStack } from './NavigationStack';
13
18
  export type { HistoryItem } from './types';
14
19
  export { StackRenderer } from './StackRenderer';
@@ -43,6 +43,15 @@ export type ScreenOptions = Partial<Omit<RNSScreenProps, 'stackPresentation'>> &
43
43
  */
44
44
  maxWidth?: number;
45
45
  };
46
+ export type NavigationStackOptions = ScreenOptions & {
47
+ /**
48
+ * Optional React component to wrap the entire stack renderer.
49
+ * Useful for providing context (theme, auth, etc.) to all screens in the stack.
50
+ */
51
+ provider?: React.ComponentType<{
52
+ children: React.ReactNode;
53
+ }>;
54
+ };
46
55
  export type HistoryItem = {
47
56
  key: string;
48
57
  routeId: string;
@@ -50,7 +59,7 @@ export type HistoryItem = {
50
59
  options?: ScreenOptions;
51
60
  params?: Record<string, unknown>;
52
61
  query?: Record<string, unknown>;
53
- passProps?: any;
62
+ passProps?: Record<string, unknown>;
54
63
  stackId?: string;
55
64
  pattern?: string;
56
65
  path?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigmela/router",
3
- "version": "0.2.7",
3
+ "version": "0.3.0",
4
4
  "description": "React Native Router",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -47,7 +47,6 @@
47
47
  "React Native Router",
48
48
  "react-native-navigation",
49
49
  "react-native-router",
50
- "react-native-navigation",
51
50
  "react-native-screens",
52
51
  "react-native-bottom-tabs",
53
52
  "react-native-bottom-sheet"
@@ -88,16 +87,27 @@
88
87
  "react": "19.1.0",
89
88
  "react-native": "0.81.4",
90
89
  "react-native-builder-bob": "^0.40.13",
90
+ "react-native-reanimated": "^4.2.2",
91
91
  "react-native-screens": "^4.18.0",
92
+ "react-native-worklets": "^0.7.4",
92
93
  "release-it": "^19.0.4",
93
94
  "typescript": "^5.9.2"
94
95
  },
95
96
  "peerDependencies": {
96
97
  "@sigmela/native-sheet": ">=0.0.1",
97
98
  "react": "*",
98
- "react-native": "*",
99
+ "react-native": ">=0.72.0",
100
+ "react-native-reanimated": ">=3.0.0",
99
101
  "react-native-screens": ">=4.18.0"
100
102
  },
103
+ "peerDependenciesMeta": {
104
+ "@sigmela/native-sheet": {
105
+ "optional": true
106
+ },
107
+ "react-native-reanimated": {
108
+ "optional": true
109
+ }
110
+ },
101
111
  "workspaces": [
102
112
  "example"
103
113
  ],
@@ -106,7 +116,8 @@
106
116
  "preset": "react-native",
107
117
  "modulePathIgnorePatterns": [
108
118
  "<rootDir>/example/node_modules",
109
- "<rootDir>/lib/"
119
+ "<rootDir>/lib/",
120
+ "<rootDir>/.worktrees/"
110
121
  ],
111
122
  "transformIgnorePatterns": [
112
123
  "node_modules/(?!((jest-)?react-native|@react-native|react-native-screens|@sigmela/native-sheet|nanoid|query-string|decode-uri-component|split-on-first|filter-obj)/)"