olova 2.0.54 → 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 +34 -283
- 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 +37 -55
- 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/dist/client-BBLXpllK.d.ts +0 -487
- package/dist/client-C0av_vTZ.d.cts +0 -487
- package/dist/client.cjs +0 -850
- package/dist/client.cjs.map +0 -1
- package/dist/client.d.cts +0 -5
- package/dist/client.d.ts +0 -5
- package/dist/client.js +0 -816
- package/dist/client.js.map +0 -1
- package/dist/image.cjs +0 -25
- package/dist/image.cjs.map +0 -1
- package/dist/image.d.cts +0 -1
- package/dist/image.d.ts +0 -1
- package/dist/image.js +0 -3
- package/dist/image.js.map +0 -1
- package/dist/index.cjs +0 -907
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -31
- package/dist/index.d.ts +0 -31
- package/dist/index.js +0 -868
- package/dist/index.js.map +0 -1
- package/dist/plugin/index.cjs +0 -1550
- package/dist/plugin/index.cjs.map +0 -1
- package/dist/plugin/index.d.cts +0 -131
- package/dist/plugin/index.d.ts +0 -131
- package/dist/plugin/index.js +0 -1490
- package/dist/plugin/index.js.map +0 -1
- package/dist/serialization-xKcOESDh.d.cts +0 -122
- package/dist/serialization-xKcOESDh.d.ts +0 -122
- package/dist/server.cjs +0 -547
- package/dist/server.cjs.map +0 -1
- package/dist/server.d.cts +0 -148
- package/dist/server.d.ts +0 -148
- package/dist/server.js +0 -493
- package/dist/server.js.map +0 -1
package/dist/client.cjs
DELETED
|
@@ -1,850 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
-
};
|
|
11
|
-
var __export = (target, all) => {
|
|
12
|
-
for (var name in all)
|
|
13
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
-
};
|
|
15
|
-
var __copyProps = (to, from, except, desc) => {
|
|
16
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
-
for (let key of __getOwnPropNames(from))
|
|
18
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
-
}
|
|
21
|
-
return to;
|
|
22
|
-
};
|
|
23
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
-
mod
|
|
30
|
-
));
|
|
31
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
-
|
|
33
|
-
// src/hydration/scheduler.ts
|
|
34
|
-
var scheduler_exports = {};
|
|
35
|
-
__export(scheduler_exports, {
|
|
36
|
-
HydrationScheduler: () => HydrationScheduler
|
|
37
|
-
});
|
|
38
|
-
var HydrationScheduler;
|
|
39
|
-
var init_scheduler = __esm({
|
|
40
|
-
"src/hydration/scheduler.ts"() {
|
|
41
|
-
"use strict";
|
|
42
|
-
HydrationScheduler = class {
|
|
43
|
-
constructor() {
|
|
44
|
-
this.queue = [];
|
|
45
|
-
this.isProcessing = false;
|
|
46
|
-
this.state = "idle";
|
|
47
|
-
if (typeof window !== "undefined") {
|
|
48
|
-
window.__FLIGHT_CHUNK__ = this.receiveChunk.bind(this);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
getState() {
|
|
52
|
-
return this.state;
|
|
53
|
-
}
|
|
54
|
-
schedule(id, priority, task) {
|
|
55
|
-
const priorityValue = {
|
|
56
|
-
critical: 0,
|
|
57
|
-
high: 1,
|
|
58
|
-
low: 2,
|
|
59
|
-
idle: 3
|
|
60
|
-
}[priority];
|
|
61
|
-
this.queue.push({ id, priority: priorityValue, task });
|
|
62
|
-
this.queue.sort((a, b) => a.priority - b.priority);
|
|
63
|
-
if (!this.isProcessing) {
|
|
64
|
-
this.processQueue();
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
async processQueue() {
|
|
68
|
-
this.isProcessing = true;
|
|
69
|
-
this.state = "hydrating";
|
|
70
|
-
while (this.queue.length > 0) {
|
|
71
|
-
const item = this.queue.shift();
|
|
72
|
-
try {
|
|
73
|
-
if (item.priority >= 2 && "requestIdleCallback" in window) {
|
|
74
|
-
await new Promise((resolve) => {
|
|
75
|
-
window.requestIdleCallback(() => {
|
|
76
|
-
item.task();
|
|
77
|
-
resolve();
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
} else {
|
|
81
|
-
await Promise.resolve().then(item.task);
|
|
82
|
-
}
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error(`[Olova] Hydration failed for ${item.id}:`, error);
|
|
85
|
-
}
|
|
86
|
-
await new Promise((r) => setTimeout(r, 0));
|
|
87
|
-
}
|
|
88
|
-
this.isProcessing = false;
|
|
89
|
-
this.state = "complete";
|
|
90
|
-
if (typeof window !== "undefined") {
|
|
91
|
-
window.dispatchEvent(new CustomEvent("olova:hydration-complete"));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
receiveChunk(chunk) {
|
|
95
|
-
this.state = "streaming";
|
|
96
|
-
const placeholder = document.querySelector(`[data-flight-id="${chunk.id}"]`);
|
|
97
|
-
if (placeholder) {
|
|
98
|
-
const temp = document.createElement("div");
|
|
99
|
-
temp.innerHTML = chunk.html;
|
|
100
|
-
while (temp.firstChild) {
|
|
101
|
-
placeholder.parentNode?.insertBefore(temp.firstChild, placeholder);
|
|
102
|
-
}
|
|
103
|
-
placeholder.remove();
|
|
104
|
-
if (chunk.data) {
|
|
105
|
-
this.schedule(chunk.id, "high", () => {
|
|
106
|
-
this.hydrateNode(chunk.id, chunk.data);
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
hydrateNode(id, data) {
|
|
112
|
-
const element = document.querySelector(`[data-flight-id="${id}"]`);
|
|
113
|
-
if (element) {
|
|
114
|
-
element.setAttribute("data-hydrated", "true");
|
|
115
|
-
element.__FLIGHT_DATA__ = data;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// src/client.ts
|
|
123
|
-
var client_exports = {};
|
|
124
|
-
__export(client_exports, {
|
|
125
|
-
Head: () => Head,
|
|
126
|
-
HeadProvider: () => HeadProvider,
|
|
127
|
-
HydrationScheduler: () => HydrationScheduler,
|
|
128
|
-
Link: () => Link,
|
|
129
|
-
Router: () => Router,
|
|
130
|
-
deserializeProps: () => deserializeProps,
|
|
131
|
-
getFlightData: () => getFlightData,
|
|
132
|
-
getHydrationScheduler: () => getHydrationScheduler,
|
|
133
|
-
navigate: () => navigate,
|
|
134
|
-
parseFlightPayload: () => parseFlightPayload,
|
|
135
|
-
replace: () => replace,
|
|
136
|
-
usePageData: () => usePageData,
|
|
137
|
-
useParams: () => useParams,
|
|
138
|
-
usePathname: () => usePathname,
|
|
139
|
-
useRouter: () => useRouter,
|
|
140
|
-
useSearchParams: () => useSearchParams
|
|
141
|
-
});
|
|
142
|
-
module.exports = __toCommonJS(client_exports);
|
|
143
|
-
|
|
144
|
-
// src/router/context.ts
|
|
145
|
-
var import_react = require("react");
|
|
146
|
-
var pageCache = /* @__PURE__ */ new Map();
|
|
147
|
-
var prefetchPromises = /* @__PURE__ */ new Map();
|
|
148
|
-
var metadataCache = /* @__PURE__ */ new Map();
|
|
149
|
-
var NAVIGATE_EVENT = "olova:navigate";
|
|
150
|
-
var eventHandlers = /* @__PURE__ */ new Map();
|
|
151
|
-
var routerEvents = {
|
|
152
|
-
on(event, handler) {
|
|
153
|
-
if (!eventHandlers.has(event)) {
|
|
154
|
-
eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
155
|
-
}
|
|
156
|
-
eventHandlers.get(event).add(handler);
|
|
157
|
-
},
|
|
158
|
-
off(event, handler) {
|
|
159
|
-
eventHandlers.get(event)?.delete(handler);
|
|
160
|
-
},
|
|
161
|
-
emit(event, ...args) {
|
|
162
|
-
eventHandlers.get(event)?.forEach((handler) => handler(...args));
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
var RouterContext = (0, import_react.createContext)({
|
|
166
|
-
pathname: "/",
|
|
167
|
-
params: {},
|
|
168
|
-
query: {},
|
|
169
|
-
asPath: "/",
|
|
170
|
-
push: async () => true,
|
|
171
|
-
replace: async () => true,
|
|
172
|
-
back: () => {
|
|
173
|
-
},
|
|
174
|
-
forward: () => {
|
|
175
|
-
},
|
|
176
|
-
prefetch: async () => {
|
|
177
|
-
},
|
|
178
|
-
reload: () => {
|
|
179
|
-
},
|
|
180
|
-
isReady: false,
|
|
181
|
-
isNavigating: false,
|
|
182
|
-
isFallback: false,
|
|
183
|
-
events: routerEvents
|
|
184
|
-
});
|
|
185
|
-
var ParamsContext = (0, import_react.createContext)({});
|
|
186
|
-
|
|
187
|
-
// src/router/navigation.ts
|
|
188
|
-
function navigate(to, options = {}) {
|
|
189
|
-
return new Promise((resolve) => {
|
|
190
|
-
const { scroll = true } = options;
|
|
191
|
-
routerEvents.emit("routeChangeStart", to, { shallow: options.shallow });
|
|
192
|
-
routerEvents.emit("beforeHistoryChange", to);
|
|
193
|
-
window.history.pushState({ scroll }, "", to);
|
|
194
|
-
window.dispatchEvent(new CustomEvent(NAVIGATE_EVENT, {
|
|
195
|
-
detail: { path: to, scroll }
|
|
196
|
-
}));
|
|
197
|
-
if (scroll) {
|
|
198
|
-
window.scrollTo(0, 0);
|
|
199
|
-
}
|
|
200
|
-
routerEvents.emit("routeChangeComplete", to, { shallow: options.shallow });
|
|
201
|
-
resolve(true);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
function replace(to, options = {}) {
|
|
205
|
-
return new Promise((resolve) => {
|
|
206
|
-
const { scroll = false } = options;
|
|
207
|
-
routerEvents.emit("routeChangeStart", to, { shallow: options.shallow });
|
|
208
|
-
routerEvents.emit("beforeHistoryChange", to);
|
|
209
|
-
window.history.replaceState({ scroll }, "", to);
|
|
210
|
-
window.dispatchEvent(new CustomEvent(NAVIGATE_EVENT, {
|
|
211
|
-
detail: { path: to, scroll, replace: true }
|
|
212
|
-
}));
|
|
213
|
-
if (scroll) {
|
|
214
|
-
window.scrollTo(0, 0);
|
|
215
|
-
}
|
|
216
|
-
routerEvents.emit("routeChangeComplete", to, { shallow: options.shallow });
|
|
217
|
-
resolve(true);
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// src/router/match.ts
|
|
222
|
-
function matchRoute(routePath, currentPath) {
|
|
223
|
-
if (routePath === currentPath) {
|
|
224
|
-
return { matches: true, params: {}, score: 100 };
|
|
225
|
-
}
|
|
226
|
-
const routeSegments = routePath.split("/").filter(Boolean);
|
|
227
|
-
const pathSegments = currentPath.split("/").filter(Boolean);
|
|
228
|
-
const params = {};
|
|
229
|
-
let score = 0;
|
|
230
|
-
for (let i = 0; i < routeSegments.length; i++) {
|
|
231
|
-
const routeSegment = routeSegments[i];
|
|
232
|
-
const pathSegment = pathSegments[i];
|
|
233
|
-
if (routeSegment?.startsWith("*") && routeSegment?.endsWith("?")) {
|
|
234
|
-
const paramName = routeSegment.slice(1, -1);
|
|
235
|
-
const remainingPath = pathSegments.slice(i);
|
|
236
|
-
params[paramName] = remainingPath.length > 0 ? remainingPath : [];
|
|
237
|
-
score += 1;
|
|
238
|
-
return { matches: true, params, score };
|
|
239
|
-
}
|
|
240
|
-
if (routeSegment?.startsWith("*")) {
|
|
241
|
-
const paramName = routeSegment.slice(1);
|
|
242
|
-
const remainingPath = pathSegments.slice(i);
|
|
243
|
-
if (remainingPath.length > 0) {
|
|
244
|
-
params[paramName] = remainingPath;
|
|
245
|
-
score += 2;
|
|
246
|
-
return { matches: true, params, score };
|
|
247
|
-
}
|
|
248
|
-
return { matches: false, params: {}, score: 0 };
|
|
249
|
-
}
|
|
250
|
-
if (routeSegment?.startsWith(":") || routeSegment?.startsWith("[") && routeSegment?.endsWith("]")) {
|
|
251
|
-
if (!pathSegment) return { matches: false, params: {}, score: 0 };
|
|
252
|
-
const paramName = routeSegment.startsWith(":") ? routeSegment.slice(1) : routeSegment.slice(1, -1);
|
|
253
|
-
params[paramName] = pathSegment;
|
|
254
|
-
score += 5;
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (routeSegment !== pathSegment) return { matches: false, params: {}, score: 0 };
|
|
258
|
-
score += 10;
|
|
259
|
-
}
|
|
260
|
-
if (routeSegments.length !== pathSegments.length) return { matches: false, params: {}, score: 0 };
|
|
261
|
-
return { matches: true, params, score };
|
|
262
|
-
}
|
|
263
|
-
function findRoute(routes, path) {
|
|
264
|
-
const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
265
|
-
const exactMatch = routes.find((r) => r.path === normalizedPath);
|
|
266
|
-
if (exactMatch) return { route: exactMatch, params: {} };
|
|
267
|
-
let bestMatch = null;
|
|
268
|
-
for (const route of routes) {
|
|
269
|
-
const { matches, params, score } = matchRoute(route.path, normalizedPath);
|
|
270
|
-
if (matches && (!bestMatch || score > bestMatch.score)) {
|
|
271
|
-
bestMatch = { route, params, score };
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return bestMatch ? { route: bestMatch.route, params: bestMatch.params } : { route: null, params: {} };
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// src/router/prefetch.ts
|
|
278
|
-
async function prefetchRoute(routes, path) {
|
|
279
|
-
const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
280
|
-
if (prefetchPromises.has(normalizedPath)) {
|
|
281
|
-
return prefetchPromises.get(normalizedPath);
|
|
282
|
-
}
|
|
283
|
-
const { route } = findRoute(routes, normalizedPath);
|
|
284
|
-
if (!route) return;
|
|
285
|
-
const cacheKey = route.path;
|
|
286
|
-
if (pageCache.has(cacheKey)) return;
|
|
287
|
-
const promise = route.component().then((module2) => {
|
|
288
|
-
pageCache.set(cacheKey, module2.default);
|
|
289
|
-
if (module2.metadata) {
|
|
290
|
-
metadataCache.set(cacheKey, module2.metadata);
|
|
291
|
-
}
|
|
292
|
-
}).catch(() => {
|
|
293
|
-
});
|
|
294
|
-
prefetchPromises.set(normalizedPath, promise);
|
|
295
|
-
return promise;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// src/router/hooks.ts
|
|
299
|
-
var import_react2 = require("react");
|
|
300
|
-
function useRouter() {
|
|
301
|
-
return (0, import_react2.useContext)(RouterContext);
|
|
302
|
-
}
|
|
303
|
-
function useParams() {
|
|
304
|
-
return (0, import_react2.useContext)(ParamsContext);
|
|
305
|
-
}
|
|
306
|
-
function usePathname() {
|
|
307
|
-
const { pathname } = (0, import_react2.useContext)(RouterContext);
|
|
308
|
-
return pathname;
|
|
309
|
-
}
|
|
310
|
-
function useSearchParams() {
|
|
311
|
-
const [searchParams, setSearchParams] = (0, import_react2.useState)(
|
|
312
|
-
() => new URLSearchParams(window.location.search)
|
|
313
|
-
);
|
|
314
|
-
(0, import_react2.useEffect)(() => {
|
|
315
|
-
const handleNavigate = () => {
|
|
316
|
-
setSearchParams(new URLSearchParams(window.location.search));
|
|
317
|
-
};
|
|
318
|
-
window.addEventListener(NAVIGATE_EVENT, handleNavigate);
|
|
319
|
-
window.addEventListener("popstate", handleNavigate);
|
|
320
|
-
return () => {
|
|
321
|
-
window.removeEventListener(NAVIGATE_EVENT, handleNavigate);
|
|
322
|
-
window.removeEventListener("popstate", handleNavigate);
|
|
323
|
-
};
|
|
324
|
-
}, []);
|
|
325
|
-
return searchParams;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// src/router/Link.tsx
|
|
329
|
-
var import_react3 = require("react");
|
|
330
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
331
|
-
function Link({
|
|
332
|
-
href,
|
|
333
|
-
children,
|
|
334
|
-
prefetch: shouldPrefetch = true,
|
|
335
|
-
scroll = true,
|
|
336
|
-
replace: shouldReplace = false,
|
|
337
|
-
shallow = false,
|
|
338
|
-
...props
|
|
339
|
-
}) {
|
|
340
|
-
const prefetchedRef = (0, import_react3.useRef)(false);
|
|
341
|
-
const linkRef = (0, import_react3.useRef)(null);
|
|
342
|
-
const getRoutes = (0, import_react3.useCallback)(() => {
|
|
343
|
-
return window.__OLOVA_ROUTES__ || [];
|
|
344
|
-
}, []);
|
|
345
|
-
(0, import_react3.useEffect)(() => {
|
|
346
|
-
if (!shouldPrefetch || prefetchedRef.current || !linkRef.current) return;
|
|
347
|
-
const observer = new IntersectionObserver(
|
|
348
|
-
(entries) => {
|
|
349
|
-
if (entries[0].isIntersecting && !prefetchedRef.current) {
|
|
350
|
-
prefetchedRef.current = true;
|
|
351
|
-
prefetchRoute(getRoutes(), href);
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
{ rootMargin: "200px" }
|
|
355
|
-
);
|
|
356
|
-
observer.observe(linkRef.current);
|
|
357
|
-
return () => observer.disconnect();
|
|
358
|
-
}, [href, shouldPrefetch, getRoutes]);
|
|
359
|
-
const handleMouseEnter = (0, import_react3.useCallback)(() => {
|
|
360
|
-
if (!prefetchedRef.current) {
|
|
361
|
-
prefetchedRef.current = true;
|
|
362
|
-
prefetchRoute(getRoutes(), href);
|
|
363
|
-
}
|
|
364
|
-
}, [href, getRoutes]);
|
|
365
|
-
const handleClick = (0, import_react3.useCallback)((e) => {
|
|
366
|
-
if (e.ctrlKey || e.metaKey || e.shiftKey || e.button !== 0 || props.target === "_blank" || href.startsWith("http") || href.startsWith("//")) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
e.preventDefault();
|
|
370
|
-
if (shouldReplace) {
|
|
371
|
-
replace(href, { scroll, shallow });
|
|
372
|
-
} else {
|
|
373
|
-
navigate(href, { scroll, shallow });
|
|
374
|
-
}
|
|
375
|
-
}, [href, scroll, shallow, shouldReplace, props.target]);
|
|
376
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
377
|
-
"a",
|
|
378
|
-
{
|
|
379
|
-
ref: linkRef,
|
|
380
|
-
href,
|
|
381
|
-
onClick: handleClick,
|
|
382
|
-
onMouseEnter: handleMouseEnter,
|
|
383
|
-
...props,
|
|
384
|
-
children
|
|
385
|
-
}
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// src/router/Router.tsx
|
|
390
|
-
var import_react5 = __toESM(require("react"), 1);
|
|
391
|
-
|
|
392
|
-
// src/router/BuiltinComponents.tsx
|
|
393
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
394
|
-
function NotFound() {
|
|
395
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "4rem 2rem", textAlign: "center" }, children: [
|
|
396
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: { fontSize: "4rem", margin: 0 }, children: "404" }),
|
|
397
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: "1.25rem", color: "#666" }, children: "This page could not be found." }),
|
|
398
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Link, { href: "/", style: { color: "#0070f3" }, children: "Go back home" })
|
|
399
|
-
] });
|
|
400
|
-
}
|
|
401
|
-
function ErrorPage() {
|
|
402
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "4rem 2rem", textAlign: "center" }, children: [
|
|
403
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { style: { fontSize: "2rem", margin: 0 }, children: "Something went wrong" }),
|
|
404
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: "1rem", color: "#666" }, children: "Failed to load this page." }),
|
|
405
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => window.location.reload(), style: {
|
|
406
|
-
padding: "0.5rem 1rem",
|
|
407
|
-
background: "#0070f3",
|
|
408
|
-
color: "white",
|
|
409
|
-
border: "none",
|
|
410
|
-
borderRadius: "4px",
|
|
411
|
-
cursor: "pointer"
|
|
412
|
-
}, children: "Try again" })
|
|
413
|
-
] });
|
|
414
|
-
}
|
|
415
|
-
function LoadingIndicator() {
|
|
416
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "2rem", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
|
|
417
|
-
width: "40px",
|
|
418
|
-
height: "40px",
|
|
419
|
-
border: "3px solid #f3f3f3",
|
|
420
|
-
borderTop: "3px solid #0070f3",
|
|
421
|
-
borderRadius: "50%",
|
|
422
|
-
animation: "olova-spin 1s linear infinite",
|
|
423
|
-
margin: "0 auto"
|
|
424
|
-
} }) });
|
|
425
|
-
}
|
|
426
|
-
function NavigationProgress() {
|
|
427
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
|
|
428
|
-
position: "fixed",
|
|
429
|
-
top: 0,
|
|
430
|
-
left: 0,
|
|
431
|
-
right: 0,
|
|
432
|
-
height: "3px",
|
|
433
|
-
background: "linear-gradient(90deg, #0070f3, #00a8ff)",
|
|
434
|
-
animation: "olova-loading 1s ease-in-out infinite",
|
|
435
|
-
zIndex: 9999
|
|
436
|
-
} });
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// src/router/Styles.ts
|
|
440
|
-
function injectStyles() {
|
|
441
|
-
if (typeof document !== "undefined") {
|
|
442
|
-
const style = document.createElement("style");
|
|
443
|
-
style.textContent = `
|
|
444
|
-
@keyframes olova-loading {
|
|
445
|
-
0% { transform: translateX(-100%); }
|
|
446
|
-
50% { transform: translateX(0); }
|
|
447
|
-
100% { transform: translateX(100%); }
|
|
448
|
-
}
|
|
449
|
-
@keyframes olova-spin {
|
|
450
|
-
0% { transform: rotate(0deg); }
|
|
451
|
-
100% { transform: rotate(360deg); }
|
|
452
|
-
}
|
|
453
|
-
`;
|
|
454
|
-
document.head.appendChild(style);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// src/router/useRouterInternal.ts
|
|
459
|
-
var import_react4 = require("react");
|
|
460
|
-
|
|
461
|
-
// src/router/Metadata.ts
|
|
462
|
-
function applyMetadata(metadata) {
|
|
463
|
-
if (!metadata || typeof document === "undefined") return;
|
|
464
|
-
if (metadata.title) {
|
|
465
|
-
document.title = metadata.title;
|
|
466
|
-
}
|
|
467
|
-
const metaTags = {
|
|
468
|
-
description: metadata.description,
|
|
469
|
-
keywords: metadata.keywords
|
|
470
|
-
};
|
|
471
|
-
for (const [name, content] of Object.entries(metaTags)) {
|
|
472
|
-
if (content) {
|
|
473
|
-
let meta = document.querySelector(`meta[name="${name}"]`);
|
|
474
|
-
if (!meta) {
|
|
475
|
-
meta = document.createElement("meta");
|
|
476
|
-
meta.setAttribute("name", name);
|
|
477
|
-
document.head.appendChild(meta);
|
|
478
|
-
}
|
|
479
|
-
meta.setAttribute("content", content);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
if (metadata.openGraph) {
|
|
483
|
-
const og = metadata.openGraph;
|
|
484
|
-
const ogTags = {
|
|
485
|
-
"og:title": og.title,
|
|
486
|
-
"og:description": og.description,
|
|
487
|
-
"og:type": og.type,
|
|
488
|
-
"og:url": og.url,
|
|
489
|
-
"og:image": og.image
|
|
490
|
-
};
|
|
491
|
-
for (const [property, content] of Object.entries(ogTags)) {
|
|
492
|
-
if (content) {
|
|
493
|
-
let meta = document.querySelector(`meta[property="${property}"]`);
|
|
494
|
-
if (!meta) {
|
|
495
|
-
meta = document.createElement("meta");
|
|
496
|
-
meta.setAttribute("property", property);
|
|
497
|
-
document.head.appendChild(meta);
|
|
498
|
-
}
|
|
499
|
-
meta.setAttribute("content", content);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// src/router/Query.ts
|
|
506
|
-
function parseQueryString(search) {
|
|
507
|
-
const params = new URLSearchParams(search);
|
|
508
|
-
const result = {};
|
|
509
|
-
params.forEach((value, key) => {
|
|
510
|
-
if (result[key]) {
|
|
511
|
-
if (Array.isArray(result[key])) {
|
|
512
|
-
result[key].push(value);
|
|
513
|
-
} else {
|
|
514
|
-
result[key] = [result[key], value];
|
|
515
|
-
}
|
|
516
|
-
} else {
|
|
517
|
-
result[key] = value;
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
return result;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// src/router/useRouterInternal.ts
|
|
524
|
-
function useRouterInternal(routes) {
|
|
525
|
-
const [currentPath, setCurrentPath] = (0, import_react4.useState)(() => {
|
|
526
|
-
if (typeof window === "undefined") return "/";
|
|
527
|
-
const path = window.location.pathname;
|
|
528
|
-
return path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
529
|
-
});
|
|
530
|
-
const [query, setQuery] = (0, import_react4.useState)(() => {
|
|
531
|
-
if (typeof window === "undefined") return {};
|
|
532
|
-
return parseQueryString(window.location.search);
|
|
533
|
-
});
|
|
534
|
-
const [components, setComponents] = (0, import_react4.useState)({ page: null, layouts: [] });
|
|
535
|
-
const [params, setParams] = (0, import_react4.useState)({});
|
|
536
|
-
const [isNavigating, setIsNavigating] = (0, import_react4.useState)(false);
|
|
537
|
-
const [isReady, setIsReady] = (0, import_react4.useState)(false);
|
|
538
|
-
const isHydrating = (0, import_react4.useRef)(true);
|
|
539
|
-
(0, import_react4.useEffect)(() => {
|
|
540
|
-
const handleNavigate = (e) => {
|
|
541
|
-
const customEvent = e;
|
|
542
|
-
const newPath = customEvent.detail?.path || window.location.pathname;
|
|
543
|
-
const normalizedPath = newPath.endsWith("/") && newPath !== "/" ? newPath.slice(0, -1) : newPath;
|
|
544
|
-
isHydrating.current = false;
|
|
545
|
-
(0, import_react4.startTransition)(() => {
|
|
546
|
-
setCurrentPath(normalizedPath);
|
|
547
|
-
setQuery(parseQueryString(window.location.search));
|
|
548
|
-
});
|
|
549
|
-
};
|
|
550
|
-
const handlePopState = () => {
|
|
551
|
-
const path = window.location.pathname;
|
|
552
|
-
const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
|
|
553
|
-
isHydrating.current = false;
|
|
554
|
-
(0, import_react4.startTransition)(() => {
|
|
555
|
-
setCurrentPath(normalizedPath);
|
|
556
|
-
setQuery(parseQueryString(window.location.search));
|
|
557
|
-
});
|
|
558
|
-
};
|
|
559
|
-
window.addEventListener(NAVIGATE_EVENT, handleNavigate);
|
|
560
|
-
window.addEventListener("popstate", handlePopState);
|
|
561
|
-
return () => {
|
|
562
|
-
window.removeEventListener(NAVIGATE_EVENT, handleNavigate);
|
|
563
|
-
window.removeEventListener("popstate", handlePopState);
|
|
564
|
-
};
|
|
565
|
-
}, []);
|
|
566
|
-
(0, import_react4.useEffect)(() => {
|
|
567
|
-
const { route, params: extractedParams } = findRoute(routes, currentPath);
|
|
568
|
-
const loadComponent = async (loader) => {
|
|
569
|
-
if (!loader) return void 0;
|
|
570
|
-
const module2 = await loader();
|
|
571
|
-
return module2.default;
|
|
572
|
-
};
|
|
573
|
-
if (!route) {
|
|
574
|
-
const findParentLayouts = async () => {
|
|
575
|
-
const segments = currentPath.split("/").filter(Boolean);
|
|
576
|
-
for (let i = segments.length - 1; i >= 0; i--) {
|
|
577
|
-
const partialPath = "/" + segments.slice(0, i).join("/");
|
|
578
|
-
const { route: parentRoute } = findRoute(routes, partialPath);
|
|
579
|
-
if (parentRoute) {
|
|
580
|
-
const layouts = await Promise.all((parentRoute.layouts || []).map((l) => loadComponent(l)));
|
|
581
|
-
return layouts.filter((l) => !!l);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
return [];
|
|
585
|
-
};
|
|
586
|
-
findParentLayouts().then((layouts) => {
|
|
587
|
-
setComponents((prev) => ({ ...prev, page: NotFound, layouts }));
|
|
588
|
-
setParams({});
|
|
589
|
-
setIsReady(true);
|
|
590
|
-
});
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
setParams(extractedParams);
|
|
594
|
-
if (!isHydrating.current) setIsNavigating(true);
|
|
595
|
-
const loadRoute = async () => {
|
|
596
|
-
try {
|
|
597
|
-
const [page, layouts, loading, error, notFound2, template] = await Promise.all([
|
|
598
|
-
loadComponent(route.component),
|
|
599
|
-
Promise.all((route.layouts || []).map((l) => loadComponent(l))),
|
|
600
|
-
loadComponent(route.loading),
|
|
601
|
-
loadComponent(route.error),
|
|
602
|
-
loadComponent(route.notFound),
|
|
603
|
-
loadComponent(route.template)
|
|
604
|
-
]);
|
|
605
|
-
if (route.metadata) {
|
|
606
|
-
metadataCache.set(route.path, route.metadata);
|
|
607
|
-
applyMetadata(route.metadata);
|
|
608
|
-
}
|
|
609
|
-
(0, import_react4.startTransition)(() => {
|
|
610
|
-
setComponents({
|
|
611
|
-
page: page || null,
|
|
612
|
-
layouts: layouts.filter((l) => !!l),
|
|
613
|
-
loading,
|
|
614
|
-
error,
|
|
615
|
-
notFound: notFound2,
|
|
616
|
-
template
|
|
617
|
-
});
|
|
618
|
-
setIsNavigating(false);
|
|
619
|
-
setIsReady(true);
|
|
620
|
-
isHydrating.current = false;
|
|
621
|
-
});
|
|
622
|
-
} catch (err) {
|
|
623
|
-
console.error("[Olova] Failed to load route:", err);
|
|
624
|
-
routerEvents.emit("routeChangeError", err, currentPath);
|
|
625
|
-
setComponents({ page: ErrorPage, layouts: [] });
|
|
626
|
-
setIsNavigating(false);
|
|
627
|
-
setIsReady(true);
|
|
628
|
-
}
|
|
629
|
-
};
|
|
630
|
-
loadRoute();
|
|
631
|
-
}, [currentPath, routes]);
|
|
632
|
-
return { currentPath, query, components, params, isNavigating, isReady, isHydrating };
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// src/router/Router.tsx
|
|
636
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
637
|
-
injectStyles();
|
|
638
|
-
var ErrorBoundary = class extends import_react5.default.Component {
|
|
639
|
-
constructor(props) {
|
|
640
|
-
super(props);
|
|
641
|
-
this.reset = () => this.setState({ hasError: false, error: null });
|
|
642
|
-
this.state = { hasError: false, error: null };
|
|
643
|
-
}
|
|
644
|
-
static getDerivedStateFromError(error) {
|
|
645
|
-
return { hasError: true, error };
|
|
646
|
-
}
|
|
647
|
-
render() {
|
|
648
|
-
if (this.state.hasError && this.props.fallback) {
|
|
649
|
-
const Fallback = this.props.fallback;
|
|
650
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Fallback, { error: this.state.error, reset: this.reset });
|
|
651
|
-
}
|
|
652
|
-
return this.props.children;
|
|
653
|
-
}
|
|
654
|
-
};
|
|
655
|
-
function Router({ routes }) {
|
|
656
|
-
const routesRef = (0, import_react5.useRef)(routes);
|
|
657
|
-
routesRef.current = routes;
|
|
658
|
-
const {
|
|
659
|
-
currentPath,
|
|
660
|
-
query,
|
|
661
|
-
components,
|
|
662
|
-
params,
|
|
663
|
-
isNavigating,
|
|
664
|
-
isReady
|
|
665
|
-
} = useRouterInternal(routes);
|
|
666
|
-
(0, import_react5.useEffect)(() => {
|
|
667
|
-
const handleHashChange = () => {
|
|
668
|
-
routerEvents.emit("hashChangeStart", window.location.hash);
|
|
669
|
-
routerEvents.emit("hashChangeComplete", window.location.hash);
|
|
670
|
-
};
|
|
671
|
-
window.addEventListener("hashchange", handleHashChange);
|
|
672
|
-
return () => window.removeEventListener("hashchange", handleHashChange);
|
|
673
|
-
}, []);
|
|
674
|
-
const routerContextValue = (0, import_react5.useMemo)(() => ({
|
|
675
|
-
pathname: currentPath,
|
|
676
|
-
params,
|
|
677
|
-
query,
|
|
678
|
-
asPath: typeof window !== "undefined" ? currentPath + window.location.search + window.location.hash : currentPath,
|
|
679
|
-
push: navigate,
|
|
680
|
-
replace,
|
|
681
|
-
back: () => typeof window !== "undefined" && window.history.back(),
|
|
682
|
-
forward: () => typeof window !== "undefined" && window.history.forward(),
|
|
683
|
-
prefetch: (url) => prefetchRoute(routesRef.current, url),
|
|
684
|
-
reload: () => typeof window !== "undefined" && window.location.reload(),
|
|
685
|
-
isReady,
|
|
686
|
-
isNavigating,
|
|
687
|
-
isFallback: false,
|
|
688
|
-
events: routerEvents
|
|
689
|
-
}), [currentPath, params, query, isReady, isNavigating]);
|
|
690
|
-
if (!components.page) return null;
|
|
691
|
-
const { page: Page, layouts, loading: Loading, error: ErrorComp } = components;
|
|
692
|
-
let content = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ErrorBoundary, { fallback: ErrorComp, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Page, { params, searchParams: query }) });
|
|
693
|
-
for (let i = layouts.length - 1; i >= 0; i--) {
|
|
694
|
-
const Layout = layouts[i];
|
|
695
|
-
content = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ErrorBoundary, { fallback: ErrorComp, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Layout, { children: content, params, searchParams: query }) }, i);
|
|
696
|
-
}
|
|
697
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RouterContext.Provider, { value: routerContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ParamsContext.Provider, { value: params, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react5.Suspense, { fallback: Loading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Loading, {}) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoadingIndicator, {}), children: [
|
|
698
|
-
content,
|
|
699
|
-
isNavigating && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NavigationProgress, {})
|
|
700
|
-
] }) }) });
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
// src/head/Head.tsx
|
|
704
|
-
var import_react7 = __toESM(require("react"), 1);
|
|
705
|
-
|
|
706
|
-
// src/head/HeadProvider.tsx
|
|
707
|
-
var import_react6 = require("react");
|
|
708
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
709
|
-
var HeadContext = (0, import_react6.createContext)(null);
|
|
710
|
-
function HeadProvider({ children }) {
|
|
711
|
-
const [state, setState] = (0, import_react6.useState)({
|
|
712
|
-
metas: /* @__PURE__ */ new Map(),
|
|
713
|
-
links: /* @__PURE__ */ new Map()
|
|
714
|
-
});
|
|
715
|
-
const update = (updates) => {
|
|
716
|
-
setState((prev) => ({ ...prev, ...updates }));
|
|
717
|
-
};
|
|
718
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeadContext.Provider, { value: { state, update }, children });
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
// src/head/Head.tsx
|
|
722
|
-
function Head({ children }) {
|
|
723
|
-
const context = (0, import_react7.useContext)(HeadContext);
|
|
724
|
-
(0, import_react7.useEffect)(() => {
|
|
725
|
-
import_react7.default.Children.forEach(children, (child) => {
|
|
726
|
-
if (!import_react7.default.isValidElement(child)) return;
|
|
727
|
-
const { type, props } = child;
|
|
728
|
-
if (type === "title") {
|
|
729
|
-
const titleProps = props;
|
|
730
|
-
if (typeof titleProps.children === "string") {
|
|
731
|
-
document.title = titleProps.children;
|
|
732
|
-
context?.update({ title: titleProps.children });
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
if (type === "meta") {
|
|
736
|
-
const metaProps = props;
|
|
737
|
-
const key = metaProps.name || metaProps.property || metaProps.httpEquiv;
|
|
738
|
-
if (key) {
|
|
739
|
-
let meta = document.querySelector(`meta[name="${key}"], meta[property="${key}"]`);
|
|
740
|
-
if (!meta) {
|
|
741
|
-
meta = document.createElement("meta");
|
|
742
|
-
if (metaProps.name) meta.setAttribute("name", metaProps.name);
|
|
743
|
-
if (metaProps.property) meta.setAttribute("property", metaProps.property);
|
|
744
|
-
document.head.appendChild(meta);
|
|
745
|
-
}
|
|
746
|
-
meta.setAttribute("content", metaProps.content);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
if (type === "link") {
|
|
750
|
-
const linkProps = props;
|
|
751
|
-
const key = linkProps.href;
|
|
752
|
-
let link = document.querySelector(`link[href="${key}"]`);
|
|
753
|
-
if (!link) {
|
|
754
|
-
link = document.createElement("link");
|
|
755
|
-
link.setAttribute("rel", linkProps.rel);
|
|
756
|
-
link.setAttribute("href", linkProps.href);
|
|
757
|
-
if (linkProps.as) link.setAttribute("as", linkProps.as);
|
|
758
|
-
document.head.appendChild(link);
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
});
|
|
762
|
-
return () => {
|
|
763
|
-
};
|
|
764
|
-
}, [children, context]);
|
|
765
|
-
return null;
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
// src/head/ssr.ts
|
|
769
|
-
var import_react8 = __toESM(require("react"), 1);
|
|
770
|
-
|
|
771
|
-
// src/data/provider.tsx
|
|
772
|
-
var import_react9 = require("react");
|
|
773
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
774
|
-
var PageDataContext = (0, import_react9.createContext)(null);
|
|
775
|
-
|
|
776
|
-
// src/data/hooks.ts
|
|
777
|
-
var import_react10 = require("react");
|
|
778
|
-
function usePageData() {
|
|
779
|
-
const context = (0, import_react10.useContext)(PageDataContext);
|
|
780
|
-
const [data, setData] = (0, import_react10.useState)(context);
|
|
781
|
-
(0, import_react10.useEffect)(() => {
|
|
782
|
-
if (typeof window !== "undefined" && window.__OLOVA_PAGE_DATA__) {
|
|
783
|
-
setData(window.__OLOVA_PAGE_DATA__);
|
|
784
|
-
}
|
|
785
|
-
}, []);
|
|
786
|
-
return data;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
// src/hydration/serialization.ts
|
|
790
|
-
function deserializeProps(props) {
|
|
791
|
-
const result = {};
|
|
792
|
-
for (const [key, value] of Object.entries(props)) {
|
|
793
|
-
if (value && typeof value === "object") {
|
|
794
|
-
if (value.__type === "Date") {
|
|
795
|
-
result[key] = new Date(value.value);
|
|
796
|
-
} else if (value.__type === "Map") {
|
|
797
|
-
result[key] = new Map(value.value);
|
|
798
|
-
} else if (value.__type === "Set") {
|
|
799
|
-
result[key] = new Set(value.value);
|
|
800
|
-
} else {
|
|
801
|
-
result[key] = deserializeProps(value);
|
|
802
|
-
}
|
|
803
|
-
} else {
|
|
804
|
-
result[key] = value;
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
return result;
|
|
808
|
-
}
|
|
809
|
-
function parseFlightPayload() {
|
|
810
|
-
if (typeof window === "undefined") return null;
|
|
811
|
-
const flight = window.__FLIGHT__;
|
|
812
|
-
return flight || null;
|
|
813
|
-
}
|
|
814
|
-
function getFlightData(key) {
|
|
815
|
-
const payload = parseFlightPayload();
|
|
816
|
-
if (!payload) return null;
|
|
817
|
-
return payload.data[key] ?? null;
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
// src/hydration/index.ts
|
|
821
|
-
init_scheduler();
|
|
822
|
-
var clientScheduler = null;
|
|
823
|
-
function getHydrationScheduler() {
|
|
824
|
-
if (typeof window === "undefined") return null;
|
|
825
|
-
if (!clientScheduler) {
|
|
826
|
-
const { HydrationScheduler: HydrationScheduler2 } = (init_scheduler(), __toCommonJS(scheduler_exports));
|
|
827
|
-
clientScheduler = new HydrationScheduler2();
|
|
828
|
-
}
|
|
829
|
-
return clientScheduler;
|
|
830
|
-
}
|
|
831
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
832
|
-
0 && (module.exports = {
|
|
833
|
-
Head,
|
|
834
|
-
HeadProvider,
|
|
835
|
-
HydrationScheduler,
|
|
836
|
-
Link,
|
|
837
|
-
Router,
|
|
838
|
-
deserializeProps,
|
|
839
|
-
getFlightData,
|
|
840
|
-
getHydrationScheduler,
|
|
841
|
-
navigate,
|
|
842
|
-
parseFlightPayload,
|
|
843
|
-
replace,
|
|
844
|
-
usePageData,
|
|
845
|
-
useParams,
|
|
846
|
-
usePathname,
|
|
847
|
-
useRouter,
|
|
848
|
-
useSearchParams
|
|
849
|
-
});
|
|
850
|
-
//# sourceMappingURL=client.cjs.map
|