@ionic/react-router 8.8.1-dev.11774029927.130994f5 → 8.8.1-dev.11774384072.1e807ca8
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/index.js +67 -41
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1556,6 +1556,26 @@ class StackManager extends React.PureComponent {
|
|
|
1556
1556
|
this.forceUpdate();
|
|
1557
1557
|
return true;
|
|
1558
1558
|
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Handles root navigation by unmounting all non-entering views in this outlet.
|
|
1561
|
+
* Fires ionViewWillLeave / ionViewDidLeave only on views that are currently visible.
|
|
1562
|
+
* Views that are mounted but not visible (e.g., pages earlier in the back stack)
|
|
1563
|
+
* are silently unmounted without lifecycle events, consistent with the behavior
|
|
1564
|
+
* of out-of-scope outlet cleanup.
|
|
1565
|
+
*/
|
|
1566
|
+
handleRootNavigation(enteringViewItem) {
|
|
1567
|
+
const allViewsInOutlet = this.context.getViewItemsForOutlet(this.id);
|
|
1568
|
+
allViewsInOutlet.forEach((viewItem) => {
|
|
1569
|
+
if (viewItem === enteringViewItem) {
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
if (viewItem.ionPageElement && isViewVisible(viewItem.ionPageElement)) {
|
|
1573
|
+
viewItem.ionPageElement.dispatchEvent(new CustomEvent('ionViewWillLeave', { bubbles: false, cancelable: false }));
|
|
1574
|
+
viewItem.ionPageElement.dispatchEvent(new CustomEvent('ionViewDidLeave', { bubbles: false, cancelable: false }));
|
|
1575
|
+
}
|
|
1576
|
+
this.context.unMountViewItem(viewItem);
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1559
1579
|
/**
|
|
1560
1580
|
* Handles nested outlet with relative routes but no parent path. Returns true to abort.
|
|
1561
1581
|
*/
|
|
@@ -2044,14 +2064,20 @@ class StackManager extends React.PureComponent {
|
|
|
2044
2064
|
// Find entering and leaving view items
|
|
2045
2065
|
const viewItems = this.findViewItems(routeInfo);
|
|
2046
2066
|
let enteringViewItem = viewItems.enteringViewItem;
|
|
2047
|
-
|
|
2048
|
-
|
|
2067
|
+
let leavingViewItem = viewItems.leavingViewItem;
|
|
2068
|
+
let shouldUnmountLeavingViewItem = this.shouldUnmountLeavingView(routeInfo, enteringViewItem, leavingViewItem);
|
|
2049
2069
|
// Get parent path for nested outlets
|
|
2050
2070
|
const parentPath = this.getParentPath();
|
|
2051
2071
|
// Handle out-of-scope outlet (route outside mount path)
|
|
2052
2072
|
if (this.handleOutOfScopeOutlet(routeInfo)) {
|
|
2053
2073
|
return;
|
|
2054
2074
|
}
|
|
2075
|
+
// Handle root navigation: unmount all non-entering views
|
|
2076
|
+
if (routeInfo.routeDirection === 'root') {
|
|
2077
|
+
this.handleRootNavigation(enteringViewItem);
|
|
2078
|
+
leavingViewItem = undefined;
|
|
2079
|
+
shouldUnmountLeavingViewItem = false;
|
|
2080
|
+
}
|
|
2055
2081
|
// Clear any pending out-of-scope unmount timeout
|
|
2056
2082
|
if (this.outOfScopeUnmountTimeout) {
|
|
2057
2083
|
clearTimeout(this.outOfScopeUnmountTimeout);
|
|
@@ -2769,34 +2795,14 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
2769
2795
|
* @param action The action that triggered the history change.
|
|
2770
2796
|
*/
|
|
2771
2797
|
const handleHistoryChange = (location, action) => {
|
|
2772
|
-
var _a, _b, _c, _d
|
|
2773
|
-
let leavingLocationInfo;
|
|
2798
|
+
var _a, _b, _c, _d;
|
|
2774
2799
|
/**
|
|
2775
|
-
*
|
|
2776
|
-
*
|
|
2800
|
+
* The leaving location is always the current route, for both programmatic
|
|
2801
|
+
* and external navigations. Using `previous()` for replace actions was
|
|
2802
|
+
* incorrect: it caused the equality check below to skip navigation when
|
|
2803
|
+
* the replace destination matched the entry two slots back in history.
|
|
2777
2804
|
*/
|
|
2778
|
-
|
|
2779
|
-
/**
|
|
2780
|
-
* The current history entry is overwritten, so the previous entry
|
|
2781
|
-
* is the one we are leaving.
|
|
2782
|
-
*/
|
|
2783
|
-
if (((_a = incomingRouteParams.current) === null || _a === void 0 ? void 0 : _a.routeAction) === 'replace') {
|
|
2784
|
-
leavingLocationInfo = locationHistory.current.previous();
|
|
2785
|
-
}
|
|
2786
|
-
else {
|
|
2787
|
-
// If the action is 'push' or 'pop', we want to use the current route.
|
|
2788
|
-
leavingLocationInfo = locationHistory.current.current();
|
|
2789
|
-
}
|
|
2790
|
-
}
|
|
2791
|
-
else {
|
|
2792
|
-
/**
|
|
2793
|
-
* An external navigation was triggered
|
|
2794
|
-
* e.g., browser back/forward button or direct link
|
|
2795
|
-
*
|
|
2796
|
-
* The leaving location is the current route.
|
|
2797
|
-
*/
|
|
2798
|
-
leavingLocationInfo = locationHistory.current.current();
|
|
2799
|
-
}
|
|
2805
|
+
const leavingLocationInfo = locationHistory.current.current();
|
|
2800
2806
|
const leavingUrl = leavingLocationInfo.pathname + leavingLocationInfo.search;
|
|
2801
2807
|
if (leavingUrl !== location.pathname + location.search) {
|
|
2802
2808
|
if (!incomingRouteParams.current) {
|
|
@@ -2898,7 +2904,7 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
2898
2904
|
* An existing id indicates that it's re-activating an existing route.
|
|
2899
2905
|
* e.g., tab switching or navigating back to a previous route
|
|
2900
2906
|
*/
|
|
2901
|
-
if ((
|
|
2907
|
+
if ((_a = incomingRouteParams.current) === null || _a === void 0 ? void 0 : _a.id) {
|
|
2902
2908
|
routeInfo = Object.assign(Object.assign({}, incomingRouteParams.current), { lastPathname: leavingLocationInfo.pathname });
|
|
2903
2909
|
locationHistory.current.add(routeInfo);
|
|
2904
2910
|
/**
|
|
@@ -2907,9 +2913,9 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
2907
2913
|
*/
|
|
2908
2914
|
}
|
|
2909
2915
|
else {
|
|
2910
|
-
const isPushed = ((
|
|
2916
|
+
const isPushed = ((_b = incomingRouteParams.current) === null || _b === void 0 ? void 0 : _b.routeAction) === 'push' &&
|
|
2911
2917
|
incomingRouteParams.current.routeDirection === 'forward';
|
|
2912
|
-
routeInfo = Object.assign(Object.assign({ id: generateId('routeInfo') }, incomingRouteParams.current), { lastPathname: leavingLocationInfo.pathname, pathname: location.pathname, search: location.search, params: ((
|
|
2918
|
+
routeInfo = Object.assign(Object.assign({ id: generateId('routeInfo') }, incomingRouteParams.current), { lastPathname: leavingLocationInfo.pathname, pathname: location.pathname, search: location.search, params: ((_c = incomingRouteParams.current) === null || _c === void 0 ? void 0 : _c.params)
|
|
2913
2919
|
? filterUndefinedParams(incomingRouteParams.current.params)
|
|
2914
2920
|
: {}, prevRouteLastPathname: leavingLocationInfo.lastPathname });
|
|
2915
2921
|
if (isPushed) {
|
|
@@ -2949,7 +2955,7 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
2949
2955
|
routeInfo.pushedByRoute = lastRoute === null || lastRoute === void 0 ? void 0 : lastRoute.pushedByRoute;
|
|
2950
2956
|
}
|
|
2951
2957
|
else {
|
|
2952
|
-
routeInfo.pushedByRoute = (
|
|
2958
|
+
routeInfo.pushedByRoute = (_d = lastRoute === null || lastRoute === void 0 ? void 0 : lastRoute.pushedByRoute) !== null && _d !== void 0 ? _d : leavingLocationInfo.pathname;
|
|
2953
2959
|
}
|
|
2954
2960
|
// Triggered by `navigate()` with replace or a `<Navigate />` component, etc.
|
|
2955
2961
|
}
|
|
@@ -3058,6 +3064,7 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
3058
3064
|
*
|
|
3059
3065
|
* @param tab The tab to set as active.
|
|
3060
3066
|
*/
|
|
3067
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3061
3068
|
const handleSetCurrentTab = (tab, _routeInfo) => {
|
|
3062
3069
|
currentTab.current = tab;
|
|
3063
3070
|
const current = locationHistory.current.current();
|
|
@@ -3090,9 +3097,9 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
3090
3097
|
* @param routeAnimation A custom animation builder to override the
|
|
3091
3098
|
* default "back" animation.
|
|
3092
3099
|
*/
|
|
3093
|
-
const handleNavigateBack = (defaultHref
|
|
3100
|
+
const handleNavigateBack = (defaultHref, routeAnimation) => {
|
|
3094
3101
|
const config = getConfig();
|
|
3095
|
-
defaultHref = defaultHref ? defaultHref : config && config.get('backButtonDefaultHref');
|
|
3102
|
+
defaultHref = defaultHref !== null && defaultHref !== void 0 ? defaultHref : (config && config.get('backButtonDefaultHref'));
|
|
3096
3103
|
const routeInfo = locationHistory.current.current();
|
|
3097
3104
|
// It's a linear navigation.
|
|
3098
3105
|
if (routeInfo && routeInfo.pushedByRoute) {
|
|
@@ -3131,18 +3138,19 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
3131
3138
|
* the history stack.
|
|
3132
3139
|
*/
|
|
3133
3140
|
}
|
|
3134
|
-
else {
|
|
3141
|
+
else if (defaultHref) {
|
|
3135
3142
|
handleNavigate(defaultHref, 'pop', 'back', routeAnimation);
|
|
3136
3143
|
}
|
|
3137
3144
|
/**
|
|
3138
3145
|
* No `pushedByRoute` (e.g., initial page load or tab root).
|
|
3139
|
-
*
|
|
3146
|
+
* Navigate to defaultHref so the back button works on direct
|
|
3147
|
+
* deep-link loads (e.g., loading /tab1/child directly).
|
|
3148
|
+
* Only navigate when defaultHref is explicitly set. The core
|
|
3149
|
+
* back-button component hides itself when no defaultHref is
|
|
3150
|
+
* provided, so a click here means the user set one intentionally.
|
|
3140
3151
|
*/
|
|
3141
3152
|
}
|
|
3142
|
-
else {
|
|
3143
|
-
if (routeInfo && routeInfo.tab) {
|
|
3144
|
-
return;
|
|
3145
|
-
}
|
|
3153
|
+
else if (defaultHref) {
|
|
3146
3154
|
handleNavigate(defaultHref, 'pop', 'back', routeAnimation);
|
|
3147
3155
|
}
|
|
3148
3156
|
};
|
|
@@ -3196,6 +3204,24 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
3196
3204
|
routeAnimation, tab: navigationTab });
|
|
3197
3205
|
navigate(path, { replace: routeAction !== 'push' });
|
|
3198
3206
|
};
|
|
3207
|
+
/**
|
|
3208
|
+
* Navigates to a new root path, clearing Ionic's navigation history so that
|
|
3209
|
+
* canGoBack() returns false after the transition. All previously mounted views
|
|
3210
|
+
* are unmounted. Useful for post-login / post-logout root navigation.
|
|
3211
|
+
*
|
|
3212
|
+
* @param pathname The path to navigate to.
|
|
3213
|
+
* @param routeAnimation An optional custom animation builder.
|
|
3214
|
+
*/
|
|
3215
|
+
const handleNavigateRoot = (pathname, routeAnimation) => {
|
|
3216
|
+
currentTab.current = undefined;
|
|
3217
|
+
forwardStack.current = [];
|
|
3218
|
+
incomingRouteParams.current = {
|
|
3219
|
+
routeAction: 'replace',
|
|
3220
|
+
routeDirection: 'root',
|
|
3221
|
+
routeAnimation,
|
|
3222
|
+
};
|
|
3223
|
+
navigate(pathname, { replace: true });
|
|
3224
|
+
};
|
|
3199
3225
|
const routeMangerContextValue = {
|
|
3200
3226
|
canGoBack: () => locationHistory.current.canGoBack(),
|
|
3201
3227
|
clearOutlet: viewStack.current.clear,
|
|
@@ -3210,7 +3236,7 @@ const IonRouter = ({ children, registerHistoryListener }) => {
|
|
|
3210
3236
|
unMountViewItem: viewStack.current.remove,
|
|
3211
3237
|
};
|
|
3212
3238
|
return (React.createElement(RouteManagerContext.Provider, { value: routeMangerContextValue },
|
|
3213
|
-
React.createElement(NavManager, { ionRoute: IonRouteInner, stackManager: StackManager, routeInfo: routeInfo, onNativeBack: handleNativeBack, onNavigateBack: handleNavigateBack, onNavigate: handleNavigate, onSetCurrentTab: handleSetCurrentTab, onChangeTab: handleChangeTab, onResetTab: handleResetTab, locationHistory: locationHistory.current }, children)));
|
|
3239
|
+
React.createElement(NavManager, { ionRoute: IonRouteInner, stackManager: StackManager, routeInfo: routeInfo, onNativeBack: handleNativeBack, onNavigateBack: handleNavigateBack, onNavigate: handleNavigate, onNavigateRoot: handleNavigateRoot, onSetCurrentTab: handleSetCurrentTab, onChangeTab: handleChangeTab, onResetTab: handleResetTab, locationHistory: locationHistory.current }, children)));
|
|
3214
3240
|
};
|
|
3215
3241
|
IonRouter.displayName = 'IonRouter';
|
|
3216
3242
|
|