@ionic/react-router 7.5.3-dev.11698858201.14165f23 → 7.5.3-dev.11699994454.1cbf1283

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.
@@ -1,270 +0,0 @@
1
- "use strict";
2
- import { RouteManagerContext, StackContext, generateId, getConfig } from "@ionic/react";
3
- import React from "react";
4
- import { matchPath } from "react-router-dom";
5
- import { clonePageElement } from "./clonePageElement";
6
- const isViewVisible = (el) => !el.classList.contains("ion-page-invisible") && !el.classList.contains("ion-page-hidden");
7
- export class StackManager extends React.PureComponent {
8
- constructor(props) {
9
- super(props);
10
- this.stackContextValue = {
11
- registerIonPage: this.registerIonPage.bind(this),
12
- isInOutlet: () => true
13
- };
14
- this.pendingPageTransition = false;
15
- this.registerIonPage = this.registerIonPage.bind(this);
16
- this.transitionPage = this.transitionPage.bind(this);
17
- this.handlePageTransition = this.handlePageTransition.bind(this);
18
- this.id = generateId("routerOutlet");
19
- this.prevProps = void 0;
20
- this.skipTransition = false;
21
- }
22
- componentDidMount() {
23
- if (this.clearOutletTimeout) {
24
- clearTimeout(this.clearOutletTimeout);
25
- }
26
- if (this.routerOutletElement) {
27
- this.setupRouterOutlet(this.routerOutletElement);
28
- this.handlePageTransition(this.props.routeInfo);
29
- }
30
- }
31
- componentDidUpdate(prevProps) {
32
- const { pathname } = this.props.routeInfo;
33
- const { pathname: prevPathname } = prevProps.routeInfo;
34
- if (pathname !== prevPathname) {
35
- this.prevProps = prevProps;
36
- this.handlePageTransition(this.props.routeInfo);
37
- } else if (this.pendingPageTransition) {
38
- this.handlePageTransition(this.props.routeInfo);
39
- this.pendingPageTransition = false;
40
- }
41
- }
42
- componentWillUnmount() {
43
- this.clearOutletTimeout = this.context.clearOutlet(this.id);
44
- }
45
- async handlePageTransition(routeInfo) {
46
- if (!this.routerOutletElement || !this.routerOutletElement.commit) {
47
- this.pendingPageTransition = true;
48
- } else {
49
- let enteringViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id);
50
- let leavingViewItem = this.context.findLeavingViewItemByRouteInfo(routeInfo, this.id);
51
- if (!leavingViewItem && routeInfo.prevRouteLastPathname) {
52
- leavingViewItem = this.context.findViewItemByPathname(routeInfo.prevRouteLastPathname, this.id);
53
- }
54
- if (leavingViewItem) {
55
- if (routeInfo.routeAction === "replace") {
56
- leavingViewItem.mount = false;
57
- } else if (!(routeInfo.routeAction === "push" && routeInfo.routeDirection === "forward")) {
58
- if (routeInfo.routeDirection !== "none" && enteringViewItem !== leavingViewItem) {
59
- leavingViewItem.mount = false;
60
- }
61
- } else if (routeInfo.routeOptions?.unmount) {
62
- leavingViewItem.mount = false;
63
- }
64
- }
65
- const enteringRoute = matchRoute(this.ionRouterOutlet?.props.children, routeInfo);
66
- if (enteringViewItem) {
67
- enteringViewItem.reactElement = enteringRoute;
68
- } else if (enteringRoute) {
69
- enteringViewItem = this.context.createViewItem(this.id, enteringRoute, routeInfo);
70
- this.context.addViewItem(enteringViewItem);
71
- }
72
- if (enteringViewItem && enteringViewItem.ionPageElement) {
73
- if (enteringViewItem === leavingViewItem) {
74
- if (enteringViewItem.routeData.match.url !== routeInfo.pathname) {
75
- return;
76
- }
77
- }
78
- if (!leavingViewItem && this.props.routeInfo.prevRouteLastPathname) {
79
- leavingViewItem = this.context.findViewItemByPathname(this.props.routeInfo.prevRouteLastPathname, this.id);
80
- }
81
- if (isViewVisible(enteringViewItem.ionPageElement) && leavingViewItem !== void 0 && !isViewVisible(leavingViewItem.ionPageElement)) {
82
- return;
83
- }
84
- this.transitionPage(routeInfo, enteringViewItem, leavingViewItem);
85
- } else if (leavingViewItem && !enteringRoute && !enteringViewItem) {
86
- if (leavingViewItem.ionPageElement) {
87
- leavingViewItem.ionPageElement.classList.add("ion-page-hidden");
88
- leavingViewItem.ionPageElement.setAttribute("aria-hidden", "true");
89
- }
90
- }
91
- this.forceUpdate();
92
- }
93
- }
94
- registerIonPage(page, routeInfo) {
95
- const foundView = this.context.findViewItemByRouteInfo(routeInfo, this.id);
96
- if (foundView) {
97
- const oldPageElement = foundView.ionPageElement;
98
- foundView.ionPageElement = page;
99
- foundView.ionRoute = true;
100
- if (oldPageElement === page) {
101
- return;
102
- }
103
- }
104
- this.handlePageTransition(routeInfo);
105
- }
106
- async setupRouterOutlet(routerOutlet) {
107
- const canStart = () => {
108
- const config = getConfig();
109
- const swipeEnabled = config && config.get("swipeBackEnabled", routerOutlet.mode === "ios");
110
- if (!swipeEnabled) {
111
- return false;
112
- }
113
- const { routeInfo } = this.props;
114
- const propsToUse = this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute ? this.prevProps.routeInfo : { pathname: routeInfo.pushedByRoute || "" };
115
- const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);
116
- return !!enteringViewItem && /**
117
- * The root url '/' is treated as
118
- * the first view item (but is never mounted),
119
- * so we do not want to swipe back to the
120
- * root url.
121
- */
122
- enteringViewItem.mount && /**
123
- * When on the first page (whatever view
124
- * you land on after the root url) it
125
- * is possible for findViewItemByRouteInfo to
126
- * return the exact same view you are currently on.
127
- * Make sure that we are not swiping back to the same
128
- * instances of a view.
129
- */
130
- enteringViewItem.routeData.match.path !== routeInfo.pathname;
131
- };
132
- const onStart = async () => {
133
- const { routeInfo } = this.props;
134
- const propsToUse = this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute ? this.prevProps.routeInfo : { pathname: routeInfo.pushedByRoute || "" };
135
- const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);
136
- const leavingViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id, false);
137
- if (enteringViewItem && leavingViewItem) {
138
- await this.transitionPage(routeInfo, enteringViewItem, leavingViewItem, "back", true);
139
- }
140
- return Promise.resolve();
141
- };
142
- const onEnd = (shouldContinue) => {
143
- if (shouldContinue) {
144
- this.skipTransition = true;
145
- this.context.goBack();
146
- } else {
147
- const { routeInfo } = this.props;
148
- const propsToUse = this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute ? this.prevProps.routeInfo : { pathname: routeInfo.pushedByRoute || "" };
149
- const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);
150
- const leavingViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id, false);
151
- if (enteringViewItem !== leavingViewItem && enteringViewItem?.ionPageElement !== void 0) {
152
- const { ionPageElement } = enteringViewItem;
153
- ionPageElement.setAttribute("aria-hidden", "true");
154
- ionPageElement.classList.add("ion-page-hidden");
155
- }
156
- }
157
- };
158
- routerOutlet.swipeHandler = {
159
- canStart,
160
- onStart,
161
- onEnd
162
- };
163
- }
164
- async transitionPage(routeInfo, enteringViewItem, leavingViewItem, direction, progressAnimation = false) {
165
- const runCommit = async (enteringEl, leavingEl) => {
166
- const skipTransition = this.skipTransition;
167
- if (skipTransition) {
168
- this.skipTransition = false;
169
- } else {
170
- enteringEl.classList.add("ion-page");
171
- enteringEl.classList.add("ion-page-invisible");
172
- }
173
- await routerOutlet.commit(enteringEl, leavingEl, {
174
- duration: skipTransition || directionToUse === void 0 ? 0 : void 0,
175
- direction: directionToUse,
176
- showGoBack: !!routeInfo.pushedByRoute,
177
- progressAnimation,
178
- animationBuilder: routeInfo.routeAnimation
179
- });
180
- };
181
- const routerOutlet = this.routerOutletElement;
182
- const routeInfoFallbackDirection = routeInfo.routeDirection === "none" || routeInfo.routeDirection === "root" ? void 0 : routeInfo.routeDirection;
183
- const directionToUse = direction ?? routeInfoFallbackDirection;
184
- if (enteringViewItem && enteringViewItem.ionPageElement && this.routerOutletElement) {
185
- if (leavingViewItem && leavingViewItem.ionPageElement && enteringViewItem === leavingViewItem) {
186
- const match = matchComponent(leavingViewItem.reactElement, routeInfo.pathname, true);
187
- if (match) {
188
- const newLeavingElement = clonePageElement(leavingViewItem.ionPageElement.outerHTML);
189
- if (newLeavingElement) {
190
- this.routerOutletElement.appendChild(newLeavingElement);
191
- await runCommit(enteringViewItem.ionPageElement, newLeavingElement);
192
- this.routerOutletElement.removeChild(newLeavingElement);
193
- }
194
- } else {
195
- await runCommit(enteringViewItem.ionPageElement, void 0);
196
- }
197
- } else {
198
- await runCommit(enteringViewItem.ionPageElement, leavingViewItem?.ionPageElement);
199
- if (leavingViewItem && leavingViewItem.ionPageElement && !progressAnimation) {
200
- leavingViewItem.ionPageElement.classList.add("ion-page-hidden");
201
- leavingViewItem.ionPageElement.setAttribute("aria-hidden", "true");
202
- }
203
- }
204
- }
205
- }
206
- render() {
207
- const { children } = this.props;
208
- const ionRouterOutlet = React.Children.only(children);
209
- this.ionRouterOutlet = ionRouterOutlet;
210
- const components = this.context.getChildrenToRender(this.id, this.ionRouterOutlet, this.props.routeInfo, () => {
211
- this.forceUpdate();
212
- });
213
- return /* @__PURE__ */ React.createElement(StackContext.Provider, { value: this.stackContextValue }, React.cloneElement(
214
- ionRouterOutlet,
215
- {
216
- ref: (node) => {
217
- if (ionRouterOutlet.props.setRef) {
218
- ionRouterOutlet.props.setRef(node);
219
- }
220
- if (ionRouterOutlet.props.forwardedRef) {
221
- ionRouterOutlet.props.forwardedRef.current = node;
222
- }
223
- this.routerOutletElement = node;
224
- const { ref } = ionRouterOutlet;
225
- if (typeof ref === "function") {
226
- ref(node);
227
- }
228
- }
229
- },
230
- components
231
- ));
232
- }
233
- static get contextType() {
234
- return RouteManagerContext;
235
- }
236
- }
237
- export default StackManager;
238
- function matchRoute(node, routeInfo) {
239
- let matchedNode;
240
- React.Children.forEach(node, (child) => {
241
- const matchProps = {
242
- exact: child.props.exact,
243
- path: child.props.path || child.props.from,
244
- component: child.props.component
245
- };
246
- const match = matchPath(routeInfo.pathname, matchProps);
247
- if (match) {
248
- matchedNode = child;
249
- }
250
- });
251
- if (matchedNode) {
252
- return matchedNode;
253
- }
254
- React.Children.forEach(node, (child) => {
255
- if (!(child.props.path || child.props.from)) {
256
- matchedNode = child;
257
- }
258
- });
259
- return matchedNode;
260
- }
261
- function matchComponent(node, pathname, forceExact) {
262
- const matchProps = {
263
- exact: forceExact ? true : node.props.exact,
264
- path: node.props.path || node.props.from,
265
- component: node.props.component
266
- };
267
- const match = matchPath(pathname, matchProps);
268
- return match;
269
- }
270
- //# sourceMappingURL=StackManager.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/ReactRouter/StackManager.tsx"],
4
- "sourcesContent": ["import type { RouteInfo, StackContextState, ViewItem } from '@ionic/react';\nimport { RouteManagerContext, StackContext, generateId, getConfig } from '@ionic/react';\nimport React from 'react';\nimport { matchPath } from 'react-router-dom';\n\nimport { clonePageElement } from './clonePageElement';\n\n// TODO(FW-2959): types\n\ninterface StackManagerProps {\n routeInfo: RouteInfo;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\ninterface StackManagerState {}\n\nconst isViewVisible = (el: HTMLElement) =>\n !el.classList.contains('ion-page-invisible') && !el.classList.contains('ion-page-hidden');\n\nexport class StackManager extends React.PureComponent<StackManagerProps, StackManagerState> {\n id: string;\n context!: React.ContextType<typeof RouteManagerContext>;\n ionRouterOutlet?: React.ReactElement;\n routerOutletElement: HTMLIonRouterOutletElement | undefined;\n prevProps?: StackManagerProps;\n skipTransition: boolean;\n\n stackContextValue: StackContextState = {\n registerIonPage: this.registerIonPage.bind(this),\n isInOutlet: () => true,\n };\n\n private clearOutletTimeout: any;\n private pendingPageTransition = false;\n\n constructor(props: StackManagerProps) {\n super(props);\n this.registerIonPage = this.registerIonPage.bind(this);\n this.transitionPage = this.transitionPage.bind(this);\n this.handlePageTransition = this.handlePageTransition.bind(this);\n this.id = generateId('routerOutlet');\n this.prevProps = undefined;\n this.skipTransition = false;\n }\n\n componentDidMount() {\n if (this.clearOutletTimeout) {\n /**\n * The clearOutlet integration with React Router is a bit hacky.\n * It uses a timeout to clear the outlet after a transition.\n * In React v18, components are mounted and unmounted in development mode\n * to check for side effects.\n *\n * This clearTimeout prevents the outlet from being cleared when the component is re-mounted,\n * which should only happen in development mode and as a result of a hot reload.\n */\n clearTimeout(this.clearOutletTimeout);\n }\n if (this.routerOutletElement) {\n this.setupRouterOutlet(this.routerOutletElement);\n this.handlePageTransition(this.props.routeInfo);\n }\n }\n\n componentDidUpdate(prevProps: StackManagerProps) {\n const { pathname } = this.props.routeInfo;\n const { pathname: prevPathname } = prevProps.routeInfo;\n\n if (pathname !== prevPathname) {\n this.prevProps = prevProps;\n this.handlePageTransition(this.props.routeInfo);\n } else if (this.pendingPageTransition) {\n this.handlePageTransition(this.props.routeInfo);\n this.pendingPageTransition = false;\n }\n }\n\n componentWillUnmount() {\n this.clearOutletTimeout = this.context.clearOutlet(this.id);\n }\n\n async handlePageTransition(routeInfo: RouteInfo) {\n if (!this.routerOutletElement || !this.routerOutletElement.commit) {\n /**\n * The route outlet has not mounted yet. We need to wait for it to render\n * before we can transition the page.\n *\n * Set a flag to indicate that we should transition the page after\n * the component has updated.\n */\n this.pendingPageTransition = true;\n } else {\n let enteringViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id);\n let leavingViewItem = this.context.findLeavingViewItemByRouteInfo(routeInfo, this.id);\n\n if (!leavingViewItem && routeInfo.prevRouteLastPathname) {\n leavingViewItem = this.context.findViewItemByPathname(routeInfo.prevRouteLastPathname, this.id);\n }\n\n // Check if leavingViewItem should be unmounted\n if (leavingViewItem) {\n if (routeInfo.routeAction === 'replace') {\n leavingViewItem.mount = false;\n } else if (!(routeInfo.routeAction === 'push' && routeInfo.routeDirection === 'forward')) {\n if (routeInfo.routeDirection !== 'none' && enteringViewItem !== leavingViewItem) {\n leavingViewItem.mount = false;\n }\n } else if (routeInfo.routeOptions?.unmount) {\n leavingViewItem.mount = false;\n }\n }\n\n const enteringRoute = matchRoute(this.ionRouterOutlet?.props.children, routeInfo) as React.ReactElement;\n\n if (enteringViewItem) {\n enteringViewItem.reactElement = enteringRoute;\n } else if (enteringRoute) {\n enteringViewItem = this.context.createViewItem(this.id, enteringRoute, routeInfo);\n this.context.addViewItem(enteringViewItem);\n }\n\n if (enteringViewItem && enteringViewItem.ionPageElement) {\n /**\n * If the entering view item is the same as the leaving view item,\n * then we don't need to transition.\n */\n if (enteringViewItem === leavingViewItem) {\n /**\n * If the entering view item is the same as the leaving view item,\n * we are either transitioning using parameterized routes to the same view\n * or a parent router outlet is re-rendering as a result of React props changing.\n *\n * If the route data does not match the current path, the parent router outlet\n * is attempting to transition and we cancel the operation.\n */\n if (enteringViewItem.routeData.match.url !== routeInfo.pathname) {\n return;\n }\n }\n\n /**\n * If there isn't a leaving view item, but the route info indicates\n * that the user has routed from a previous path, then we need\n * to find the leaving view item to transition between.\n */\n if (!leavingViewItem && this.props.routeInfo.prevRouteLastPathname) {\n leavingViewItem = this.context.findViewItemByPathname(this.props.routeInfo.prevRouteLastPathname, this.id);\n }\n\n /**\n * If the entering view is already visible and the leaving view is not, the transition does not need to occur.\n */\n if (\n isViewVisible(enteringViewItem.ionPageElement) &&\n leavingViewItem !== undefined &&\n !isViewVisible(leavingViewItem.ionPageElement!)\n ) {\n return;\n }\n\n /**\n * The view should only be transitioned in the following cases:\n * 1. Performing a replace or pop action, such as a swipe to go back gesture\n * to animation the leaving view off the screen.\n *\n * 2. Navigating between top-level router outlets, such as /page-1 to /page-2;\n * or navigating within a nested outlet, such as /tabs/tab-1 to /tabs/tab-2.\n *\n * 3. The entering view is an ion-router-outlet containing a page\n * matching the current route and that hasn't already transitioned in.\n *\n * This should only happen when navigating directly to a nested router outlet\n * route or on an initial page load (i.e. refreshing). In cases when loading\n * /tabs/tab-1, we need to transition the /tabs page element into the view.\n */\n this.transitionPage(routeInfo, enteringViewItem, leavingViewItem);\n } else if (leavingViewItem && !enteringRoute && !enteringViewItem) {\n // If we have a leavingView but no entering view/route, we are probably leaving to\n // another outlet, so hide this leavingView. We do it in a timeout to give time for a\n // transition to finish.\n // setTimeout(() => {\n if (leavingViewItem.ionPageElement) {\n leavingViewItem.ionPageElement.classList.add('ion-page-hidden');\n leavingViewItem.ionPageElement.setAttribute('aria-hidden', 'true');\n }\n // }, 250);\n }\n\n this.forceUpdate();\n }\n }\n\n registerIonPage(page: HTMLElement, routeInfo: RouteInfo) {\n const foundView = this.context.findViewItemByRouteInfo(routeInfo, this.id);\n if (foundView) {\n const oldPageElement = foundView.ionPageElement;\n foundView.ionPageElement = page;\n foundView.ionRoute = true;\n\n /**\n * React 18 will unmount and remount IonPage\n * elements in development mode when using createRoot.\n * This can cause duplicate page transitions to occur.\n */\n if (oldPageElement === page) {\n return;\n }\n }\n this.handlePageTransition(routeInfo);\n }\n\n async setupRouterOutlet(routerOutlet: HTMLIonRouterOutletElement) {\n const canStart = () => {\n const config = getConfig();\n const swipeEnabled = config && config.get('swipeBackEnabled', routerOutlet.mode === 'ios');\n if (!swipeEnabled) {\n return false;\n }\n\n const { routeInfo } = this.props;\n\n const propsToUse =\n this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute\n ? this.prevProps.routeInfo\n : ({ pathname: routeInfo.pushedByRoute || '' } as any);\n const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);\n\n return (\n !!enteringViewItem &&\n /**\n * The root url '/' is treated as\n * the first view item (but is never mounted),\n * so we do not want to swipe back to the\n * root url.\n */\n enteringViewItem.mount &&\n /**\n * When on the first page (whatever view\n * you land on after the root url) it\n * is possible for findViewItemByRouteInfo to\n * return the exact same view you are currently on.\n * Make sure that we are not swiping back to the same\n * instances of a view.\n */\n enteringViewItem.routeData.match.path !== routeInfo.pathname\n );\n };\n\n const onStart = async () => {\n const { routeInfo } = this.props;\n\n const propsToUse =\n this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute\n ? this.prevProps.routeInfo\n : ({ pathname: routeInfo.pushedByRoute || '' } as any);\n const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);\n const leavingViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id, false);\n\n /**\n * When the gesture starts, kick off\n * a transition that is controlled\n * via a swipe gesture.\n */\n if (enteringViewItem && leavingViewItem) {\n await this.transitionPage(routeInfo, enteringViewItem, leavingViewItem, 'back', true);\n }\n\n return Promise.resolve();\n };\n const onEnd = (shouldContinue: boolean) => {\n if (shouldContinue) {\n this.skipTransition = true;\n\n this.context.goBack();\n } else {\n /**\n * In the event that the swipe\n * gesture was aborted, we should\n * re-hide the page that was going to enter.\n */\n const { routeInfo } = this.props;\n\n const propsToUse =\n this.prevProps && this.prevProps.routeInfo.pathname === routeInfo.pushedByRoute\n ? this.prevProps.routeInfo\n : ({ pathname: routeInfo.pushedByRoute || '' } as any);\n const enteringViewItem = this.context.findViewItemByRouteInfo(propsToUse, this.id, false);\n const leavingViewItem = this.context.findViewItemByRouteInfo(routeInfo, this.id, false);\n\n /**\n * Ionic React has a design defect where it\n * a) Unmounts the leaving view item when using parameterized routes\n * b) Considers the current view to be the entering view when using\n * parameterized routes\n *\n * As a result, we should not hide the view item here\n * as it will cause the current view to be hidden.\n */\n if (enteringViewItem !== leavingViewItem && enteringViewItem?.ionPageElement !== undefined) {\n const { ionPageElement } = enteringViewItem;\n ionPageElement.setAttribute('aria-hidden', 'true');\n ionPageElement.classList.add('ion-page-hidden');\n }\n }\n };\n\n routerOutlet.swipeHandler = {\n canStart,\n onStart,\n onEnd,\n };\n }\n\n async transitionPage(\n routeInfo: RouteInfo,\n enteringViewItem: ViewItem,\n leavingViewItem?: ViewItem,\n direction?: 'forward' | 'back',\n progressAnimation = false\n ) {\n const runCommit = async (enteringEl: HTMLElement, leavingEl?: HTMLElement) => {\n const skipTransition = this.skipTransition;\n\n /**\n * If the transition was handled\n * via the swipe to go back gesture,\n * then we do not want to perform\n * another transition.\n *\n * We skip adding ion-page or ion-page-invisible\n * because the entering view already exists in the DOM.\n * If we added the classes, there would be a flicker where\n * the view would be briefly hidden.\n */\n if (skipTransition) {\n /**\n * We need to reset skipTransition before\n * we call routerOutlet.commit otherwise\n * the transition triggered by the swipe\n * to go back gesture would reset it. In\n * that case you would see a duplicate\n * transition triggered by handlePageTransition\n * in componentDidUpdate.\n */\n this.skipTransition = false;\n } else {\n enteringEl.classList.add('ion-page');\n enteringEl.classList.add('ion-page-invisible');\n }\n\n await routerOutlet.commit(enteringEl, leavingEl, {\n duration: skipTransition || directionToUse === undefined ? 0 : undefined,\n direction: directionToUse,\n showGoBack: !!routeInfo.pushedByRoute,\n progressAnimation,\n animationBuilder: routeInfo.routeAnimation,\n });\n };\n\n const routerOutlet = this.routerOutletElement!;\n\n const routeInfoFallbackDirection =\n routeInfo.routeDirection === 'none' || routeInfo.routeDirection === 'root' ? undefined : routeInfo.routeDirection;\n const directionToUse = direction ?? routeInfoFallbackDirection;\n\n if (enteringViewItem && enteringViewItem.ionPageElement && this.routerOutletElement) {\n if (leavingViewItem && leavingViewItem.ionPageElement && enteringViewItem === leavingViewItem) {\n // If a page is transitioning to another version of itself\n // we clone it so we can have an animation to show\n\n const match = matchComponent(leavingViewItem.reactElement, routeInfo.pathname, true);\n if (match) {\n const newLeavingElement = clonePageElement(leavingViewItem.ionPageElement.outerHTML);\n if (newLeavingElement) {\n this.routerOutletElement.appendChild(newLeavingElement);\n await runCommit(enteringViewItem.ionPageElement, newLeavingElement);\n this.routerOutletElement.removeChild(newLeavingElement);\n }\n } else {\n await runCommit(enteringViewItem.ionPageElement, undefined);\n }\n } else {\n await runCommit(enteringViewItem.ionPageElement, leavingViewItem?.ionPageElement);\n if (leavingViewItem && leavingViewItem.ionPageElement && !progressAnimation) {\n leavingViewItem.ionPageElement.classList.add('ion-page-hidden');\n leavingViewItem.ionPageElement.setAttribute('aria-hidden', 'true');\n }\n }\n }\n }\n\n render() {\n const { children } = this.props;\n const ionRouterOutlet = React.Children.only(children) as React.ReactElement;\n this.ionRouterOutlet = ionRouterOutlet;\n\n const components = this.context.getChildrenToRender(this.id, this.ionRouterOutlet, this.props.routeInfo, () => {\n this.forceUpdate();\n });\n\n return (\n <StackContext.Provider value={this.stackContextValue}>\n {React.cloneElement(\n ionRouterOutlet as any,\n {\n ref: (node: HTMLIonRouterOutletElement) => {\n if (ionRouterOutlet.props.setRef) {\n ionRouterOutlet.props.setRef(node);\n }\n if (ionRouterOutlet.props.forwardedRef) {\n ionRouterOutlet.props.forwardedRef.current = node;\n }\n this.routerOutletElement = node;\n const { ref } = ionRouterOutlet as any;\n if (typeof ref === 'function') {\n ref(node);\n }\n },\n },\n components\n )}\n </StackContext.Provider>\n );\n }\n\n static get contextType() {\n return RouteManagerContext;\n }\n}\n\nexport default StackManager;\n\nfunction matchRoute(node: React.ReactNode, routeInfo: RouteInfo) {\n let matchedNode: React.ReactNode;\n React.Children.forEach(node as React.ReactElement, (child: React.ReactElement) => {\n const matchProps = {\n exact: child.props.exact,\n path: child.props.path || child.props.from,\n component: child.props.component,\n };\n const match = matchPath(routeInfo.pathname, matchProps);\n if (match) {\n matchedNode = child;\n }\n });\n\n if (matchedNode) {\n return matchedNode;\n }\n // If we haven't found a node\n // try to find one that doesn't have a path or from prop, that will be our not found route\n React.Children.forEach(node as React.ReactElement, (child: React.ReactElement) => {\n if (!(child.props.path || child.props.from)) {\n matchedNode = child;\n }\n });\n\n return matchedNode;\n}\n\nfunction matchComponent(node: React.ReactElement, pathname: string, forceExact?: boolean) {\n const matchProps = {\n exact: forceExact ? true : node.props.exact,\n path: node.props.path || node.props.from,\n component: node.props.component,\n };\n const match = matchPath(pathname, matchProps);\n\n return match;\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,21 +0,0 @@
1
- "use strict";
2
- export function clonePageElement(leavingViewHtml) {
3
- let html;
4
- if (typeof leavingViewHtml === "string") {
5
- html = leavingViewHtml;
6
- } else {
7
- html = leavingViewHtml.outerHTML;
8
- }
9
- if (document) {
10
- const newEl = document.createElement("div");
11
- newEl.innerHTML = html;
12
- newEl.style.zIndex = "";
13
- const ionBackButton = newEl.getElementsByTagName("ion-back-button");
14
- if (ionBackButton[0]) {
15
- ionBackButton[0].remove();
16
- }
17
- return newEl.firstChild;
18
- }
19
- return void 0;
20
- }
21
- //# sourceMappingURL=clonePageElement.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/ReactRouter/clonePageElement.ts"],
4
- "sourcesContent": ["export function clonePageElement(leavingViewHtml: string | HTMLElement) {\n let html: string;\n if (typeof leavingViewHtml === 'string') {\n html = leavingViewHtml;\n } else {\n html = leavingViewHtml.outerHTML;\n }\n if (document) {\n const newEl = document.createElement('div');\n newEl.innerHTML = html;\n newEl.style.zIndex = '';\n // Remove an existing back button so the new element doesn't get two of them\n const ionBackButton = newEl.getElementsByTagName('ion-back-button');\n if (ionBackButton[0]) {\n ionBackButton[0].remove();\n }\n return newEl.firstChild as HTMLElement;\n }\n return undefined;\n}\n"],
5
- "mappings": ";AAAO,gBAAS,iBAAiB,iBAAuC;AACtE,MAAI;AACJ,MAAI,OAAO,oBAAoB,UAAU;AACvC,WAAO;AAAA,EACT,OAAO;AACL,WAAO,gBAAgB;AAAA,EACzB;AACA,MAAI,UAAU;AACZ,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,YAAY;AAClB,UAAM,MAAM,SAAS;AAErB,UAAM,gBAAgB,MAAM,qBAAqB,iBAAiB;AAClE,QAAI,cAAc,CAAC,GAAG;AACpB,oBAAc,CAAC,EAAE,OAAO;AAAA,IAC1B;AACA,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;",
6
- "names": []
7
- }