clear-react-router 1.9.3 → 1.9.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 +25 -1
- package/dist/components/Link.d.ts +19 -5
- package/dist/index.js +20 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,6 +107,8 @@ Component for client-side navigation with prefetch support, active state detecti
|
|
|
107
107
|
| Prop | Type | Default | Description |
|
|
108
108
|
|------|------|---------|-------------|
|
|
109
109
|
| `to` | `string` | required | Target path |
|
|
110
|
+
| `as` | `(props: ElementProps<T>) => ReactElement` | renders `<a>` | Render prop for using a custom element/component instead of the default `<a>`. Receives the computed isActive and isPending values, event handlers, and ref to attach to your own element |
|
|
111
|
+
| `exact` | `boolean` | `false` | When `false`, the link is also considered active if the current URL starts with `to` (useful for nested routes) |
|
|
110
112
|
| `prefetch` | `'hover' \| 'render' \| 'viewport' \| 'none'` | `Router` config | Override the global prefetch strategy |
|
|
111
113
|
| `hoverPrefetchDelay` | `number` | `Router` config | Override the global hover delay |
|
|
112
114
|
| `children` | `ReactNode` | required | Content to render inside the link |
|
|
@@ -120,7 +122,7 @@ Component for client-side navigation with prefetch support, active state detecti
|
|
|
120
122
|
|
|
121
123
|
| State | Type | Description |
|
|
122
124
|
|-------|------|-------------|
|
|
123
|
-
| `isActive` | `boolean` | `true` when the link's `to` matches the current URL |
|
|
125
|
+
| `isActive` | `boolean` | `true` when the link's `to` matches the current URL considering `exact` value |
|
|
124
126
|
| `isPending` | `boolean` | `true` when the target route is currently loading (loader is running) |
|
|
125
127
|
|
|
126
128
|
### Prefetch Strategies
|
|
@@ -137,6 +139,22 @@ Component for client-side navigation with prefetch support, active state detecti
|
|
|
137
139
|
```tsx
|
|
138
140
|
import { Router, Link } from 'clear-react-router';
|
|
139
141
|
|
|
142
|
+
// Render a custom element/component via `as`. The function receives ref, event handlers, isActive/isPending and must render them itself
|
|
143
|
+
import { Button } from '@mui/material';
|
|
144
|
+
|
|
145
|
+
<Link
|
|
146
|
+
to="/dashboard"
|
|
147
|
+
as={({ isActive, isPending, ...props }) => (
|
|
148
|
+
<Button
|
|
149
|
+
{...props}
|
|
150
|
+
variant={isActive ? 'contained' : 'outlined'}
|
|
151
|
+
sx={{ opacity: isPending ? 0.5 : 1 }}
|
|
152
|
+
/>
|
|
153
|
+
)}
|
|
154
|
+
>
|
|
155
|
+
Dashboard
|
|
156
|
+
</Link>
|
|
157
|
+
|
|
140
158
|
// Global prefetch: hover with 100ms delay
|
|
141
159
|
<Router routes={routes} prefetch="hover" hoverPrefetchDelay={100} />
|
|
142
160
|
|
|
@@ -169,6 +187,12 @@ import { Router, Link } from 'clear-react-router';
|
|
|
169
187
|
<Link to="/details" beforeNavigate={saveDashboardData}>
|
|
170
188
|
Admin Panel
|
|
171
189
|
</Link>
|
|
190
|
+
|
|
191
|
+
// `exact={false}` — active for nested routes too
|
|
192
|
+
// e.g. active when current URL is "/settings" or "/settings/profile"
|
|
193
|
+
<Link to="/settings" exact={false}>
|
|
194
|
+
Settings
|
|
195
|
+
</Link>
|
|
172
196
|
```
|
|
173
197
|
**Important**: prefetch="render" should be used sparingly, as it preloads data immediately when the link is rendered, which may cause unnecessary network requests.
|
|
174
198
|
|
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
import { type CSSProperties, ReactNode,
|
|
1
|
+
import { type CSSProperties, ReactNode, MouseEvent, ReactElement, Ref } from 'react';
|
|
2
2
|
import { RouterProps } from '../types';
|
|
3
3
|
type States = {
|
|
4
4
|
isActive: boolean;
|
|
5
5
|
isPending: boolean;
|
|
6
6
|
};
|
|
7
|
-
type
|
|
7
|
+
type ElementProps<T extends HTMLElement = HTMLElement> = {
|
|
8
|
+
ref: Ref<T>;
|
|
9
|
+
href: string;
|
|
10
|
+
isActive: boolean;
|
|
11
|
+
isPending: boolean;
|
|
12
|
+
onClick(event: MouseEvent): void;
|
|
13
|
+
onMouseEnter(event: MouseEvent): void;
|
|
14
|
+
onMouseLeave(event: MouseEvent): void;
|
|
15
|
+
className?: string;
|
|
16
|
+
style?: CSSProperties;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
};
|
|
19
|
+
type LinkProps<T extends HTMLElement = HTMLAnchorElement> = {
|
|
8
20
|
to: string;
|
|
9
|
-
children
|
|
21
|
+
children?: ReactNode;
|
|
22
|
+
as?: (props: ElementProps<T>) => ReactElement;
|
|
10
23
|
prefetch?: RouterProps['prefetch'];
|
|
11
24
|
hoverPrefetchDelay?: number;
|
|
12
|
-
style?: CSSProperties | ((arg: States) => CSSProperties);
|
|
13
25
|
className?: string | ((arg: States) => string);
|
|
14
26
|
activeClassName?: string;
|
|
15
27
|
pendingClassName?: string;
|
|
16
28
|
beforeNavigate?(): Promise<void>;
|
|
29
|
+
style?: CSSProperties | ((arg: States) => CSSProperties);
|
|
30
|
+
exact?: boolean;
|
|
17
31
|
};
|
|
18
|
-
export declare const Link: ({ children, to, prefetch: prefetchLink, hoverPrefetchDelay, className, style, beforeNavigate, activeClassName, pendingClassName, }: LinkProps) => import("react
|
|
32
|
+
export declare const Link: <T extends HTMLElement = HTMLAnchorElement>({ children, to, as, prefetch: prefetchLink, hoverPrefetchDelay, className, style, beforeNavigate, exact, activeClassName, pendingClassName, }: LinkProps<T>) => ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
19
33
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -44,7 +44,7 @@ var createCommitState = ({ routeItemDataState, pendingState }) => (nextLocation,
|
|
|
44
44
|
//#region constants.ts
|
|
45
45
|
var emptyLoaderState = {};
|
|
46
46
|
//#endregion
|
|
47
|
-
//#region \0@oxc-project+runtime@0.
|
|
47
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/typeof.js
|
|
48
48
|
function _typeof(o) {
|
|
49
49
|
"@babel/helpers - typeof";
|
|
50
50
|
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
@@ -54,7 +54,7 @@ function _typeof(o) {
|
|
|
54
54
|
}, _typeof(o);
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
|
-
//#region \0@oxc-project+runtime@0.
|
|
57
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/toPrimitive.js
|
|
58
58
|
function toPrimitive(t, r) {
|
|
59
59
|
if ("object" != _typeof(t) || !t) return t;
|
|
60
60
|
var e = t[Symbol.toPrimitive];
|
|
@@ -66,13 +66,13 @@ function toPrimitive(t, r) {
|
|
|
66
66
|
return ("string" === r ? String : Number)(t);
|
|
67
67
|
}
|
|
68
68
|
//#endregion
|
|
69
|
-
//#region \0@oxc-project+runtime@0.
|
|
69
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/toPropertyKey.js
|
|
70
70
|
function toPropertyKey(t) {
|
|
71
71
|
var i = toPrimitive(t, "string");
|
|
72
72
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
73
73
|
}
|
|
74
74
|
//#endregion
|
|
75
|
-
//#region \0@oxc-project+runtime@0.
|
|
75
|
+
//#region \0@oxc-project+runtime@0.132.0/helpers/defineProperty.js
|
|
76
76
|
function _defineProperty(e, r, t) {
|
|
77
77
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
78
78
|
value: t,
|
|
@@ -756,12 +756,13 @@ var useLocation = () => {
|
|
|
756
756
|
};
|
|
757
757
|
//#endregion
|
|
758
758
|
//#region components/Link.tsx
|
|
759
|
-
var
|
|
759
|
+
var defaultAs = ({ isActive, isPending, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { ...props });
|
|
760
|
+
var Link = ({ children, to, as = defaultAs, prefetch: prefetchLink, hoverPrefetchDelay, className, style, beforeNavigate, exact = false, activeClassName = "active-link", pendingClassName = "pending-link" }) => {
|
|
760
761
|
const isPending = useIsRoutePending(to);
|
|
761
762
|
const { pathname } = useLocation();
|
|
762
763
|
const navigate = useNavigate();
|
|
763
764
|
const timeout = useRef(0);
|
|
764
|
-
const
|
|
765
|
+
const elementRef = useRef(null);
|
|
765
766
|
const { prefetch: configPrefetch, hoverPrefetchDelay: configPrefetchDelay } = routerConfig;
|
|
766
767
|
const prefetch = prefetchLink || configPrefetch;
|
|
767
768
|
const prefetchDelay = hoverPrefetchDelay ?? configPrefetchDelay;
|
|
@@ -789,17 +790,19 @@ var Link = ({ children, to, prefetch: prefetchLink, hoverPrefetchDelay, classNam
|
|
|
789
790
|
}, [prefetch, to]);
|
|
790
791
|
useEffect(() => {
|
|
791
792
|
if (prefetch !== "viewport") return;
|
|
792
|
-
const element =
|
|
793
|
+
const element = elementRef.current;
|
|
794
|
+
if (!element) return;
|
|
793
795
|
const observer = new IntersectionObserver(async () => {
|
|
794
796
|
await router.runtime.prefetch(to);
|
|
795
797
|
observer.disconnect();
|
|
796
798
|
});
|
|
797
|
-
|
|
798
|
-
return () =>
|
|
799
|
-
if (element) observer.disconnect();
|
|
800
|
-
};
|
|
799
|
+
observer.observe(element);
|
|
800
|
+
return () => observer.disconnect();
|
|
801
801
|
}, [prefetch, to]);
|
|
802
|
-
|
|
802
|
+
useEffect(() => () => {
|
|
803
|
+
if (timeout.current) clearTimeout(timeout.current);
|
|
804
|
+
}, []);
|
|
805
|
+
const isActive = to === "/" ? pathname === "/" : exact ? pathname === to : pathname === to || pathname?.startsWith(`${to}/`);
|
|
803
806
|
const normalizedClassName = typeof className === "function" ? className({
|
|
804
807
|
isActive,
|
|
805
808
|
isPending
|
|
@@ -814,18 +817,21 @@ var Link = ({ children, to, prefetch: prefetchLink, hoverPrefetchDelay, classNam
|
|
|
814
817
|
normalizedClassName
|
|
815
818
|
].filter(Boolean).join(" ");
|
|
816
819
|
const clickHandler = async (event) => {
|
|
820
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
817
821
|
event.preventDefault();
|
|
818
822
|
await beforeNavigate?.();
|
|
819
823
|
await navigate(to);
|
|
820
824
|
};
|
|
821
|
-
return
|
|
825
|
+
return as({
|
|
826
|
+
ref: elementRef,
|
|
822
827
|
href: to,
|
|
823
|
-
ref,
|
|
824
828
|
style: normalizedStyle,
|
|
825
829
|
className: resultClassName,
|
|
826
830
|
onClick: clickHandler,
|
|
827
831
|
onMouseEnter,
|
|
828
832
|
onMouseLeave,
|
|
833
|
+
isActive,
|
|
834
|
+
isPending,
|
|
829
835
|
children
|
|
830
836
|
});
|
|
831
837
|
};
|