clear-react-router 1.6.3 → 1.6.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.
- package/README.md +24 -7
- package/dist/components/Router.d.ts +1 -1
- package/dist/components/RouterProvider.d.ts +2 -2
- package/dist/config/routerConfig.d.ts +1 -1
- package/dist/hooks/useHandleNavigation.d.ts +3 -3
- package/dist/hooks/useLoader.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +27 -26
- package/dist/types/global.d.ts +12 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ It provides first-class support for:
|
|
|
20
20
|
- **Navigation Blocking** - Prevent accidental navigation with `useBlocker`
|
|
21
21
|
- **Smooth Animations** - Page transitions with fade effect (customizable duration)
|
|
22
22
|
- **Static Layout** — Keep navbar, footer, and other elements outside the router to avoid unnecessary re-renders
|
|
23
|
-
- **
|
|
23
|
+
- **Programmatic Redirects** - Redirect from beforeLoad hook
|
|
24
24
|
- **Cache invalidation** - Manual route invalidation
|
|
25
25
|
- **Prefetching** - Preload data on hover for instant navigation
|
|
26
26
|
- **Lazy Loading** - Code-split your routes with dynamic imports for optimal performance
|
|
@@ -55,7 +55,7 @@ The root component that provides routing context to the application. Place stati
|
|
|
55
55
|
|
|
56
56
|
| Prop | Type | Default | Description |
|
|
57
57
|
|------|------|---------|-------------|
|
|
58
|
-
| `
|
|
58
|
+
| `routes` | `RouteItem[]` | required | Array of route configurations |
|
|
59
59
|
| `context` | `object` | `{}` | Initial context (user, theme, etc.) |
|
|
60
60
|
| `children` | `ReactNode` | required | App content (must include `<Router />`) |
|
|
61
61
|
|
|
@@ -83,12 +83,13 @@ Renders the current route's component. Must be placed inside `<RouterProvider>`.
|
|
|
83
83
|
| `animationDuration` | `number` | `optional` | Animation duration in milliseconds (browser default is used if not set) |
|
|
84
84
|
| `spinner` | `boolean \| undefined` | `true` | Show a small spinner in the corner while loading data (only when `isAnimated` is enabled) |
|
|
85
85
|
| `preserveScroll` | `boolean \| undefined` | `true` | Save and restore scroll position when navigating between pages |
|
|
86
|
-
| `
|
|
86
|
+
| `showFallbackOnAnimation` | `boolean \| undefined` | `false` | Show `loaderFallback` even when `isAnimated` is `true` (instead of spinner) |
|
|
87
87
|
| `prefetch` | `'hover' \| 'render' \| 'viewport' \| 'none'` | `'hover'` | Default prefetch strategy for all `<Link>` components |
|
|
88
88
|
| `hoverPrefetchDelay` | `number` | `150` | Delay in milliseconds before prefetching on hover (only for `'hover'` strategy) |
|
|
89
|
+
| `errorBoundary` | `ComponentType<{ children: ReactNode }>` | `undefined` | Custom error boundary component for catching render errors in route components |
|
|
89
90
|
|
|
90
91
|
```
|
|
91
|
-
<RouterProvider
|
|
92
|
+
<RouterProvider routes={routes}>
|
|
92
93
|
<Navbar />
|
|
93
94
|
<Router spinner={false} isAnimated /> {/* disable the spinner */}
|
|
94
95
|
</RouterProvider>
|
|
@@ -122,7 +123,7 @@ Component for client-side navigation with prefetch support.
|
|
|
122
123
|
import { RouterProvider, Router, Link } from 'clear-react-router';
|
|
123
124
|
|
|
124
125
|
// Global prefetch: hover with 100ms delay
|
|
125
|
-
<RouterProvider
|
|
126
|
+
<RouterProvider routes={routes} prefetch="hover" hoverPrefetchDelay={100}>
|
|
126
127
|
<Router />
|
|
127
128
|
</RouterProvider>
|
|
128
129
|
|
|
@@ -216,6 +217,23 @@ const routes = createRouter([
|
|
|
216
217
|
]);
|
|
217
218
|
```
|
|
218
219
|
|
|
220
|
+
### Error Boundaries
|
|
221
|
+
|
|
222
|
+
You can provide a custom error boundary to catch rendering errors in route components. This is useful for preventing the entire app from crashing when a specific route fails to render.
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
import { RouterProvider, Router } from 'clear-react-router';
|
|
226
|
+
import { routes } from './routes';
|
|
227
|
+
import { ErrorBoundary } from './components/ErrorBoundary';
|
|
228
|
+
|
|
229
|
+
const App = () => (
|
|
230
|
+
<RouterProvider routes={routes}>
|
|
231
|
+
<Router errorBoundary={ErrorBoundary} />
|
|
232
|
+
</RouterProvider>
|
|
233
|
+
);
|
|
234
|
+
```
|
|
235
|
+
**Note:** The `errorBoundary` prop only catches render-time errors in route components. It does not catch errors in `loader` or `beforeLoad` — those are handled by the router's `errorElement` mechanism.
|
|
236
|
+
|
|
219
237
|
## Hooks
|
|
220
238
|
|
|
221
239
|
### `useNavigate()`
|
|
@@ -285,7 +303,7 @@ const UserProfile = () => {
|
|
|
285
303
|
}
|
|
286
304
|
```
|
|
287
305
|
|
|
288
|
-
### `useInvalidate`
|
|
306
|
+
### `useInvalidate()`
|
|
289
307
|
|
|
290
308
|
Returns a function that marks route data as stale and re-runs the route lifecycle.
|
|
291
309
|
|
|
@@ -566,7 +584,6 @@ function ProductFilter() {
|
|
|
566
584
|
|
|
567
585
|
- **Array support** — `getSearchParams` returns `string[]` when multiple values exist for the same key
|
|
568
586
|
- **Functional updates** — Update parameters based on previous state without losing other params
|
|
569
|
-
- **Type-safe** — Proper TypeScript support with overloads
|
|
570
587
|
- **Stable reference** — `setSearchParams` reference is stable and safe to use in `useEffect`
|
|
571
588
|
|
|
572
589
|
> **Note:** `getSearchParams` returns `string` for single values, `string[]` for multiple values, and `''` if the key is not found.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { RouterProps } from '../types/global';
|
|
2
|
-
export declare const Router: ({ isAnimated, animationDuration, spinner, preserveScroll,
|
|
2
|
+
export declare const Router: ({ isAnimated, animationDuration, spinner, preserveScroll, showFallbackOnAnimation, prefetch, hoverPrefetchDelay, errorBoundary: ErrorBoundary, }: RouterProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -2,8 +2,8 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
import { RouteItem } from '../types/global';
|
|
3
3
|
type RouteProviderProps = {
|
|
4
4
|
children: ReactNode;
|
|
5
|
-
|
|
5
|
+
routes: RouteItem[];
|
|
6
6
|
context?: Record<string, unknown>;
|
|
7
7
|
};
|
|
8
|
-
export declare const RouterProvider: ({ children,
|
|
8
|
+
export declare const RouterProvider: ({ children, routes, context: initialContext }: RouteProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
9
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RouterProps } from '../types/global';
|
|
2
2
|
declare class RouterConfig {
|
|
3
3
|
isAnimated: boolean;
|
|
4
|
-
|
|
4
|
+
showFallbackOnAnimation: boolean;
|
|
5
5
|
prefetch: RouterProps['prefetch'];
|
|
6
6
|
hoverPrefetchDelay: number;
|
|
7
7
|
configure(config: Partial<RouterConfig>): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Dispatch, RefObject, type SetStateAction } from 'react';
|
|
2
2
|
import { BlockerState, LoaderState, Location, RevalidateCacheArgs, RouteItem, RouteItemData, UpdateBlockedRouteProps } from '../types/global';
|
|
3
3
|
type UseHandleNavigation = {
|
|
4
|
-
|
|
4
|
+
routes: RouteItem[];
|
|
5
5
|
context: Record<string, unknown>;
|
|
6
6
|
revalidateCache(arg: RevalidateCacheArgs): Promise<unknown>;
|
|
7
7
|
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
@@ -12,13 +12,13 @@ type UseHandleNavigation = {
|
|
|
12
12
|
loaderStateRef: RefObject<LoaderState>;
|
|
13
13
|
clearTimestamp(path: string): void;
|
|
14
14
|
};
|
|
15
|
-
export declare const useHandleNavigation: ({
|
|
15
|
+
export declare const useHandleNavigation: ({ routes, context, revalidateCache, setContext, isCacheItemFresh, loaderStateRef, clearTimestamp, }: UseHandleNavigation) => {
|
|
16
16
|
blockerState: BlockerState;
|
|
17
17
|
updateLocation: (nextLocation: Location) => Promise<void>;
|
|
18
18
|
updateBlockedRoute: ({ type, payload }: UpdateBlockedRouteProps) => void;
|
|
19
19
|
routeItemData: RouteItemData;
|
|
20
20
|
restoreScroll: () => void;
|
|
21
|
-
currentLoaderFallback: import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | (() => import("react").ReactElement) | undefined;
|
|
21
|
+
currentLoaderFallback: (import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | (() => import("react").ReactElement)) | undefined;
|
|
22
22
|
isLoading: boolean;
|
|
23
23
|
loaderState: LoaderState;
|
|
24
24
|
invalidate: (pathname?: string) => Promise<void>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type Dispatch, type SetStateAction } from 'react';
|
|
2
2
|
import type { LoaderState, RevalidateCacheArgs, RouteItem } from '../types/global';
|
|
3
3
|
type UseLoaderParams = {
|
|
4
|
-
|
|
4
|
+
routes: RouteItem[];
|
|
5
5
|
context: Record<string, unknown>;
|
|
6
6
|
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
7
7
|
};
|
|
8
|
-
export declare const useLoader: ({
|
|
8
|
+
export declare const useLoader: ({ routes, context, setContext }: UseLoaderParams) => {
|
|
9
9
|
prefetchLoader: (pathname: string) => Promise<void>;
|
|
10
10
|
revalidateCache: ({ routeItem, pathname }: RevalidateCacheArgs) => Promise<unknown>;
|
|
11
11
|
isCacheItemFresh: ({ routeItem, pathname }: {
|
package/dist/index.d.ts
CHANGED
|
@@ -14,4 +14,4 @@ export { useSearchParams } from './hooks/useSearchParams';
|
|
|
14
14
|
export { useHistoricalTrail } from './hooks/useHistoricalTrail';
|
|
15
15
|
export { adapter } from './utils/adapter';
|
|
16
16
|
export { createRouter } from './utils/utils';
|
|
17
|
-
export type { RouteItem, BlockerState, Location, AdapterType } from './types/global';
|
|
17
|
+
export type { RouteItem, BlockerState, Location, AdapterType, RouterProps } from './types/global';
|
package/dist/index.js
CHANGED
|
@@ -125,7 +125,7 @@ function _defineProperty(e, r, t) {
|
|
|
125
125
|
var RouterConfig = class {
|
|
126
126
|
constructor() {
|
|
127
127
|
_defineProperty(this, "isAnimated", false);
|
|
128
|
-
_defineProperty(this, "
|
|
128
|
+
_defineProperty(this, "showFallbackOnAnimation", false);
|
|
129
129
|
_defineProperty(this, "prefetch", "hover");
|
|
130
130
|
_defineProperty(this, "hoverPrefetchDelay", 150);
|
|
131
131
|
}
|
|
@@ -188,8 +188,8 @@ var comparePaths = (el, pathname) => {
|
|
|
188
188
|
//#endregion
|
|
189
189
|
//#region hooks/useHandleNavigation.ts
|
|
190
190
|
var ALL_LOCATIONS = "*";
|
|
191
|
-
var useHandleNavigation = ({
|
|
192
|
-
const { isAnimated,
|
|
191
|
+
var useHandleNavigation = ({ routes, context, revalidateCache, setContext, isCacheItemFresh, loaderStateRef, clearTimestamp }) => {
|
|
192
|
+
const { isAnimated, showFallbackOnAnimation: showFallback } = routerConfig;
|
|
193
193
|
const [isLoading, setIsLoading] = useState(false);
|
|
194
194
|
const [blockedRoute, setBlockedRoute] = useState({
|
|
195
195
|
from: "",
|
|
@@ -240,7 +240,7 @@ var useHandleNavigation = ({ routeList, context, revalidateCache, setContext, is
|
|
|
240
240
|
}, [navigation, isAnimated]);
|
|
241
241
|
const invalidate = useCallback(async (pathname = routeItemData.location.pathname) => {
|
|
242
242
|
if (typeof pathname !== "string") return;
|
|
243
|
-
const routeItem =
|
|
243
|
+
const routeItem = routes.find((el) => comparePaths(el, pathname));
|
|
244
244
|
const resultParams = getParamsObject({
|
|
245
245
|
params: routeItem?.params,
|
|
246
246
|
pathname
|
|
@@ -274,14 +274,14 @@ var useHandleNavigation = ({ routeList, context, revalidateCache, setContext, is
|
|
|
274
274
|
loaderStateRef,
|
|
275
275
|
revalidateCache,
|
|
276
276
|
routeItemData.location.pathname,
|
|
277
|
-
|
|
277
|
+
routes,
|
|
278
278
|
setContext
|
|
279
279
|
]);
|
|
280
280
|
const navigationHandler = useCallback(async (nextLocation) => {
|
|
281
281
|
navigationSeq.current = navigationSeq.current + 1;
|
|
282
282
|
const seq = navigationSeq.current;
|
|
283
283
|
loaderStateRef.current = emptyLoaderState;
|
|
284
|
-
const nextItem =
|
|
284
|
+
const nextItem = routes.find((el) => el.path === ALL_LOCATIONS || comparePaths(el, nextLocation.pathname));
|
|
285
285
|
const params = getParamsObject({
|
|
286
286
|
params: nextItem?.params,
|
|
287
287
|
pathname: nextLocation.pathname
|
|
@@ -337,7 +337,7 @@ var useHandleNavigation = ({ routeList, context, revalidateCache, setContext, is
|
|
|
337
337
|
}, [
|
|
338
338
|
context,
|
|
339
339
|
revalidateCache,
|
|
340
|
-
|
|
340
|
+
routes,
|
|
341
341
|
transitionedNavigation,
|
|
342
342
|
setContext,
|
|
343
343
|
isCacheItemFresh,
|
|
@@ -407,7 +407,7 @@ var useHandleNavigation = ({ routeList, context, revalidateCache, setContext, is
|
|
|
407
407
|
};
|
|
408
408
|
//#endregion
|
|
409
409
|
//#region hooks/useLoader.ts
|
|
410
|
-
var useLoader = ({
|
|
410
|
+
var useLoader = ({ routes, context, setContext }) => {
|
|
411
411
|
const timestampMapRef = useRef(/* @__PURE__ */ new Map());
|
|
412
412
|
const loaderMapRef = useRef({});
|
|
413
413
|
const loaderStateRef = useRef(emptyLoaderState);
|
|
@@ -467,12 +467,12 @@ var useLoader = ({ routeList, context, setContext }) => {
|
|
|
467
467
|
]);
|
|
468
468
|
return {
|
|
469
469
|
prefetchLoader: useCallback(async (pathname) => {
|
|
470
|
-
const item =
|
|
470
|
+
const item = routes.find((el) => comparePaths(el, pathname));
|
|
471
471
|
if (item) await revalidateCache({
|
|
472
472
|
routeItem: item,
|
|
473
473
|
pathname
|
|
474
474
|
});
|
|
475
|
-
}, [revalidateCache,
|
|
475
|
+
}, [revalidateCache, routes]),
|
|
476
476
|
revalidateCache,
|
|
477
477
|
isCacheItemFresh,
|
|
478
478
|
loaderStateRef,
|
|
@@ -483,15 +483,15 @@ var useLoader = ({ routeList, context, setContext }) => {
|
|
|
483
483
|
};
|
|
484
484
|
//#endregion
|
|
485
485
|
//#region components/RouterProvider.tsx
|
|
486
|
-
var RouterProvider = ({ children,
|
|
486
|
+
var RouterProvider = ({ children, routes, context: initialContext = {} }) => {
|
|
487
487
|
const [context, setContext] = useState(initialContext);
|
|
488
488
|
const { prefetchLoader, revalidateCache, isCacheItemFresh, loaderStateRef, clearTimestamp } = useLoader({
|
|
489
|
-
|
|
489
|
+
routes,
|
|
490
490
|
context,
|
|
491
491
|
setContext
|
|
492
492
|
});
|
|
493
493
|
const { blockerState, updateLocation, updateBlockedRoute, routeItemData, restoreScroll, currentLoaderFallback, isLoading, loaderState, invalidate } = useHandleNavigation({
|
|
494
|
-
|
|
494
|
+
routes,
|
|
495
495
|
context,
|
|
496
496
|
setContext,
|
|
497
497
|
revalidateCache,
|
|
@@ -590,6 +590,11 @@ var usePreserveScroll = (preserveScroll) => {
|
|
|
590
590
|
]);
|
|
591
591
|
};
|
|
592
592
|
//#endregion
|
|
593
|
+
//#region hooks/useSetRouterConfig.ts
|
|
594
|
+
var useSetRouterConfig = (routerProps) => {
|
|
595
|
+
useEffect(() => routerConfig.configure(routerProps), [routerProps]);
|
|
596
|
+
};
|
|
597
|
+
//#endregion
|
|
593
598
|
//#region components/Spinner.tsx
|
|
594
599
|
var Spinner = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cr-spinner" });
|
|
595
600
|
//#endregion
|
|
@@ -599,32 +604,28 @@ var renderElement = (Component) => {
|
|
|
599
604
|
return typeof Component === "function" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, {}) : Component;
|
|
600
605
|
};
|
|
601
606
|
//#endregion
|
|
602
|
-
//#region hooks/useSetRouterConfig.ts
|
|
603
|
-
var useSetRouterConfig = (routerProps) => {
|
|
604
|
-
useEffect(() => routerConfig.configure(routerProps), [routerProps]);
|
|
605
|
-
};
|
|
606
|
-
//#endregion
|
|
607
607
|
//#region components/Router.tsx
|
|
608
|
-
var
|
|
609
|
-
|
|
608
|
+
var EmptyBoundary = ({ children }) => children;
|
|
609
|
+
var Router = ({ isAnimated, animationDuration, spinner = true, preserveScroll = true, showFallbackOnAnimation = false, prefetch = "hover", hoverPrefetchDelay = 150, errorBoundary: ErrorBoundary = EmptyBoundary }) => {
|
|
610
|
+
const { routeItemData: { routeItem, location }, loaderState, currentLoaderFallback, isLoading } = useNavigationState();
|
|
610
611
|
usePreserveScroll(preserveScroll);
|
|
611
612
|
useApplyCustomAnimation(animationDuration);
|
|
612
613
|
useSetRouterConfig({
|
|
613
614
|
isAnimated,
|
|
614
|
-
|
|
615
|
+
showFallbackOnAnimation,
|
|
615
616
|
prefetch,
|
|
616
617
|
hoverPrefetchDelay
|
|
617
618
|
});
|
|
618
619
|
const showErrorElement = !isLoading && Boolean(loaderState.loaderError || loaderState.beforeLoadError);
|
|
619
620
|
const showSpinner = spinner && isAnimated && isLoading;
|
|
620
621
|
const loadingContent = !showErrorElement && isLoading;
|
|
621
|
-
if ((
|
|
622
|
-
if (!
|
|
622
|
+
if ((showFallbackOnAnimation || !isAnimated) && loadingContent) return renderElement(currentLoaderFallback);
|
|
623
|
+
if (!showFallbackOnAnimation && isAnimated && loadingContent) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {});
|
|
623
624
|
if (!routeItem) return null;
|
|
624
625
|
if (showErrorElement) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [renderElement(routeItem.errorElement), showSpinner && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {})] });
|
|
625
626
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
626
627
|
style: { viewTransitionName: "page" },
|
|
627
|
-
children: [renderElement(routeItem.element)
|
|
628
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorBoundary, { children: renderElement(routeItem.element) }, location.pathname), showSpinner && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {})]
|
|
628
629
|
});
|
|
629
630
|
};
|
|
630
631
|
//#endregion
|
|
@@ -710,11 +711,11 @@ var Link = ({ children, to, prefetch: prefetchLink, hoverPrefetchDelay }) => {
|
|
|
710
711
|
//#endregion
|
|
711
712
|
//#region hooks/useParams.ts
|
|
712
713
|
var useParams = () => {
|
|
713
|
-
const { routeItemData: { routeItem } } = useNavigationState();
|
|
714
|
+
const { routeItemData: { routeItem, location: { pathname } } } = useNavigationState();
|
|
714
715
|
if (!routeItem) return void 0;
|
|
715
716
|
return getParamsObject({
|
|
716
717
|
params: routeItem?.params,
|
|
717
|
-
pathname
|
|
718
|
+
pathname
|
|
718
719
|
});
|
|
719
720
|
};
|
|
720
721
|
//#endregion
|
package/dist/types/global.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import type { ComponentType, Dispatch, ReactElement, SetStateAction } from 'react';
|
|
1
|
+
import type { ComponentType, Dispatch, ReactElement, ReactNode, SetStateAction } from 'react';
|
|
2
2
|
export type LazyComponent = () => Promise<{
|
|
3
3
|
default: ComponentType<unknown>;
|
|
4
4
|
}>;
|
|
5
|
+
type Element = (() => ReactElement) | ReactElement;
|
|
5
6
|
export type ClientRouteItem = {
|
|
6
7
|
path: string;
|
|
7
|
-
element:
|
|
8
|
+
element: Element | LazyComponent;
|
|
8
9
|
loader?(arg: {
|
|
9
10
|
params: Record<string, string>;
|
|
10
11
|
context: Record<string, unknown>;
|
|
11
12
|
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
12
13
|
}): Promise<unknown>;
|
|
13
|
-
loaderFallback?:
|
|
14
|
-
errorElement?:
|
|
15
|
-
fallback?:
|
|
14
|
+
loaderFallback?: Element;
|
|
15
|
+
errorElement?: Element;
|
|
16
|
+
fallback?: Element;
|
|
16
17
|
children?: ClientRouteItem[];
|
|
17
18
|
staleTime?: number;
|
|
18
19
|
beforeLoad?: (arg: {
|
|
@@ -28,7 +29,7 @@ export type ClientRouteItem = {
|
|
|
28
29
|
}) => Promise<void>;
|
|
29
30
|
};
|
|
30
31
|
export type RouteItem = ClientRouteItem & {
|
|
31
|
-
element:
|
|
32
|
+
element: Element;
|
|
32
33
|
params?: {
|
|
33
34
|
key: string;
|
|
34
35
|
value: string;
|
|
@@ -67,7 +68,11 @@ export type RouterProps = {
|
|
|
67
68
|
animationDuration?: number;
|
|
68
69
|
spinner?: boolean;
|
|
69
70
|
preserveScroll?: boolean;
|
|
70
|
-
|
|
71
|
+
showFallbackOnAnimation?: boolean;
|
|
71
72
|
prefetch?: 'hover' | 'render' | 'viewport' | 'none';
|
|
72
73
|
hoverPrefetchDelay?: number;
|
|
74
|
+
errorBoundary?: ComponentType<{
|
|
75
|
+
children: ReactNode;
|
|
76
|
+
}>;
|
|
73
77
|
};
|
|
78
|
+
export {};
|