olova 2.0.55 → 2.0.56
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 +28 -288
- package/dist/chunk-23UAGQ6N.js +2208 -0
- package/dist/chunk-23UAGQ6N.js.map +1 -0
- package/dist/chunk-D7SIC5TC.js +367 -0
- package/dist/chunk-D7SIC5TC.js.map +1 -0
- package/dist/entry-server.cjs +2341 -0
- package/dist/entry-server.cjs.map +1 -0
- package/dist/entry-server.js +114 -0
- package/dist/entry-server.js.map +1 -0
- package/dist/entry-worker.cjs +2354 -0
- package/dist/entry-worker.cjs.map +1 -0
- package/dist/entry-worker.js +126 -0
- package/dist/entry-worker.js.map +1 -0
- package/dist/main.cjs +18 -0
- package/dist/main.cjs.map +1 -0
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -0
- package/dist/olova.cjs +1684 -0
- package/dist/olova.cjs.map +1 -0
- package/dist/olova.d.cts +72 -0
- package/dist/olova.d.ts +72 -0
- package/dist/olova.js +1325 -0
- package/dist/olova.js.map +1 -0
- package/dist/performance.cjs +386 -0
- package/dist/performance.cjs.map +1 -0
- package/dist/performance.js +3 -0
- package/dist/performance.js.map +1 -0
- package/dist/router.cjs +646 -0
- package/dist/router.cjs.map +1 -0
- package/dist/router.d.cts +113 -0
- package/dist/router.d.ts +113 -0
- package/dist/router.js +632 -0
- package/dist/router.js.map +1 -0
- package/main.tsx +76 -0
- package/olova.ts +619 -0
- package/package.json +42 -61
- package/src/entry-server.tsx +165 -0
- package/src/entry-worker.tsx +201 -0
- package/src/generator/index.ts +409 -0
- package/src/hydration/flight.ts +320 -0
- package/src/hydration/index.ts +12 -0
- package/src/hydration/types.ts +225 -0
- package/src/logger.ts +182 -0
- package/src/main.tsx +24 -0
- package/src/performance.ts +488 -0
- package/src/plugin/index.ts +204 -0
- package/src/router/ErrorBoundary.tsx +145 -0
- package/src/router/Link.tsx +117 -0
- package/src/router/OlovaRouter.tsx +354 -0
- package/src/router/Outlet.tsx +8 -0
- package/src/router/context.ts +117 -0
- package/src/router/index.ts +29 -0
- package/src/router/matching.ts +63 -0
- package/src/router/router.tsx +23 -0
- package/src/router/search-params.ts +29 -0
- package/src/scanner/index.ts +116 -0
- package/src/types/index.ts +191 -0
- package/src/utils/export.ts +85 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/naming.ts +54 -0
- package/src/utils/path.ts +45 -0
- package/tsup.config.ts +35 -0
- package/CHANGELOG.md +0 -31
- package/LICENSE +0 -21
- package/dist/index.cjs +0 -883
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -138
- package/dist/index.d.ts +0 -138
- package/dist/index.js +0 -832
- package/dist/index.js.map +0 -1
- package/dist/plugin.cjs +0 -927
- package/dist/plugin.cjs.map +0 -1
- package/dist/plugin.d.cts +0 -18
- package/dist/plugin.d.ts +0 -18
- package/dist/plugin.js +0 -894
- package/dist/plugin.js.map +0 -1
- package/dist/ssg.cjs +0 -637
- package/dist/ssg.cjs.map +0 -1
- package/dist/ssg.d.cts +0 -191
- package/dist/ssg.d.ts +0 -191
- package/dist/ssg.js +0 -585
- package/dist/ssg.js.map +0 -1
- package/dist/types-BT6YsBGO.d.cts +0 -143
- package/dist/types-BT6YsBGO.d.ts +0 -143
package/dist/index.js
DELETED
|
@@ -1,832 +0,0 @@
|
|
|
1
|
-
// src/router.tsx
|
|
2
|
-
import { useMemo, useEffect as useEffect3 } from "react";
|
|
3
|
-
|
|
4
|
-
// src/context.tsx
|
|
5
|
-
import { createContext, useContext, useState, useCallback, useEffect, useTransition } from "react";
|
|
6
|
-
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
var OlovaRouterContext = createContext(null);
|
|
8
|
-
var isBrowser = typeof window !== "undefined";
|
|
9
|
-
var ssrContextValue = {
|
|
10
|
-
pathname: "/",
|
|
11
|
-
params: {},
|
|
12
|
-
searchParams: new URLSearchParams(),
|
|
13
|
-
navigate: () => {
|
|
14
|
-
},
|
|
15
|
-
replace: () => {
|
|
16
|
-
},
|
|
17
|
-
back: () => {
|
|
18
|
-
},
|
|
19
|
-
forward: () => {
|
|
20
|
-
},
|
|
21
|
-
refresh: () => {
|
|
22
|
-
},
|
|
23
|
-
prefetch: () => {
|
|
24
|
-
},
|
|
25
|
-
isNavigating: false
|
|
26
|
-
};
|
|
27
|
-
function setSSRContext(pathname, params = {}) {
|
|
28
|
-
ssrContextValue = {
|
|
29
|
-
pathname,
|
|
30
|
-
params,
|
|
31
|
-
searchParams: new URLSearchParams(),
|
|
32
|
-
navigate: () => {
|
|
33
|
-
},
|
|
34
|
-
replace: () => {
|
|
35
|
-
},
|
|
36
|
-
back: () => {
|
|
37
|
-
},
|
|
38
|
-
forward: () => {
|
|
39
|
-
},
|
|
40
|
-
refresh: () => {
|
|
41
|
-
},
|
|
42
|
-
prefetch: () => {
|
|
43
|
-
},
|
|
44
|
-
isNavigating: false
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function useOlovaRouter() {
|
|
48
|
-
const context = useContext(OlovaRouterContext);
|
|
49
|
-
if (!context) {
|
|
50
|
-
if (!isBrowser) {
|
|
51
|
-
return ssrContextValue;
|
|
52
|
-
}
|
|
53
|
-
throw new Error("useOlovaRouter must be used within an OlovaRouter");
|
|
54
|
-
}
|
|
55
|
-
return context;
|
|
56
|
-
}
|
|
57
|
-
function usePathname() {
|
|
58
|
-
return useOlovaRouter().pathname;
|
|
59
|
-
}
|
|
60
|
-
function useParams() {
|
|
61
|
-
return useOlovaRouter().params;
|
|
62
|
-
}
|
|
63
|
-
function useSearchParams() {
|
|
64
|
-
return useOlovaRouter().searchParams;
|
|
65
|
-
}
|
|
66
|
-
function useRouter() {
|
|
67
|
-
const { navigate, replace, back, forward, refresh, prefetch, isNavigating } = useOlovaRouter();
|
|
68
|
-
return {
|
|
69
|
-
push: navigate,
|
|
70
|
-
replace,
|
|
71
|
-
back,
|
|
72
|
-
forward,
|
|
73
|
-
refresh,
|
|
74
|
-
prefetch,
|
|
75
|
-
isNavigating
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function OlovaRouterProvider({ children, basePath = "" }) {
|
|
79
|
-
const [pathname, setPathname] = useState(() => {
|
|
80
|
-
const path = window.location.pathname;
|
|
81
|
-
return basePath ? path.replace(new RegExp(`^${basePath}`), "") || "/" : path;
|
|
82
|
-
});
|
|
83
|
-
const [searchParams, setSearchParams] = useState(() => new URLSearchParams(window.location.search));
|
|
84
|
-
const [params, setParams] = useState({});
|
|
85
|
-
const [isPending, startTransition] = useTransition();
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
const handlePopState = () => {
|
|
88
|
-
startTransition(() => {
|
|
89
|
-
const path = window.location.pathname;
|
|
90
|
-
setPathname(basePath ? path.replace(new RegExp(`^${basePath}`), "") || "/" : path);
|
|
91
|
-
setSearchParams(new URLSearchParams(window.location.search));
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
window.addEventListener("popstate", handlePopState);
|
|
95
|
-
return () => window.removeEventListener("popstate", handlePopState);
|
|
96
|
-
}, [basePath]);
|
|
97
|
-
const navigate = useCallback((to, options = {}) => {
|
|
98
|
-
const url = new URL(to, window.location.origin);
|
|
99
|
-
const fullPath = basePath + url.pathname;
|
|
100
|
-
startTransition(() => {
|
|
101
|
-
if (options.replace) {
|
|
102
|
-
window.history.replaceState(null, "", fullPath + url.search);
|
|
103
|
-
} else {
|
|
104
|
-
window.history.pushState(null, "", fullPath + url.search);
|
|
105
|
-
}
|
|
106
|
-
setPathname(url.pathname);
|
|
107
|
-
setSearchParams(new URLSearchParams(url.search));
|
|
108
|
-
if (options.scroll !== false) {
|
|
109
|
-
window.scrollTo(0, 0);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}, [basePath]);
|
|
113
|
-
const replace = useCallback((to, options = {}) => {
|
|
114
|
-
navigate(to, { ...options, replace: true });
|
|
115
|
-
}, [navigate]);
|
|
116
|
-
const back = useCallback(() => {
|
|
117
|
-
window.history.back();
|
|
118
|
-
}, []);
|
|
119
|
-
const forward = useCallback(() => {
|
|
120
|
-
window.history.forward();
|
|
121
|
-
}, []);
|
|
122
|
-
const refresh = useCallback(() => {
|
|
123
|
-
startTransition(() => {
|
|
124
|
-
setPathname((prev) => prev);
|
|
125
|
-
});
|
|
126
|
-
}, []);
|
|
127
|
-
const prefetch = useCallback((href) => {
|
|
128
|
-
console.log("[Olova] Prefetching:", href);
|
|
129
|
-
}, []);
|
|
130
|
-
const updateParams = useCallback((newParams) => {
|
|
131
|
-
setParams(newParams);
|
|
132
|
-
}, []);
|
|
133
|
-
const contextValue = {
|
|
134
|
-
pathname,
|
|
135
|
-
params,
|
|
136
|
-
searchParams,
|
|
137
|
-
navigate,
|
|
138
|
-
replace,
|
|
139
|
-
back,
|
|
140
|
-
forward,
|
|
141
|
-
refresh,
|
|
142
|
-
prefetch,
|
|
143
|
-
isNavigating: isPending
|
|
144
|
-
};
|
|
145
|
-
return /* @__PURE__ */ jsx(OlovaRouterContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(OlovaParamsUpdater, { updateParams, children }) });
|
|
146
|
-
}
|
|
147
|
-
var ParamsUpdaterContext = createContext(null);
|
|
148
|
-
function OlovaParamsUpdater({
|
|
149
|
-
children,
|
|
150
|
-
updateParams
|
|
151
|
-
}) {
|
|
152
|
-
return /* @__PURE__ */ jsx(ParamsUpdaterContext.Provider, { value: updateParams, children });
|
|
153
|
-
}
|
|
154
|
-
function useParamsUpdater() {
|
|
155
|
-
return useContext(ParamsUpdaterContext);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// src/components/ErrorBoundary.tsx
|
|
159
|
-
import { Component } from "react";
|
|
160
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
161
|
-
var RouteErrorBoundary = class extends Component {
|
|
162
|
-
constructor(props) {
|
|
163
|
-
super(props);
|
|
164
|
-
this.reset = () => {
|
|
165
|
-
this.setState({ hasError: false, error: null });
|
|
166
|
-
};
|
|
167
|
-
this.state = { hasError: false, error: null };
|
|
168
|
-
}
|
|
169
|
-
static getDerivedStateFromError(error) {
|
|
170
|
-
return { hasError: true, error };
|
|
171
|
-
}
|
|
172
|
-
componentDidCatch(error, errorInfo) {
|
|
173
|
-
console.error("[Olova] Route error:", error, errorInfo);
|
|
174
|
-
this.props.onError?.(error, errorInfo);
|
|
175
|
-
}
|
|
176
|
-
render() {
|
|
177
|
-
if (this.state.hasError && this.state.error) {
|
|
178
|
-
const FallbackComponent = this.props.fallback;
|
|
179
|
-
if (FallbackComponent) {
|
|
180
|
-
return /* @__PURE__ */ jsx2(FallbackComponent, { error: this.state.error, reset: this.reset });
|
|
181
|
-
}
|
|
182
|
-
return /* @__PURE__ */ jsx2("div", { className: "flex min-h-[400px] flex-col items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-destructive/20 bg-destructive/5 p-6 text-center", children: [
|
|
183
|
-
/* @__PURE__ */ jsx2("h2", { className: "mb-2 text-xl font-semibold text-destructive", children: "Something went wrong!" }),
|
|
184
|
-
/* @__PURE__ */ jsx2("p", { className: "mb-4 text-sm text-muted-foreground", children: this.state.error.message }),
|
|
185
|
-
/* @__PURE__ */ jsx2(
|
|
186
|
-
"button",
|
|
187
|
-
{
|
|
188
|
-
onClick: this.reset,
|
|
189
|
-
className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90",
|
|
190
|
-
children: "Try again"
|
|
191
|
-
}
|
|
192
|
-
)
|
|
193
|
-
] }) });
|
|
194
|
-
}
|
|
195
|
-
return this.props.children;
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
function DefaultErrorComponent({ error, reset }) {
|
|
199
|
-
return /* @__PURE__ */ jsx2("div", { className: "flex min-h-[400px] flex-col items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "max-w-md rounded-lg border border-destructive/20 bg-destructive/5 p-6 text-center", children: [
|
|
200
|
-
/* @__PURE__ */ jsx2("div", { className: "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10", children: /* @__PURE__ */ jsx2(
|
|
201
|
-
"svg",
|
|
202
|
-
{
|
|
203
|
-
className: "h-6 w-6 text-destructive",
|
|
204
|
-
fill: "none",
|
|
205
|
-
viewBox: "0 0 24 24",
|
|
206
|
-
stroke: "currentColor",
|
|
207
|
-
children: /* @__PURE__ */ jsx2(
|
|
208
|
-
"path",
|
|
209
|
-
{
|
|
210
|
-
strokeLinecap: "round",
|
|
211
|
-
strokeLinejoin: "round",
|
|
212
|
-
strokeWidth: 2,
|
|
213
|
-
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
214
|
-
}
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
) }),
|
|
218
|
-
/* @__PURE__ */ jsx2("h2", { className: "mb-2 text-xl font-semibold text-foreground", children: "Something went wrong!" }),
|
|
219
|
-
/* @__PURE__ */ jsx2("p", { className: "mb-4 text-sm text-muted-foreground", children: error.message }),
|
|
220
|
-
/* @__PURE__ */ jsx2(
|
|
221
|
-
"button",
|
|
222
|
-
{
|
|
223
|
-
onClick: reset,
|
|
224
|
-
className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90",
|
|
225
|
-
children: "Try again"
|
|
226
|
-
}
|
|
227
|
-
)
|
|
228
|
-
] }) });
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// src/components/Loading.tsx
|
|
232
|
-
import { Suspense } from "react";
|
|
233
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
234
|
-
function RouteLoadingBoundary({ children, fallback }) {
|
|
235
|
-
return /* @__PURE__ */ jsx3(Suspense, { fallback: fallback || /* @__PURE__ */ jsx3(DefaultLoadingComponent, {}), children });
|
|
236
|
-
}
|
|
237
|
-
function DefaultLoadingComponent() {
|
|
238
|
-
return /* @__PURE__ */ jsx3("div", { className: "flex min-h-[400px] flex-col items-center justify-center p-8", children: /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
|
|
239
|
-
/* @__PURE__ */ jsxs2("div", { className: "relative h-10 w-10", children: [
|
|
240
|
-
/* @__PURE__ */ jsx3("div", { className: "absolute inset-0 animate-ping rounded-full bg-primary/20" }),
|
|
241
|
-
/* @__PURE__ */ jsx3("div", { className: "absolute inset-0 animate-pulse rounded-full bg-primary/40" }),
|
|
242
|
-
/* @__PURE__ */ jsx3("div", { className: "absolute inset-2 animate-spin rounded-full border-2 border-primary border-t-transparent" })
|
|
243
|
-
] }),
|
|
244
|
-
/* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: "Loading..." })
|
|
245
|
-
] }) });
|
|
246
|
-
}
|
|
247
|
-
function Skeleton({ className = "" }) {
|
|
248
|
-
return /* @__PURE__ */ jsx3(
|
|
249
|
-
"div",
|
|
250
|
-
{
|
|
251
|
-
className: `animate-pulse rounded-md bg-muted ${className}`,
|
|
252
|
-
"aria-hidden": "true"
|
|
253
|
-
}
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
function SkeletonText({ lines = 3, className = "" }) {
|
|
257
|
-
return /* @__PURE__ */ jsx3("div", { className: `space-y-2 ${className}`, children: Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsx3(
|
|
258
|
-
Skeleton,
|
|
259
|
-
{
|
|
260
|
-
className: `h-4 ${i === lines - 1 ? "w-3/4" : "w-full"}`
|
|
261
|
-
},
|
|
262
|
-
i
|
|
263
|
-
)) });
|
|
264
|
-
}
|
|
265
|
-
function SkeletonCard({ className = "" }) {
|
|
266
|
-
return /* @__PURE__ */ jsxs2("div", { className: `rounded-lg border bg-card p-6 ${className}`, children: [
|
|
267
|
-
/* @__PURE__ */ jsx3(Skeleton, { className: "mb-4 h-6 w-1/2" }),
|
|
268
|
-
/* @__PURE__ */ jsx3(SkeletonText, { lines: 3 })
|
|
269
|
-
] });
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// src/components/NotFound.tsx
|
|
273
|
-
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
274
|
-
function NotFoundBoundary({ children, fallback: Fallback, show404 }) {
|
|
275
|
-
if (show404) {
|
|
276
|
-
if (Fallback) {
|
|
277
|
-
return /* @__PURE__ */ jsx4(Fallback, {});
|
|
278
|
-
}
|
|
279
|
-
return /* @__PURE__ */ jsx4(DefaultNotFoundComponent, {});
|
|
280
|
-
}
|
|
281
|
-
return /* @__PURE__ */ jsx4(Fragment, { children });
|
|
282
|
-
}
|
|
283
|
-
function DefaultNotFoundComponent() {
|
|
284
|
-
return /* @__PURE__ */ jsx4("div", { className: "flex min-h-[60vh] flex-col items-center justify-center p-8", children: /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
|
|
285
|
-
/* @__PURE__ */ jsx4("h1", { className: "mb-2 text-8xl font-bold text-primary", children: "404" }),
|
|
286
|
-
/* @__PURE__ */ jsx4("h2", { className: "mb-4 text-2xl font-semibold text-foreground", children: "Page Not Found" }),
|
|
287
|
-
/* @__PURE__ */ jsx4("p", { className: "mb-8 max-w-md text-muted-foreground", children: "The page you're looking for doesn't exist or has been moved." }),
|
|
288
|
-
/* @__PURE__ */ jsxs3(
|
|
289
|
-
"a",
|
|
290
|
-
{
|
|
291
|
-
href: "/",
|
|
292
|
-
className: "inline-flex items-center gap-2 rounded-md bg-primary px-6 py-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90",
|
|
293
|
-
children: [
|
|
294
|
-
/* @__PURE__ */ jsx4(
|
|
295
|
-
"svg",
|
|
296
|
-
{
|
|
297
|
-
className: "h-4 w-4",
|
|
298
|
-
fill: "none",
|
|
299
|
-
viewBox: "0 0 24 24",
|
|
300
|
-
stroke: "currentColor",
|
|
301
|
-
children: /* @__PURE__ */ jsx4(
|
|
302
|
-
"path",
|
|
303
|
-
{
|
|
304
|
-
strokeLinecap: "round",
|
|
305
|
-
strokeLinejoin: "round",
|
|
306
|
-
strokeWidth: 2,
|
|
307
|
-
d: "M10 19l-7-7m0 0l7-7m-7 7h18"
|
|
308
|
-
}
|
|
309
|
-
)
|
|
310
|
-
}
|
|
311
|
-
),
|
|
312
|
-
"Go back home"
|
|
313
|
-
]
|
|
314
|
-
}
|
|
315
|
-
)
|
|
316
|
-
] }) });
|
|
317
|
-
}
|
|
318
|
-
function notFound() {
|
|
319
|
-
throw new NotFoundError();
|
|
320
|
-
}
|
|
321
|
-
var NotFoundError = class extends Error {
|
|
322
|
-
constructor() {
|
|
323
|
-
super("NEXT_NOT_FOUND");
|
|
324
|
-
this.name = "NotFoundError";
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
// src/components/Metadata.tsx
|
|
329
|
-
import { useEffect as useEffect2, useContext as useContext2, createContext as createContext2, useState as useState2, useCallback as useCallback2 } from "react";
|
|
330
|
-
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
331
|
-
var MetadataContext = createContext2(null);
|
|
332
|
-
function MetadataProvider({ children, rootMetadata }) {
|
|
333
|
-
const [metadata, setMetadataState] = useState2(rootMetadata || null);
|
|
334
|
-
const setMetadata = useCallback2((newMetadata) => {
|
|
335
|
-
setMetadataState(newMetadata);
|
|
336
|
-
}, []);
|
|
337
|
-
return /* @__PURE__ */ jsxs4(MetadataContext.Provider, { value: { metadata, rootMetadata: rootMetadata || null, setMetadata }, children: [
|
|
338
|
-
/* @__PURE__ */ jsx5(MetadataHead, { metadata, fallback: rootMetadata }),
|
|
339
|
-
children
|
|
340
|
-
] });
|
|
341
|
-
}
|
|
342
|
-
function useMetadata() {
|
|
343
|
-
const context = useContext2(MetadataContext);
|
|
344
|
-
if (!context) {
|
|
345
|
-
throw new Error("useMetadata must be used within a MetadataProvider");
|
|
346
|
-
}
|
|
347
|
-
return context;
|
|
348
|
-
}
|
|
349
|
-
function usePageMetadata(metadata) {
|
|
350
|
-
const context = useContext2(MetadataContext);
|
|
351
|
-
useEffect2(() => {
|
|
352
|
-
if (context && metadata) {
|
|
353
|
-
context.setMetadata(metadata);
|
|
354
|
-
}
|
|
355
|
-
return () => {
|
|
356
|
-
if (context) {
|
|
357
|
-
context.setMetadata(context.rootMetadata);
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
}, [metadata, context]);
|
|
361
|
-
}
|
|
362
|
-
function MetadataHead({ metadata, fallback }) {
|
|
363
|
-
useEffect2(() => {
|
|
364
|
-
const activeMetadata = metadata || fallback;
|
|
365
|
-
if (!activeMetadata) return;
|
|
366
|
-
if (activeMetadata.title) {
|
|
367
|
-
document.title = activeMetadata.title;
|
|
368
|
-
}
|
|
369
|
-
const addedMetas = [];
|
|
370
|
-
const setMeta = (name, content, property) => {
|
|
371
|
-
const attr = property ? "property" : "name";
|
|
372
|
-
let meta = document.querySelector(`meta[${attr}="${name}"]`);
|
|
373
|
-
if (!meta) {
|
|
374
|
-
meta = document.createElement("meta");
|
|
375
|
-
meta.setAttribute(attr, name);
|
|
376
|
-
document.head.appendChild(meta);
|
|
377
|
-
addedMetas.push(meta);
|
|
378
|
-
}
|
|
379
|
-
meta.content = content;
|
|
380
|
-
};
|
|
381
|
-
if (activeMetadata.description) {
|
|
382
|
-
setMeta("description", activeMetadata.description);
|
|
383
|
-
}
|
|
384
|
-
if (activeMetadata.keywords?.length) {
|
|
385
|
-
setMeta("keywords", activeMetadata.keywords.join(", "));
|
|
386
|
-
}
|
|
387
|
-
if (activeMetadata.authors?.length) {
|
|
388
|
-
setMeta("author", activeMetadata.authors.map((a) => a.name).join(", "));
|
|
389
|
-
}
|
|
390
|
-
if (activeMetadata.robots) {
|
|
391
|
-
setMeta("robots", activeMetadata.robots);
|
|
392
|
-
}
|
|
393
|
-
if (activeMetadata.openGraph) {
|
|
394
|
-
const og = activeMetadata.openGraph;
|
|
395
|
-
if (og.title) {
|
|
396
|
-
setMeta("og:title", og.title, true);
|
|
397
|
-
}
|
|
398
|
-
if (og.description) {
|
|
399
|
-
setMeta("og:description", og.description, true);
|
|
400
|
-
}
|
|
401
|
-
if (og.url) {
|
|
402
|
-
setMeta("og:url", og.url, true);
|
|
403
|
-
}
|
|
404
|
-
if (og.siteName) {
|
|
405
|
-
setMeta("og:site_name", og.siteName, true);
|
|
406
|
-
}
|
|
407
|
-
if (og.type) {
|
|
408
|
-
setMeta("og:type", og.type, true);
|
|
409
|
-
}
|
|
410
|
-
if (og.images?.length) {
|
|
411
|
-
const img = og.images[0];
|
|
412
|
-
setMeta("og:image", img.url, true);
|
|
413
|
-
if (img.width) setMeta("og:image:width", String(img.width), true);
|
|
414
|
-
if (img.height) setMeta("og:image:height", String(img.height), true);
|
|
415
|
-
if (img.alt) setMeta("og:image:alt", img.alt, true);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
if (activeMetadata.twitter) {
|
|
419
|
-
const tw = activeMetadata.twitter;
|
|
420
|
-
if (tw.card) {
|
|
421
|
-
setMeta("twitter:card", tw.card);
|
|
422
|
-
}
|
|
423
|
-
if (tw.title) {
|
|
424
|
-
setMeta("twitter:title", tw.title);
|
|
425
|
-
}
|
|
426
|
-
if (tw.description) {
|
|
427
|
-
setMeta("twitter:description", tw.description);
|
|
428
|
-
}
|
|
429
|
-
if (tw.site) {
|
|
430
|
-
setMeta("twitter:site", tw.site);
|
|
431
|
-
}
|
|
432
|
-
if (tw.creator) {
|
|
433
|
-
setMeta("twitter:creator", tw.creator);
|
|
434
|
-
}
|
|
435
|
-
if (tw.images?.length) {
|
|
436
|
-
setMeta("twitter:image", tw.images[0]);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
if (activeMetadata.canonical) {
|
|
440
|
-
let link = document.querySelector('link[rel="canonical"]');
|
|
441
|
-
if (!link) {
|
|
442
|
-
link = document.createElement("link");
|
|
443
|
-
link.rel = "canonical";
|
|
444
|
-
document.head.appendChild(link);
|
|
445
|
-
}
|
|
446
|
-
link.href = activeMetadata.canonical;
|
|
447
|
-
}
|
|
448
|
-
return () => {
|
|
449
|
-
addedMetas.forEach((meta) => {
|
|
450
|
-
if (meta.parentNode) {
|
|
451
|
-
meta.parentNode.removeChild(meta);
|
|
452
|
-
}
|
|
453
|
-
});
|
|
454
|
-
};
|
|
455
|
-
}, [metadata, fallback]);
|
|
456
|
-
return null;
|
|
457
|
-
}
|
|
458
|
-
function generateMetadataHtml(metadata) {
|
|
459
|
-
const tags = [];
|
|
460
|
-
if (metadata.title) {
|
|
461
|
-
tags.push(` <title>${escapeHtml(metadata.title)}</title>`);
|
|
462
|
-
}
|
|
463
|
-
if (metadata.description) {
|
|
464
|
-
tags.push(` <meta name="description" content="${escapeHtml(metadata.description)}" />`);
|
|
465
|
-
}
|
|
466
|
-
if (metadata.keywords?.length) {
|
|
467
|
-
tags.push(` <meta name="keywords" content="${escapeHtml(metadata.keywords.join(", "))}" />`);
|
|
468
|
-
}
|
|
469
|
-
if (metadata.authors?.length) {
|
|
470
|
-
tags.push(` <meta name="author" content="${escapeHtml(metadata.authors.map((a) => a.name).join(", "))}" />`);
|
|
471
|
-
}
|
|
472
|
-
if (metadata.robots) {
|
|
473
|
-
tags.push(` <meta name="robots" content="${escapeHtml(metadata.robots)}" />`);
|
|
474
|
-
}
|
|
475
|
-
if (metadata.openGraph) {
|
|
476
|
-
const og = metadata.openGraph;
|
|
477
|
-
if (og.title) tags.push(` <meta property="og:title" content="${escapeHtml(og.title)}" />`);
|
|
478
|
-
if (og.description) tags.push(` <meta property="og:description" content="${escapeHtml(og.description)}" />`);
|
|
479
|
-
if (og.url) tags.push(` <meta property="og:url" content="${escapeHtml(og.url)}" />`);
|
|
480
|
-
if (og.siteName) tags.push(` <meta property="og:site_name" content="${escapeHtml(og.siteName)}" />`);
|
|
481
|
-
if (og.type) tags.push(` <meta property="og:type" content="${escapeHtml(og.type)}" />`);
|
|
482
|
-
if (og.images?.length) {
|
|
483
|
-
const img = og.images[0];
|
|
484
|
-
tags.push(` <meta property="og:image" content="${escapeHtml(img.url)}" />`);
|
|
485
|
-
if (img.width) tags.push(` <meta property="og:image:width" content="${img.width}" />`);
|
|
486
|
-
if (img.height) tags.push(` <meta property="og:image:height" content="${img.height}" />`);
|
|
487
|
-
if (img.alt) tags.push(` <meta property="og:image:alt" content="${escapeHtml(img.alt)}" />`);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
if (metadata.twitter) {
|
|
491
|
-
const tw = metadata.twitter;
|
|
492
|
-
if (tw.card) tags.push(` <meta name="twitter:card" content="${escapeHtml(tw.card)}" />`);
|
|
493
|
-
if (tw.title) tags.push(` <meta name="twitter:title" content="${escapeHtml(tw.title)}" />`);
|
|
494
|
-
if (tw.description) tags.push(` <meta name="twitter:description" content="${escapeHtml(tw.description)}" />`);
|
|
495
|
-
if (tw.site) tags.push(` <meta name="twitter:site" content="${escapeHtml(tw.site)}" />`);
|
|
496
|
-
if (tw.creator) tags.push(` <meta name="twitter:creator" content="${escapeHtml(tw.creator)}" />`);
|
|
497
|
-
if (tw.images?.length) tags.push(` <meta name="twitter:image" content="${escapeHtml(tw.images[0])}" />`);
|
|
498
|
-
}
|
|
499
|
-
if (metadata.canonical) {
|
|
500
|
-
tags.push(` <link rel="canonical" href="${escapeHtml(metadata.canonical)}" />`);
|
|
501
|
-
}
|
|
502
|
-
return tags.join("\n");
|
|
503
|
-
}
|
|
504
|
-
function escapeHtml(text) {
|
|
505
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// src/router.tsx
|
|
509
|
-
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
510
|
-
function OlovaRouter({
|
|
511
|
-
routes,
|
|
512
|
-
basePath = "",
|
|
513
|
-
defaultLoading,
|
|
514
|
-
defaultNotFound,
|
|
515
|
-
defaultError,
|
|
516
|
-
rootMetadata,
|
|
517
|
-
routeMetadata
|
|
518
|
-
}) {
|
|
519
|
-
return /* @__PURE__ */ jsx6(OlovaRouterProvider, { basePath, children: /* @__PURE__ */ jsx6(
|
|
520
|
-
RouteRenderer,
|
|
521
|
-
{
|
|
522
|
-
routes,
|
|
523
|
-
defaultLoading,
|
|
524
|
-
defaultNotFound,
|
|
525
|
-
defaultError,
|
|
526
|
-
rootMetadata,
|
|
527
|
-
routeMetadata
|
|
528
|
-
}
|
|
529
|
-
) });
|
|
530
|
-
}
|
|
531
|
-
function RouteRenderer({
|
|
532
|
-
routes,
|
|
533
|
-
defaultLoading,
|
|
534
|
-
defaultNotFound,
|
|
535
|
-
defaultError,
|
|
536
|
-
rootMetadata,
|
|
537
|
-
routeMetadata
|
|
538
|
-
}) {
|
|
539
|
-
const pathname = usePathname();
|
|
540
|
-
const updateParams = useParamsUpdater();
|
|
541
|
-
const match = useMemo(() => {
|
|
542
|
-
return matchRoute(routes, pathname);
|
|
543
|
-
}, [routes, pathname]);
|
|
544
|
-
useEffect3(() => {
|
|
545
|
-
if (updateParams && match) {
|
|
546
|
-
updateParams(match.params);
|
|
547
|
-
}
|
|
548
|
-
}, [match, updateParams]);
|
|
549
|
-
const currentMetadata = useMemo(() => {
|
|
550
|
-
if (!routeMetadata) return null;
|
|
551
|
-
if (routeMetadata[pathname]) {
|
|
552
|
-
return routeMetadata[pathname];
|
|
553
|
-
}
|
|
554
|
-
return null;
|
|
555
|
-
}, [pathname, routeMetadata]);
|
|
556
|
-
if (!match) {
|
|
557
|
-
const NotFoundComponent = defaultNotFound || DefaultNotFoundComponent;
|
|
558
|
-
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
559
|
-
/* @__PURE__ */ jsx6(MetadataHead, { metadata: currentMetadata, fallback: rootMetadata }),
|
|
560
|
-
/* @__PURE__ */ jsx6(NotFoundComponent, {})
|
|
561
|
-
] });
|
|
562
|
-
}
|
|
563
|
-
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
564
|
-
/* @__PURE__ */ jsx6(MetadataHead, { metadata: currentMetadata, fallback: rootMetadata }),
|
|
565
|
-
/* @__PURE__ */ jsx6(
|
|
566
|
-
LayoutRenderer,
|
|
567
|
-
{
|
|
568
|
-
match,
|
|
569
|
-
routes,
|
|
570
|
-
defaultLoading,
|
|
571
|
-
defaultError
|
|
572
|
-
}
|
|
573
|
-
)
|
|
574
|
-
] });
|
|
575
|
-
}
|
|
576
|
-
function LayoutRenderer({ match, routes, defaultLoading, defaultError }) {
|
|
577
|
-
const { route, params } = match;
|
|
578
|
-
const layoutChain = useMemo(() => {
|
|
579
|
-
return findLayoutChain(routes, route);
|
|
580
|
-
}, [routes, route]);
|
|
581
|
-
const renderSlots = (currentRoute) => {
|
|
582
|
-
const slots = {};
|
|
583
|
-
if (currentRoute.slots) {
|
|
584
|
-
for (const [slotName, slotRoute] of Object.entries(currentRoute.slots)) {
|
|
585
|
-
if (slotRoute.component) {
|
|
586
|
-
const SlotComponent = slotRoute.component;
|
|
587
|
-
const SlotLoading = slotRoute.loading;
|
|
588
|
-
const SlotError = slotRoute.error || defaultError;
|
|
589
|
-
slots[slotName] = /* @__PURE__ */ jsx6(RouteErrorBoundary, { fallback: SlotError, children: /* @__PURE__ */ jsx6(RouteLoadingBoundary, { fallback: SlotLoading ? /* @__PURE__ */ jsx6(SlotLoading, {}) : defaultLoading, children: /* @__PURE__ */ jsx6(SlotComponent, { params, searchParams: {} }) }) }, slotName);
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
return slots;
|
|
594
|
-
};
|
|
595
|
-
const renderLayouts = (index) => {
|
|
596
|
-
if (index >= layoutChain.length) {
|
|
597
|
-
if (!route.component) {
|
|
598
|
-
return null;
|
|
599
|
-
}
|
|
600
|
-
const PageComponent = route.component;
|
|
601
|
-
const LoadingComponent2 = route.loading;
|
|
602
|
-
const ErrorComponent2 = route.error || defaultError;
|
|
603
|
-
return /* @__PURE__ */ jsx6(RouteErrorBoundary, { fallback: ErrorComponent2, children: /* @__PURE__ */ jsx6(RouteLoadingBoundary, { fallback: LoadingComponent2 ? /* @__PURE__ */ jsx6(LoadingComponent2, {}) : defaultLoading, children: /* @__PURE__ */ jsx6(PageComponent, { params, searchParams: {} }) }) });
|
|
604
|
-
}
|
|
605
|
-
const currentLayout = layoutChain[index];
|
|
606
|
-
if (!currentLayout.layout) {
|
|
607
|
-
return renderLayouts(index + 1);
|
|
608
|
-
}
|
|
609
|
-
const LayoutComponent = currentLayout.layout;
|
|
610
|
-
const LoadingComponent = currentLayout.loading;
|
|
611
|
-
const ErrorComponent = currentLayout.error || defaultError;
|
|
612
|
-
const slots = renderSlots(currentLayout);
|
|
613
|
-
return /* @__PURE__ */ jsx6(RouteErrorBoundary, { fallback: ErrorComponent, children: /* @__PURE__ */ jsx6(RouteLoadingBoundary, { fallback: LoadingComponent ? /* @__PURE__ */ jsx6(LoadingComponent, {}) : defaultLoading, children: /* @__PURE__ */ jsx6(LayoutComponent, { params, ...slots, children: renderLayouts(index + 1) }) }) });
|
|
614
|
-
};
|
|
615
|
-
return /* @__PURE__ */ jsx6(Fragment2, { children: renderLayouts(0) });
|
|
616
|
-
}
|
|
617
|
-
function matchRoute(routes, pathname) {
|
|
618
|
-
const segments = pathname.split("/").filter(Boolean);
|
|
619
|
-
function matchRecursive(routeList, segmentIndex, params) {
|
|
620
|
-
if (segmentIndex >= segments.length) {
|
|
621
|
-
for (const route of routeList) {
|
|
622
|
-
if (route.path === "" || route.path === "/") {
|
|
623
|
-
if (route.component) {
|
|
624
|
-
return {
|
|
625
|
-
route,
|
|
626
|
-
params,
|
|
627
|
-
pathname,
|
|
628
|
-
searchParams: new URLSearchParams(window.location.search)
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
return null;
|
|
634
|
-
}
|
|
635
|
-
const currentSegment = segments[segmentIndex];
|
|
636
|
-
for (const route of routeList) {
|
|
637
|
-
if (route.path.startsWith("(") && route.path.endsWith(")")) {
|
|
638
|
-
if (route.children.length > 0) {
|
|
639
|
-
const childMatch = matchRecursive(route.children, segmentIndex, params);
|
|
640
|
-
if (childMatch) return childMatch;
|
|
641
|
-
}
|
|
642
|
-
continue;
|
|
643
|
-
}
|
|
644
|
-
if (route.isCatchAll && route.paramName) {
|
|
645
|
-
const remainingSegments = segments.slice(segmentIndex);
|
|
646
|
-
const newParams = { ...params, [route.paramName]: remainingSegments.join("/") };
|
|
647
|
-
if (route.component) {
|
|
648
|
-
return {
|
|
649
|
-
route,
|
|
650
|
-
params: newParams,
|
|
651
|
-
pathname,
|
|
652
|
-
searchParams: new URLSearchParams(window.location.search)
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
if (route.isDynamic && route.paramName) {
|
|
657
|
-
const newParams = { ...params, [route.paramName]: currentSegment };
|
|
658
|
-
if (segmentIndex === segments.length - 1) {
|
|
659
|
-
if (route.component) {
|
|
660
|
-
return {
|
|
661
|
-
route,
|
|
662
|
-
params: newParams,
|
|
663
|
-
pathname,
|
|
664
|
-
searchParams: new URLSearchParams(window.location.search)
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
if (route.children.length > 0) {
|
|
669
|
-
const childMatch = matchRecursive(route.children, segmentIndex + 1, newParams);
|
|
670
|
-
if (childMatch) return childMatch;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
if (route.path === currentSegment) {
|
|
674
|
-
if (segmentIndex === segments.length - 1) {
|
|
675
|
-
if (route.component) {
|
|
676
|
-
return {
|
|
677
|
-
route,
|
|
678
|
-
params,
|
|
679
|
-
pathname,
|
|
680
|
-
searchParams: new URLSearchParams(window.location.search)
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
for (const child of route.children) {
|
|
684
|
-
if ((child.path === "" || child.path === "/") && child.component) {
|
|
685
|
-
return {
|
|
686
|
-
route: child,
|
|
687
|
-
params,
|
|
688
|
-
pathname,
|
|
689
|
-
searchParams: new URLSearchParams(window.location.search)
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
if (route.children.length > 0) {
|
|
695
|
-
const childMatch = matchRecursive(route.children, segmentIndex + 1, params);
|
|
696
|
-
if (childMatch) return childMatch;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
return null;
|
|
701
|
-
}
|
|
702
|
-
if (pathname === "/" || pathname === "") {
|
|
703
|
-
for (const route of routes) {
|
|
704
|
-
if ((route.path === "" || route.path === "/") && route.component) {
|
|
705
|
-
return {
|
|
706
|
-
route,
|
|
707
|
-
params: {},
|
|
708
|
-
pathname: "/",
|
|
709
|
-
searchParams: new URLSearchParams(window.location.search)
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
return matchRecursive(routes, 0, {});
|
|
715
|
-
}
|
|
716
|
-
function findLayoutChain(routes, targetRoute) {
|
|
717
|
-
const chain = [];
|
|
718
|
-
function findRecursive(routeList, path) {
|
|
719
|
-
for (const route of routeList) {
|
|
720
|
-
const currentPath = [...path, route];
|
|
721
|
-
if (route.id === targetRoute.id) {
|
|
722
|
-
for (const r of currentPath) {
|
|
723
|
-
if (r.layout) {
|
|
724
|
-
chain.push(r);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
return true;
|
|
728
|
-
}
|
|
729
|
-
if (route.children.length > 0) {
|
|
730
|
-
if (findRecursive(route.children, currentPath)) {
|
|
731
|
-
return true;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
return false;
|
|
736
|
-
}
|
|
737
|
-
findRecursive(routes, []);
|
|
738
|
-
return chain;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// src/components/Link.tsx
|
|
742
|
-
import { forwardRef, useCallback as useCallback3 } from "react";
|
|
743
|
-
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
744
|
-
var Link = forwardRef(
|
|
745
|
-
({ href, replace = false, scroll = true, prefetch = true, children, onClick, ...props }, ref) => {
|
|
746
|
-
const router = useOlovaRouter();
|
|
747
|
-
const handleClick = useCallback3(
|
|
748
|
-
(e) => {
|
|
749
|
-
onClick?.(e);
|
|
750
|
-
if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) {
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
if (href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//")) {
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
if (href.startsWith("#")) {
|
|
757
|
-
return;
|
|
758
|
-
}
|
|
759
|
-
e.preventDefault();
|
|
760
|
-
if (replace) {
|
|
761
|
-
router.replace(href, { scroll });
|
|
762
|
-
} else {
|
|
763
|
-
router.navigate(href, { scroll });
|
|
764
|
-
}
|
|
765
|
-
},
|
|
766
|
-
[href, replace, scroll, router, onClick]
|
|
767
|
-
);
|
|
768
|
-
const handleMouseEnter = useCallback3(() => {
|
|
769
|
-
if (prefetch && !href.startsWith("http")) {
|
|
770
|
-
router.prefetch(href);
|
|
771
|
-
}
|
|
772
|
-
}, [href, prefetch, router]);
|
|
773
|
-
return /* @__PURE__ */ jsx7(
|
|
774
|
-
"a",
|
|
775
|
-
{
|
|
776
|
-
ref,
|
|
777
|
-
href,
|
|
778
|
-
onClick: handleClick,
|
|
779
|
-
onMouseEnter: handleMouseEnter,
|
|
780
|
-
...props,
|
|
781
|
-
children
|
|
782
|
-
}
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
);
|
|
786
|
-
Link.displayName = "Link";
|
|
787
|
-
var NavLink = forwardRef(
|
|
788
|
-
({ href, activeClassName = "", inactiveClassName = "", exact = false, className = "", ...props }, ref) => {
|
|
789
|
-
const { pathname } = useOlovaRouter();
|
|
790
|
-
const isActive = exact ? pathname === href : pathname.startsWith(href) && (href === "/" ? pathname === "/" : true);
|
|
791
|
-
const combinedClassName = `${className} ${isActive ? activeClassName : inactiveClassName}`.trim();
|
|
792
|
-
return /* @__PURE__ */ jsx7(
|
|
793
|
-
Link,
|
|
794
|
-
{
|
|
795
|
-
ref,
|
|
796
|
-
href,
|
|
797
|
-
className: combinedClassName,
|
|
798
|
-
"aria-current": isActive ? "page" : void 0,
|
|
799
|
-
...props
|
|
800
|
-
}
|
|
801
|
-
);
|
|
802
|
-
}
|
|
803
|
-
);
|
|
804
|
-
NavLink.displayName = "NavLink";
|
|
805
|
-
export {
|
|
806
|
-
DefaultErrorComponent,
|
|
807
|
-
DefaultLoadingComponent,
|
|
808
|
-
DefaultNotFoundComponent,
|
|
809
|
-
Link,
|
|
810
|
-
MetadataHead,
|
|
811
|
-
MetadataProvider,
|
|
812
|
-
NavLink,
|
|
813
|
-
NotFoundBoundary,
|
|
814
|
-
NotFoundError,
|
|
815
|
-
OlovaRouter,
|
|
816
|
-
RouteErrorBoundary,
|
|
817
|
-
RouteLoadingBoundary,
|
|
818
|
-
Skeleton,
|
|
819
|
-
SkeletonCard,
|
|
820
|
-
SkeletonText,
|
|
821
|
-
generateMetadataHtml,
|
|
822
|
-
notFound,
|
|
823
|
-
setSSRContext,
|
|
824
|
-
useMetadata,
|
|
825
|
-
useOlovaRouter,
|
|
826
|
-
usePageMetadata,
|
|
827
|
-
useParams,
|
|
828
|
-
usePathname,
|
|
829
|
-
useRouter,
|
|
830
|
-
useSearchParams
|
|
831
|
-
};
|
|
832
|
-
//# sourceMappingURL=index.js.map
|