@ionic/react-router 8.7.12 → 8.7.13-dev.11765426479.16a61ecf

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,23 +1,8 @@
1
- import type { Action as HistoryAction, History, Location as HistoryLocation } from 'history';
1
+ /**
2
+ * `IonReactHashRouter` provides a way to use hash-based routing in Ionic
3
+ * React applications.
4
+ */
5
+ import type { PropsWithChildren } from 'react';
2
6
  import React from 'react';
3
- import type { BrowserRouterProps } from 'react-router-dom';
4
- interface IonReactHashRouterProps extends BrowserRouterProps {
5
- history?: History;
6
- }
7
- export declare class IonReactHashRouter extends React.Component<IonReactHashRouterProps> {
8
- history: History;
9
- historyListenHandler?: (location: HistoryLocation, action: HistoryAction) => void;
10
- constructor(props: IonReactHashRouterProps);
11
- /**
12
- * history@4.x passes separate location and action
13
- * params. history@5.x passes location and action
14
- * together as a single object.
15
- * TODO: If support for React Router <=5 is dropped
16
- * this logic is no longer needed. We can just assume
17
- * a single object with both location and action.
18
- */
19
- handleHistoryChange(location: HistoryLocation, action: HistoryAction): void;
20
- registerHistoryListener(cb: (location: HistoryLocation, action: HistoryAction) => void): void;
21
- render(): React.JSX.Element;
22
- }
23
- export {};
7
+ import type { HashRouterProps } from 'react-router-dom';
8
+ export declare const IonReactHashRouter: ({ children, ...routerProps }: PropsWithChildren<HashRouterProps>) => React.JSX.Element;
@@ -1,23 +1,9 @@
1
- import type { Action as HistoryAction, Location as HistoryLocation, MemoryHistory } from 'history';
1
+ /**
2
+ * `IonReactMemoryRouter` provides a way to use `react-router` in
3
+ * environments where a traditional browser history (like `BrowserRouter`)
4
+ * isn't available or desirable.
5
+ */
6
+ import type { PropsWithChildren } from 'react';
2
7
  import React from 'react';
3
8
  import type { MemoryRouterProps } from 'react-router';
4
- interface IonReactMemoryRouterProps extends MemoryRouterProps {
5
- history: MemoryHistory;
6
- }
7
- export declare class IonReactMemoryRouter extends React.Component<IonReactMemoryRouterProps> {
8
- history: MemoryHistory;
9
- historyListenHandler?: (location: HistoryLocation, action: HistoryAction) => void;
10
- constructor(props: IonReactMemoryRouterProps);
11
- /**
12
- * history@4.x passes separate location and action
13
- * params. history@5.x passes location and action
14
- * together as a single object.
15
- * TODO: If support for React Router <=5 is dropped
16
- * this logic is no longer needed. We can just assume
17
- * a single object with both location and action.
18
- */
19
- handleHistoryChange(location: HistoryLocation, action: HistoryAction): void;
20
- registerHistoryListener(cb: (location: HistoryLocation, action: HistoryAction) => void): void;
21
- render(): React.JSX.Element;
22
- }
23
- export {};
9
+ export declare const IonReactMemoryRouter: ({ children, ...routerProps }: PropsWithChildren<MemoryRouterProps>) => React.JSX.Element;
@@ -1,23 +1,10 @@
1
- import type { Action as HistoryAction, History, Location as HistoryLocation } from 'history';
1
+ /**
2
+ * `IonReactRouter` facilitates the integration of Ionic's specific
3
+ * navigation and UI management with the standard React Router mechanisms,
4
+ * allowing an inner Ionic-specific router (`IonRouter`) to react to
5
+ * navigation events.
6
+ */
7
+ import type { PropsWithChildren } from 'react';
2
8
  import React from 'react';
3
9
  import type { BrowserRouterProps } from 'react-router-dom';
4
- interface IonReactRouterProps extends BrowserRouterProps {
5
- history?: History;
6
- }
7
- export declare class IonReactRouter extends React.Component<IonReactRouterProps> {
8
- historyListenHandler?: (location: HistoryLocation, action: HistoryAction) => void;
9
- history: History;
10
- constructor(props: IonReactRouterProps);
11
- /**
12
- * history@4.x passes separate location and action
13
- * params. history@5.x passes location and action
14
- * together as a single object.
15
- * TODO: If support for React Router <=5 is dropped
16
- * this logic is no longer needed. We can just assume
17
- * a single object with both location and action.
18
- */
19
- handleHistoryChange(location: HistoryLocation, action: HistoryAction): void;
20
- registerHistoryListener(cb: (location: HistoryLocation, action: HistoryAction) => void): void;
21
- render(): React.JSX.Element;
22
- }
23
- export {};
10
+ export declare const IonReactRouter: ({ children, ...browserRouterProps }: PropsWithChildren<BrowserRouterProps>) => React.JSX.Element;
@@ -1,5 +1,3 @@
1
1
  import type { IonRouteProps } from '@ionic/react';
2
2
  import React from 'react';
3
- export declare class IonRouteInner extends React.PureComponent<IonRouteProps> {
4
- render(): React.JSX.Element;
5
- }
3
+ export declare const IonRouteInner: ({ path, element }: IonRouteProps) => React.JSX.Element;
@@ -1,44 +1,24 @@
1
- import type { AnimationBuilder, RouteAction, RouteInfo, RouteManagerContextState, RouterDirection, ViewItem } from '@ionic/react';
2
- import { LocationHistory } from '@ionic/react';
3
- import type { Action as HistoryAction, Location as HistoryLocation } from 'history';
1
+ /**
2
+ * `IonRouter` is responsible for managing the application's navigation
3
+ * state, tracking the history of visited routes, and coordinating
4
+ * transitions between different views. It intercepts route changes from
5
+ * React Router and translates them into actions that Ionic can understand
6
+ * and animate.
7
+ */
8
+ import type { RouterDirection, RouterOptions } from '@ionic/react';
9
+ import type { Action as HistoryAction, Location } from 'history';
10
+ import type { PropsWithChildren } from 'react';
4
11
  import React from 'react';
5
- import type { RouteComponentProps } from 'react-router-dom';
6
- import { ReactRouterViewStack } from './ReactRouterViewStack';
12
+ type HistoryLocation = Location;
7
13
  export interface LocationState {
8
14
  direction?: RouterDirection;
9
- routerOptions?: {
10
- as?: string;
11
- unmount?: boolean;
12
- };
15
+ routerOptions?: RouterOptions;
13
16
  }
14
- interface IonRouteProps extends RouteComponentProps<{}, {}, LocationState> {
15
- registerHistoryListener: (cb: (location: HistoryLocation<any>, action: HistoryAction) => void) => void;
17
+ interface IonRouterProps {
18
+ registerHistoryListener: (cb: (location: HistoryLocation, action: HistoryAction) => void) => void;
16
19
  }
17
- interface IonRouteState {
18
- routeInfo: RouteInfo;
19
- }
20
- declare class IonRouterInner extends React.PureComponent<IonRouteProps, IonRouteState> {
21
- currentTab?: string;
22
- exitViewFromOtherOutletHandlers: ((pathname: string) => ViewItem | undefined)[];
23
- incomingRouteParams?: Partial<RouteInfo>;
24
- locationHistory: LocationHistory;
25
- viewStack: ReactRouterViewStack;
26
- routeMangerContextState: RouteManagerContextState;
27
- constructor(props: IonRouteProps);
28
- handleChangeTab(tab: string, path?: string, routeOptions?: any): void;
29
- handleHistoryChange(location: HistoryLocation<LocationState>, action: HistoryAction): void;
30
- /**
31
- * history@4.x uses goBack(), history@5.x uses back()
32
- * TODO: If support for React Router <=5 is dropped
33
- * this logic is no longer needed. We can just
34
- * assume back() is available.
35
- */
36
- handleNativeBack(): void;
37
- handleNavigate(path: string, routeAction: RouteAction, routeDirection?: RouterDirection, routeAnimation?: AnimationBuilder, routeOptions?: any, tab?: string): void;
38
- handleNavigateBack(defaultHref?: string | RouteInfo, routeAnimation?: AnimationBuilder): void;
39
- handleResetTab(tab: string, originalHref: string, originalRouteOptions: any): void;
40
- handleSetCurrentTab(tab: string): void;
41
- render(): React.JSX.Element;
42
- }
43
- export declare const IonRouter: React.ComponentClass<Pick<IonRouteProps, "registerHistoryListener">, any> & import("react-router").WithRouterStatics<typeof IonRouterInner>;
20
+ export declare const IonRouter: {
21
+ ({ children, registerHistoryListener }: PropsWithChildren<IonRouterProps>): React.JSX.Element;
22
+ displayName: string;
23
+ };
44
24
  export {};
@@ -1,15 +1,68 @@
1
+ /**
2
+ * `ReactRouterViewStack` is a custom navigation manager used in Ionic React
3
+ * apps to map React Router route elements (such as `<IonRoute>`) to "view
4
+ * items" that Ionic can manage in a view stack. This is critical to maintain
5
+ * Ionic’s animation, lifecycle, and history behavior across views.
6
+ */
1
7
  import type { RouteInfo, ViewItem } from '@ionic/react';
2
8
  import { ViewStacks } from '@ionic/react';
3
9
  import React from 'react';
4
10
  export declare class ReactRouterViewStack extends ViewStacks {
11
+ private viewItemCounter;
5
12
  constructor();
6
- createViewItem(outletId: string, reactElement: React.ReactElement, routeInfo: RouteInfo, page?: HTMLElement): ViewItem<any>;
7
- getChildrenToRender(outletId: string, ionRouterOutlet: React.ReactElement, routeInfo: RouteInfo): React.JSX.Element[];
8
- findViewItemByRouteInfo(routeInfo: RouteInfo, outletId?: string, updateMatch?: boolean): ViewItem<any> | undefined;
9
- findLeavingViewItemByRouteInfo(routeInfo: RouteInfo, outletId?: string, mustBeIonRoute?: boolean): ViewItem<any> | undefined;
10
- findViewItemByPathname(pathname: string, outletId?: string): ViewItem<any> | undefined;
11
13
  /**
12
- * Returns the matching view item and the match result for a given pathname.
14
+ * Creates a new view item for the given outlet and react route element.
15
+ * Associates route props with the matched route path for further lookups.
16
+ */
17
+ createViewItem: (outletId: string, reactElement: React.ReactElement, routeInfo: RouteInfo, page?: HTMLElement) => ViewItem<any>;
18
+ /**
19
+ * Renders a ViewLifeCycleManager for the given view item.
20
+ * Handles cleanup if the view no longer matches.
21
+ *
22
+ * - Deactivates view if it no longer matches the current route
23
+ * - Wraps the route element in <Routes> to support nested routing and ensure remounting
24
+ * - Adds a unique key to <Routes> so React Router remounts routes when switching
25
+ */
26
+ private renderViewItem;
27
+ /**
28
+ * Re-renders all active view items for the specified outlet.
29
+ * Ensures React elements are updated with the latest match.
30
+ *
31
+ * 1. Iterates through children of IonRouterOutlet
32
+ * 2. Updates each matching viewItem with the current child React element
33
+ * (important for updating props or changes to elements)
34
+ * 3. Returns a list of React components that will be rendered inside the outlet
35
+ * Each view is wrapped in <ViewLifeCycleManager> to manage lifecycle and rendering
36
+ */
37
+ getChildrenToRender: (outletId: string, ionRouterOutlet: React.ReactElement, routeInfo: RouteInfo) => React.JSX.Element[];
38
+ /**
39
+ * Finds a view item matching the current route, optionally updating its match state.
40
+ */
41
+ findViewItemByRouteInfo: (routeInfo: RouteInfo, outletId?: string, updateMatch?: boolean) => ViewItem<any> | undefined;
42
+ /**
43
+ * Finds the view item that was previously active before a route change.
44
+ */
45
+ findLeavingViewItemByRouteInfo: (routeInfo: RouteInfo, outletId?: string, mustBeIonRoute?: boolean) => ViewItem<any> | undefined;
46
+ /**
47
+ * Finds a view item by pathname only, used in simpler queries.
48
+ */
49
+ findViewItemByPathname: (pathname: string, outletId?: string) => ViewItem<any> | undefined;
50
+ /**
51
+ * Core function that matches a given pathname against all view items.
52
+ * Returns both the matched view item and match metadata.
13
53
  */
14
54
  private findViewItemByPath;
55
+ /**
56
+ * Clean up old, unmounted view items to prevent memory leaks
57
+ */
58
+ private cleanupStaleViewItems;
59
+ /**
60
+ * Override add to prevent duplicate view items with the same ID in the same outlet
61
+ * But allow multiple view items for the same route path (for navigation history)
62
+ */
63
+ add: (viewItem: ViewItem) => void;
64
+ /**
65
+ * Override remove
66
+ */
67
+ remove: (viewItem: ViewItem) => void;
15
68
  }
@@ -0,0 +1,57 @@
1
+ import type React from 'react';
2
+ /**
3
+ * Finds the longest common prefix among an array of paths.
4
+ * Used to determine the scope of an outlet with absolute routes.
5
+ *
6
+ * @param paths An array of absolute path strings.
7
+ * @returns The common prefix shared by all paths.
8
+ */
9
+ export declare const computeCommonPrefix: (paths: string[]) => string;
10
+ /**
11
+ * Checks if a route is a specific match (not wildcard or index).
12
+ *
13
+ * @param route The route element to check.
14
+ * @param remainingPath The remaining path to match against.
15
+ * @returns True if the route specifically matches the remaining path.
16
+ */
17
+ export declare const isSpecificRouteMatch: (route: React.ReactElement, remainingPath: string) => boolean;
18
+ /**
19
+ * Result of parent path computation.
20
+ */
21
+ export interface ParentPathResult {
22
+ parentPath: string | undefined;
23
+ outletMountPath: string | undefined;
24
+ }
25
+ interface RouteAnalysis {
26
+ hasRelativeRoutes: boolean;
27
+ hasIndexRoute: boolean;
28
+ hasWildcardRoute: boolean;
29
+ routeChildren: React.ReactElement[];
30
+ }
31
+ /**
32
+ * Analyzes route children to determine their characteristics.
33
+ *
34
+ * @param routeChildren The route children to analyze.
35
+ * @returns Analysis of the route characteristics.
36
+ */
37
+ export declare const analyzeRouteChildren: (routeChildren: React.ReactElement[]) => RouteAnalysis;
38
+ interface ComputeParentPathOptions {
39
+ currentPathname: string;
40
+ outletMountPath: string | undefined;
41
+ routeChildren: React.ReactElement[];
42
+ hasRelativeRoutes: boolean;
43
+ hasIndexRoute: boolean;
44
+ hasWildcardRoute: boolean;
45
+ }
46
+ /**
47
+ * Computes the parent path for a nested outlet based on the current pathname
48
+ * and the outlet's route configuration.
49
+ *
50
+ * The algorithm finds the shortest parent path where a route matches the remaining path.
51
+ * Priority: specific routes > wildcard routes > index routes (only at mount point)
52
+ *
53
+ * @param options The options for computing the parent path.
54
+ * @returns The computed parent path result.
55
+ */
56
+ export declare const computeParentPath: (options: ComputeParentPathOptions) => ParentPathResult;
57
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { PathMatch } from 'react-router';
2
+ /**
3
+ * Options for the matchPath function.
4
+ */
5
+ interface MatchPathOptions {
6
+ /**
7
+ * The pathname to match against.
8
+ */
9
+ pathname: string;
10
+ /**
11
+ * The props to match against, they are identical to the matching props `Route` accepts.
12
+ */
13
+ componentProps: {
14
+ path?: string;
15
+ caseSensitive?: boolean;
16
+ end?: boolean;
17
+ index?: boolean;
18
+ };
19
+ }
20
+ /**
21
+ * The matchPath function is used only for matching paths, not rendering components or elements.
22
+ * @see https://reactrouter.com/v6/utils/match-path
23
+ */
24
+ export declare const matchPath: ({ pathname, componentProps }: MatchPathOptions) => PathMatch<string> | null;
25
+ /**
26
+ * Determines the portion of a pathname that a given route pattern should match against.
27
+ * For absolute route patterns we return the full pathname. For relative patterns we
28
+ * strip off the already-matched parent segments so React Router receives the remainder.
29
+ */
30
+ export declare const derivePathnameToMatch: (fullPathname: string, routePath?: string) => string;
31
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Ensures the given path has a leading slash.
3
+ *
4
+ * @param value The path string to normalize.
5
+ * @returns The path with a leading slash.
6
+ */
7
+ export declare const ensureLeadingSlash: (value: string) => string;
8
+ /**
9
+ * Strips the trailing slash from a path, unless it's the root path.
10
+ *
11
+ * @param value The path string to normalize.
12
+ * @returns The path without a trailing slash.
13
+ */
14
+ export declare const stripTrailingSlash: (value: string) => string;
15
+ /**
16
+ * Normalizes a pathname for comparison by ensuring a leading slash
17
+ * and removing trailing slashes.
18
+ *
19
+ * @param value The pathname to normalize, can be undefined.
20
+ * @returns A normalized pathname string.
21
+ */
22
+ export declare const normalizePathnameForComparison: (value: string | undefined) => string;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ /**
3
+ * Extracts the children from a Routes wrapper component.
4
+ * The use of `<Routes />` is encouraged with React Router v6.
5
+ *
6
+ * @param node The React node to extract Routes children from.
7
+ * @returns The children of the Routes component, or undefined if not found.
8
+ */
9
+ export declare const getRoutesChildren: (node: React.ReactNode) => React.ReactNode | undefined;
10
+ /**
11
+ * Extracts Route children from a node (either directly or from a Routes wrapper).
12
+ *
13
+ * @param children The children to extract routes from.
14
+ * @returns An array of Route elements.
15
+ */
16
+ export declare const extractRouteChildren: (children: React.ReactNode) => React.ReactElement[];
17
+ /**
18
+ * Checks if a React element is a Navigate component (redirect).
19
+ *
20
+ * @param element The element to check.
21
+ * @returns True if the element is a Navigate component.
22
+ */
23
+ export declare const isNavigateElement: (element: unknown) => boolean;
@@ -0,0 +1,10 @@
1
+ import type { ViewItem } from '@ionic/react';
2
+ /**
3
+ * Sorts view items by route specificity (most specific first).
4
+ * - Exact matches (no wildcards/params) come first
5
+ * - Among wildcard routes, longer paths are more specific
6
+ *
7
+ * @param views The view items to sort.
8
+ * @returns A new sorted array of view items.
9
+ */
10
+ export declare const sortViewsBySpecificity: (views: ViewItem[]) => ViewItem[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionic/react-router",
3
- "version": "8.7.12",
3
+ "version": "8.7.13-dev.11765426479.16a61ecf",
4
4
  "description": "React Router wrapper for @ionic/react",
5
5
  "keywords": [
6
6
  "ionic",
@@ -36,14 +36,14 @@
36
36
  "dist/"
37
37
  ],
38
38
  "dependencies": {
39
- "@ionic/react": "8.7.12",
39
+ "@ionic/react": "8.7.13-dev.11765426479.16a61ecf",
40
40
  "tslib": "*"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": ">=16.8.6",
44
44
  "react-dom": ">=16.8.6",
45
- "react-router": "^5.0.1",
46
- "react-router-dom": "^5.0.1"
45
+ "react-router": ">=6.0.0",
46
+ "react-router-dom": ">=6.0.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@ionic/eslint-config": "^0.3.0",
@@ -52,16 +52,15 @@
52
52
  "@types/node": "^14.0.14",
53
53
  "@types/react": "^17.0.79",
54
54
  "@types/react-dom": "^17.0.25",
55
- "@types/react-router": "^5.0.3",
56
- "@types/react-router-dom": "^5.1.5",
57
55
  "@typescript-eslint/eslint-plugin": "^5.48.2",
58
56
  "@typescript-eslint/parser": "^5.48.2",
59
57
  "eslint": "^7.32.0",
58
+ "history": "^5.3.0",
60
59
  "prettier": "^2.8.3",
61
60
  "react": "^17.0.2",
62
61
  "react-dom": "^17.0.2",
63
- "react-router": "^5.0.1",
64
- "react-router-dom": "^5.0.1",
62
+ "react-router": "^6.30.0",
63
+ "react-router-dom": "^6.30.0",
65
64
  "rimraf": "^3.0.2",
66
65
  "rollup": "^4.2.0",
67
66
  "typescript": "^4.0.5"
@@ -1,30 +0,0 @@
1
- import type { RouteInfo, StackContextState, ViewItem } from '@ionic/react';
2
- import { RouteManagerContext } from '@ionic/react';
3
- import React from 'react';
4
- interface StackManagerProps {
5
- routeInfo: RouteInfo;
6
- }
7
- interface StackManagerState {
8
- }
9
- export declare class StackManager extends React.PureComponent<StackManagerProps, StackManagerState> {
10
- id: string;
11
- context: React.ContextType<typeof RouteManagerContext>;
12
- ionRouterOutlet?: React.ReactElement;
13
- routerOutletElement: HTMLIonRouterOutletElement | undefined;
14
- prevProps?: StackManagerProps;
15
- skipTransition: boolean;
16
- stackContextValue: StackContextState;
17
- private clearOutletTimeout;
18
- private pendingPageTransition;
19
- constructor(props: StackManagerProps);
20
- componentDidMount(): void;
21
- componentDidUpdate(prevProps: StackManagerProps): void;
22
- componentWillUnmount(): void;
23
- handlePageTransition(routeInfo: RouteInfo): Promise<void>;
24
- registerIonPage(page: HTMLElement, routeInfo: RouteInfo): void;
25
- setupRouterOutlet(routerOutlet: HTMLIonRouterOutletElement): Promise<void>;
26
- transitionPage(routeInfo: RouteInfo, enteringViewItem: ViewItem, leavingViewItem?: ViewItem, direction?: 'forward' | 'back', progressAnimation?: boolean): Promise<void>;
27
- render(): React.JSX.Element;
28
- static get contextType(): React.Context<import("@ionic/react").RouteManagerContextState>;
29
- }
30
- export default StackManager;
@@ -1,21 +0,0 @@
1
- import { matchPath as reactRouterMatchPath } from 'react-router';
2
- interface MatchPathOptions {
3
- /**
4
- * The pathname to match against.
5
- */
6
- pathname: string;
7
- /**
8
- * The props to match against, they are identical to the matching props `Route` accepts.
9
- */
10
- componentProps: {
11
- path?: string;
12
- from?: string;
13
- component?: any;
14
- exact?: boolean;
15
- };
16
- }
17
- /**
18
- * @see https://v5.reactrouter.com/web/api/matchPath
19
- */
20
- export declare const matchPath: ({ pathname, componentProps, }: MatchPathOptions) => false | ReturnType<typeof reactRouterMatchPath>;
21
- export {};