@sigmela/router 0.3.2 → 0.3.4
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.
|
@@ -6,7 +6,7 @@ import { useRouter } from "../RouterContext.js";
|
|
|
6
6
|
import { ScreenStackItem } from 'react-native-screens';
|
|
7
7
|
import { Pressable, StyleSheet, View, Text } from 'react-native';
|
|
8
8
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
9
|
-
import { useCallback, useSyncExternalStore, memo, useEffect, useState, useMemo } from 'react';
|
|
9
|
+
import { useCallback, useSyncExternalStore, memo, useEffect, useState, useMemo, startTransition } from 'react';
|
|
10
10
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
|
|
11
11
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
12
|
const TIMING_CONFIG = {
|
|
@@ -19,9 +19,17 @@ const DrawerStackRenderer = /*#__PURE__*/memo(({
|
|
|
19
19
|
}) => {
|
|
20
20
|
const router = useRouter();
|
|
21
21
|
const stackId = stack.getId();
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const [history, setHistory] = useState(() => router.getStackHistory(stackId));
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const update = () => {
|
|
25
|
+
startTransition(() => {
|
|
26
|
+
setHistory(router.getStackHistory(stackId));
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const unsub = router.subscribeStack(stackId, update);
|
|
30
|
+
update();
|
|
31
|
+
return unsub;
|
|
32
|
+
}, [router, stackId]);
|
|
25
33
|
return /*#__PURE__*/_jsx(StackRenderer, {
|
|
26
34
|
appearance: appearance,
|
|
27
35
|
stackId: stackId,
|
|
@@ -116,9 +124,11 @@ export const RenderDrawer = /*#__PURE__*/memo(({
|
|
|
116
124
|
useEffect(() => {
|
|
117
125
|
const key = tabs[index]?.tabKey;
|
|
118
126
|
if (key) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
startTransition(() => {
|
|
128
|
+
setVisited(prev => prev[key] ? prev : {
|
|
129
|
+
...prev,
|
|
130
|
+
[key]: true
|
|
131
|
+
});
|
|
122
132
|
});
|
|
123
133
|
}
|
|
124
134
|
}, [tabs, index]);
|
package/lib/module/Navigation.js
CHANGED
|
@@ -4,13 +4,28 @@ import { ScreenStackItem } from "./ScreenStackItem/index.js";
|
|
|
4
4
|
import { RouterContext } from "./RouterContext.js";
|
|
5
5
|
import { ScreenStack } from "./ScreenStack/index.js";
|
|
6
6
|
import { StyleSheet } from 'react-native';
|
|
7
|
-
import {
|
|
7
|
+
import { memo, useEffect, useRef, useState, startTransition } from 'react';
|
|
8
8
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
9
|
const EMPTY_HISTORY = [];
|
|
10
10
|
function useStackHistory(router, stackId) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const [history, setHistory] = useState(() => stackId ? router.getStackHistory(stackId) : EMPTY_HISTORY);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!stackId) {
|
|
14
|
+
startTransition(() => {
|
|
15
|
+
setHistory(EMPTY_HISTORY);
|
|
16
|
+
});
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const update = () => {
|
|
20
|
+
startTransition(() => {
|
|
21
|
+
setHistory(router.getStackHistory(stackId));
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const unsub = router.subscribeStack(stackId, update);
|
|
25
|
+
update();
|
|
26
|
+
return unsub;
|
|
27
|
+
}, [router, stackId]);
|
|
28
|
+
return history;
|
|
14
29
|
}
|
|
15
30
|
|
|
16
31
|
/**
|
|
@@ -30,8 +45,10 @@ export const Navigation = /*#__PURE__*/memo(({
|
|
|
30
45
|
}));
|
|
31
46
|
useEffect(() => {
|
|
32
47
|
return router.subscribeRoot(() => {
|
|
33
|
-
|
|
34
|
-
|
|
48
|
+
startTransition(() => {
|
|
49
|
+
setRoot({
|
|
50
|
+
rootId: router.getRootStackId()
|
|
51
|
+
});
|
|
35
52
|
});
|
|
36
53
|
});
|
|
37
54
|
}, [router]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { memo,
|
|
3
|
+
import { memo, useEffect, useState, startTransition } from 'react';
|
|
4
4
|
import { ScreenStackItem } from "./ScreenStackItem/index.js";
|
|
5
5
|
import { ScreenStack } from "./ScreenStack/index.js";
|
|
6
6
|
import { useRouter } from "./RouterContext.js";
|
|
@@ -13,15 +13,19 @@ export const StackRenderer = /*#__PURE__*/memo(({
|
|
|
13
13
|
}) => {
|
|
14
14
|
const router = useRouter();
|
|
15
15
|
const hasHistoryProp = history != null;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const [internalHistory, setInternalHistory] = useState(() => hasHistoryProp ? history : router.getStackHistory(stackId));
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (hasHistoryProp) return;
|
|
19
|
+
const update = () => {
|
|
20
|
+
startTransition(() => {
|
|
21
|
+
setInternalHistory(router.getStackHistory(stackId));
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const unsub = router.subscribeStack(stackId, update);
|
|
25
|
+
update();
|
|
26
|
+
return unsub;
|
|
19
27
|
}, [router, stackId, hasHistoryProp]);
|
|
20
|
-
const
|
|
21
|
-
if (hasHistoryProp) return history;
|
|
22
|
-
return router.getStackHistory(stackId);
|
|
23
|
-
}, [router, stackId, hasHistoryProp, history]);
|
|
24
|
-
const historyForThisStack = useSyncExternalStore(subscribe, get, get);
|
|
28
|
+
const historyForThisStack = hasHistoryProp ? history : internalHistory;
|
|
25
29
|
return /*#__PURE__*/_jsx(ScreenStack, {
|
|
26
30
|
style: [styles.flex, appearance?.screen],
|
|
27
31
|
children: historyForThisStack.map(item => /*#__PURE__*/_jsx(ScreenStackItem, {
|
|
@@ -5,7 +5,7 @@ import { TabBarContext } from "./TabBarContext.js";
|
|
|
5
5
|
import { useRouter } from "../RouterContext.js";
|
|
6
6
|
import { Tabs } from 'react-native-screens';
|
|
7
7
|
import { Platform, StyleSheet, View } from 'react-native';
|
|
8
|
-
import { useCallback, useSyncExternalStore, memo, useEffect, useState, useMemo } from 'react';
|
|
8
|
+
import { useCallback, useSyncExternalStore, memo, useEffect, useState, useMemo, startTransition } from 'react';
|
|
9
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
10
|
const isImageSource = value => {
|
|
11
11
|
if (value == null) return false;
|
|
@@ -136,9 +136,17 @@ const TabStackRenderer = /*#__PURE__*/memo(({
|
|
|
136
136
|
}) => {
|
|
137
137
|
const router = useRouter();
|
|
138
138
|
const stackId = stack.getId();
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
const [history, setHistory] = useState(() => router.getStackHistory(stackId));
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
const update = () => {
|
|
142
|
+
startTransition(() => {
|
|
143
|
+
setHistory(router.getStackHistory(stackId));
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
const unsub = router.subscribeStack(stackId, update);
|
|
147
|
+
update();
|
|
148
|
+
return () => unsub();
|
|
149
|
+
}, [router, stackId]);
|
|
142
150
|
return /*#__PURE__*/_jsx(StackRenderer, {
|
|
143
151
|
appearance: appearance,
|
|
144
152
|
stackId: stackId,
|
|
@@ -168,6 +176,20 @@ export const RenderTabBar = /*#__PURE__*/memo(({
|
|
|
168
176
|
index,
|
|
169
177
|
config
|
|
170
178
|
} = snapshot;
|
|
179
|
+
|
|
180
|
+
// Local focus state driven by startTransition so that isFocused changes
|
|
181
|
+
// are deferred until the native Fragment lifecycle completes (Android Fabric).
|
|
182
|
+
const [focusedTabKey, setFocusedTabKey] = useState(() => tabs[index]?.tabKey);
|
|
183
|
+
|
|
184
|
+
// Sync focusedTabKey when index changes from external sources (programmatic navigation).
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
const key = tabs[index]?.tabKey;
|
|
187
|
+
if (key && key !== focusedTabKey) {
|
|
188
|
+
startTransition(() => {
|
|
189
|
+
setFocusedTabKey(key);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}, [tabs, index, focusedTabKey]);
|
|
171
193
|
const {
|
|
172
194
|
iconColor,
|
|
173
195
|
iconColorActive,
|
|
@@ -191,7 +213,10 @@ export const RenderTabBar = /*#__PURE__*/memo(({
|
|
|
191
213
|
const tabIndex = tabs.findIndex(route => route.tabKey === tabKey);
|
|
192
214
|
if (tabIndex === -1) return;
|
|
193
215
|
|
|
194
|
-
//
|
|
216
|
+
// Defer isFocused update so the native Fragment has time to attach.
|
|
217
|
+
startTransition(() => {
|
|
218
|
+
setFocusedTabKey(tabKey);
|
|
219
|
+
});
|
|
195
220
|
if (tabIndex !== index) {
|
|
196
221
|
tabBar.onIndexChange(tabIndex);
|
|
197
222
|
}
|
|
@@ -347,7 +372,7 @@ export const RenderTabBar = /*#__PURE__*/memo(({
|
|
|
347
372
|
experimentalControlNavigationStateInJS: config.experimentalControlNavigationStateInJS,
|
|
348
373
|
...containerProps,
|
|
349
374
|
children: tabs.map((tab, i) => {
|
|
350
|
-
const isFocused = tab.tabKey ===
|
|
375
|
+
const isFocused = tab.tabKey === focusedTabKey;
|
|
351
376
|
const stack = tabBar.stacks[tab.tabKey];
|
|
352
377
|
const node = tabBar.nodes[tab.tabKey];
|
|
353
378
|
const Screen = tabBar.screens[tab.tabKey];
|