@flight-framework/router 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,453 +1,465 @@
1
- import {
2
- __commonJS,
3
- __require,
4
- __toESM,
5
- clearPrefetchCache,
6
- findRoute,
7
- generatePath,
8
- getRouterContext,
9
- initRouter,
10
- isActive,
11
- isPrefetched,
12
- matchRoute,
13
- navigate,
14
- observeForPrefetch,
15
- parseParams,
16
- prefetch,
17
- prefetchAll,
18
- prefetchPages,
19
- prefetchWhenIdle,
20
- redirect,
21
- setupIntentPrefetch,
22
- subscribe
23
- } from "../chunk-YXMDNDIZ.js";
24
-
25
- // ../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.production.js
26
- var require_react_dom_production = __commonJS({
27
- "../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.production.js"(exports) {
28
- "use strict";
29
- var React3 = __require("react");
30
- function formatProdErrorMessage(code) {
31
- var url = "https://react.dev/errors/" + code;
32
- if (1 < arguments.length) {
33
- url += "?args[]=" + encodeURIComponent(arguments[1]);
34
- for (var i = 2; i < arguments.length; i++)
35
- url += "&args[]=" + encodeURIComponent(arguments[i]);
36
- }
37
- return "Minified React error #" + code + "; visit " + url + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";
38
- }
39
- function noop() {
40
- }
41
- var Internals = {
42
- d: {
43
- f: noop,
44
- r: function() {
45
- throw Error(formatProdErrorMessage(522));
46
- },
47
- D: noop,
48
- C: noop,
49
- L: noop,
50
- m: noop,
51
- X: noop,
52
- S: noop,
53
- M: noop
54
- },
55
- p: 0,
56
- findDOMNode: null
57
- };
58
- var REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal");
59
- function createPortal$1(children, containerInfo, implementation) {
60
- var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
61
- return {
62
- $$typeof: REACT_PORTAL_TYPE,
63
- key: null == key ? null : "" + key,
64
- children,
65
- containerInfo,
66
- implementation
67
- };
68
- }
69
- var ReactSharedInternals = React3.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
70
- function getCrossOriginStringAs(as, input) {
71
- if ("font" === as) return "";
72
- if ("string" === typeof input)
73
- return "use-credentials" === input ? input : "";
74
- }
75
- exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals;
76
- exports.createPortal = function(children, container) {
77
- var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
78
- if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType)
79
- throw Error(formatProdErrorMessage(299));
80
- return createPortal$1(children, container, null, key);
81
- };
82
- exports.flushSync = function(fn) {
83
- var previousTransition = ReactSharedInternals.T, previousUpdatePriority = Internals.p;
84
- try {
85
- if (ReactSharedInternals.T = null, Internals.p = 2, fn) return fn();
86
- } finally {
87
- ReactSharedInternals.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f();
88
- }
89
- };
90
- exports.preconnect = function(href, options) {
91
- "string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals.d.C(href, options));
92
- };
93
- exports.prefetchDNS = function(href) {
94
- "string" === typeof href && Internals.d.D(href);
95
- };
96
- exports.preinit = function(href, options) {
97
- if ("string" === typeof href && options && "string" === typeof options.as) {
98
- var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
99
- "style" === as ? Internals.d.S(
100
- href,
101
- "string" === typeof options.precedence ? options.precedence : void 0,
102
- {
103
- crossOrigin,
104
- integrity,
105
- fetchPriority
106
- }
107
- ) : "script" === as && Internals.d.X(href, {
108
- crossOrigin,
109
- integrity,
110
- fetchPriority,
111
- nonce: "string" === typeof options.nonce ? options.nonce : void 0
1
+ // src/context.ts
2
+ var isBrowser = typeof window !== "undefined";
3
+ var currentContext = {
4
+ path: "/",
5
+ searchParams: new URLSearchParams(),
6
+ navigate: () => {
7
+ },
8
+ back: () => {
9
+ },
10
+ forward: () => {
11
+ }
12
+ };
13
+ var subscribers = /* @__PURE__ */ new Set();
14
+ function subscribe(callback) {
15
+ subscribers.add(callback);
16
+ return () => subscribers.delete(callback);
17
+ }
18
+ function getRouterContext() {
19
+ return currentContext;
20
+ }
21
+ function updateContext(updates) {
22
+ currentContext = { ...currentContext, ...updates };
23
+ subscribers.forEach((cb) => cb(currentContext));
24
+ }
25
+ function navigateTo(to, options = {}) {
26
+ if (!isBrowser) return;
27
+ const { replace = false, scroll = true, state } = options;
28
+ if (replace) {
29
+ window.history.replaceState(state ?? null, "", to);
30
+ } else {
31
+ window.history.pushState(state ?? null, "", to);
32
+ }
33
+ const url = new URL(to, window.location.origin);
34
+ updateContext({
35
+ path: url.pathname,
36
+ searchParams: url.searchParams
37
+ });
38
+ if (scroll) {
39
+ window.scrollTo({ top: 0, left: 0, behavior: "instant" });
40
+ }
41
+ }
42
+ function initRouter(options = {}) {
43
+ const { initialPath, basePath = "" } = options;
44
+ let path;
45
+ let searchParams;
46
+ if (isBrowser) {
47
+ path = window.location.pathname;
48
+ searchParams = new URLSearchParams(window.location.search);
49
+ } else {
50
+ path = initialPath || "/";
51
+ searchParams = new URLSearchParams();
52
+ }
53
+ if (basePath && path.startsWith(basePath)) {
54
+ path = path.slice(basePath.length) || "/";
55
+ }
56
+ currentContext = {
57
+ path,
58
+ searchParams,
59
+ navigate: navigateTo,
60
+ back: () => isBrowser && window.history.back(),
61
+ forward: () => isBrowser && window.history.forward()
62
+ };
63
+ if (isBrowser) {
64
+ window.addEventListener("popstate", () => {
65
+ updateContext({
66
+ path: window.location.pathname,
67
+ searchParams: new URLSearchParams(window.location.search)
68
+ });
69
+ });
70
+ const originalPushState = history.pushState.bind(history);
71
+ const originalReplaceState = history.replaceState.bind(history);
72
+ history.pushState = function(state, unused, url) {
73
+ originalPushState(state, unused, url);
74
+ if (url) {
75
+ const newUrl = new URL(url.toString(), window.location.origin);
76
+ updateContext({
77
+ path: newUrl.pathname,
78
+ searchParams: newUrl.searchParams
112
79
  });
113
80
  }
114
81
  };
115
- exports.preinitModule = function(href, options) {
116
- if ("string" === typeof href)
117
- if ("object" === typeof options && null !== options) {
118
- if (null == options.as || "script" === options.as) {
119
- var crossOrigin = getCrossOriginStringAs(
120
- options.as,
121
- options.crossOrigin
122
- );
123
- Internals.d.M(href, {
124
- crossOrigin,
125
- integrity: "string" === typeof options.integrity ? options.integrity : void 0,
126
- nonce: "string" === typeof options.nonce ? options.nonce : void 0
127
- });
128
- }
129
- } else null == options && Internals.d.M(href);
130
- };
131
- exports.preload = function(href, options) {
132
- if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
133
- var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);
134
- Internals.d.L(href, as, {
135
- crossOrigin,
136
- integrity: "string" === typeof options.integrity ? options.integrity : void 0,
137
- nonce: "string" === typeof options.nonce ? options.nonce : void 0,
138
- type: "string" === typeof options.type ? options.type : void 0,
139
- fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
140
- referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
141
- imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
142
- imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
143
- media: "string" === typeof options.media ? options.media : void 0
82
+ history.replaceState = function(state, unused, url) {
83
+ originalReplaceState(state, unused, url);
84
+ if (url) {
85
+ const newUrl = new URL(url.toString(), window.location.origin);
86
+ updateContext({
87
+ path: newUrl.pathname,
88
+ searchParams: newUrl.searchParams
144
89
  });
145
90
  }
146
91
  };
147
- exports.preloadModule = function(href, options) {
148
- if ("string" === typeof href)
149
- if (options) {
150
- var crossOrigin = getCrossOriginStringAs(options.as, options.crossOrigin);
151
- Internals.d.m(href, {
152
- as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
153
- crossOrigin,
154
- integrity: "string" === typeof options.integrity ? options.integrity : void 0
155
- });
156
- } else Internals.d.m(href);
157
- };
158
- exports.requestFormReset = function(form) {
159
- Internals.d.r(form);
160
- };
161
- exports.unstable_batchedUpdates = function(fn, a) {
162
- return fn(a);
163
- };
164
- exports.useFormState = function(action, initialState, permalink) {
165
- return ReactSharedInternals.H.useFormState(action, initialState, permalink);
166
- };
167
- exports.useFormStatus = function() {
168
- return ReactSharedInternals.H.useHostTransitionStatus();
169
- };
170
- exports.version = "19.2.3";
171
92
  }
172
- });
173
-
174
- // ../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.development.js
175
- var require_react_dom_development = __commonJS({
176
- "../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.development.js"(exports) {
177
- "use strict";
178
- "production" !== process.env.NODE_ENV && (function() {
179
- function noop() {
180
- }
181
- function testStringCoercion(value) {
182
- return "" + value;
183
- }
184
- function createPortal$1(children, containerInfo, implementation) {
185
- var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
186
- try {
187
- testStringCoercion(key);
188
- var JSCompiler_inline_result = false;
189
- } catch (e) {
190
- JSCompiler_inline_result = true;
191
- }
192
- JSCompiler_inline_result && (console.error(
193
- "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
194
- "function" === typeof Symbol && Symbol.toStringTag && key[Symbol.toStringTag] || key.constructor.name || "Object"
195
- ), testStringCoercion(key));
196
- return {
197
- $$typeof: REACT_PORTAL_TYPE,
198
- key: null == key ? null : "" + key,
199
- children,
200
- containerInfo,
201
- implementation
202
- };
203
- }
204
- function getCrossOriginStringAs(as, input) {
205
- if ("font" === as) return "";
206
- if ("string" === typeof input)
207
- return "use-credentials" === input ? input : "";
208
- }
209
- function getValueDescriptorExpectingObjectForWarning(thing) {
210
- return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : 'something with type "' + typeof thing + '"';
211
- }
212
- function getValueDescriptorExpectingEnumForWarning(thing) {
213
- return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "string" === typeof thing ? JSON.stringify(thing) : "number" === typeof thing ? "`" + thing + "`" : 'something with type "' + typeof thing + '"';
214
- }
215
- function resolveDispatcher() {
216
- var dispatcher = ReactSharedInternals.H;
217
- null === dispatcher && console.error(
218
- "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem."
93
+ }
94
+ var initialized = false;
95
+ if (isBrowser && !initialized) {
96
+ initialized = true;
97
+ initRouter();
98
+ }
99
+ var RouterContext = null;
100
+ var RouterProvider = null;
101
+ var useRouter = getRouterContext;
102
+ if (typeof globalThis !== "undefined") {
103
+ try {
104
+ const React3 = globalThis.React;
105
+ if (React3?.createContext) {
106
+ const { createContext: createContext2, useState: useState2, useEffect: useEffect3, useContext: useContext3 } = React3;
107
+ const ReactRouterContext = createContext2(currentContext);
108
+ RouterContext = ReactRouterContext;
109
+ RouterProvider = function FlightRouterProvider({
110
+ children,
111
+ initialPath,
112
+ basePath = ""
113
+ }) {
114
+ const [routerState, setRouterState] = useState2(() => {
115
+ const path = isBrowser ? window.location.pathname : initialPath || "/";
116
+ const searchParams = isBrowser ? new URLSearchParams(window.location.search) : new URLSearchParams();
117
+ return {
118
+ path: basePath && path.startsWith(basePath) ? path.slice(basePath.length) || "/" : path,
119
+ searchParams,
120
+ navigate: navigateTo,
121
+ back: () => isBrowser && window.history.back(),
122
+ forward: () => isBrowser && window.history.forward()
123
+ };
124
+ });
125
+ useEffect3(() => {
126
+ if (!isBrowser) return;
127
+ const handlePopState = () => {
128
+ let path = window.location.pathname;
129
+ if (basePath && path.startsWith(basePath)) {
130
+ path = path.slice(basePath.length) || "/";
131
+ }
132
+ setRouterState((prev) => ({
133
+ ...prev,
134
+ path,
135
+ searchParams: new URLSearchParams(window.location.search)
136
+ }));
137
+ };
138
+ window.addEventListener("popstate", handlePopState);
139
+ return () => window.removeEventListener("popstate", handlePopState);
140
+ }, [basePath]);
141
+ useEffect3(() => {
142
+ return subscribe((ctx) => {
143
+ setRouterState((prev) => ({
144
+ ...prev,
145
+ path: ctx.path,
146
+ searchParams: ctx.searchParams
147
+ }));
148
+ });
149
+ }, []);
150
+ return React3.createElement(
151
+ ReactRouterContext.Provider,
152
+ { value: routerState },
153
+ children
219
154
  );
220
- return dispatcher;
221
- }
222
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
223
- var React3 = __require("react"), Internals = {
224
- d: {
225
- f: noop,
226
- r: function() {
227
- throw Error(
228
- "Invalid form element. requestFormReset must be passed a form that was rendered by React."
229
- );
230
- },
231
- D: noop,
232
- C: noop,
233
- L: noop,
234
- m: noop,
235
- X: noop,
236
- S: noop,
237
- M: noop
238
- },
239
- p: 0,
240
- findDOMNode: null
241
- }, REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), ReactSharedInternals = React3.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
242
- "function" === typeof Map && null != Map.prototype && "function" === typeof Map.prototype.forEach && "function" === typeof Set && null != Set.prototype && "function" === typeof Set.prototype.clear && "function" === typeof Set.prototype.forEach || console.error(
243
- "React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"
244
- );
245
- exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals;
246
- exports.createPortal = function(children, container) {
247
- var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
248
- if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType)
249
- throw Error("Target container is not a DOM element.");
250
- return createPortal$1(children, container, null, key);
251
- };
252
- exports.flushSync = function(fn) {
253
- var previousTransition = ReactSharedInternals.T, previousUpdatePriority = Internals.p;
254
- try {
255
- if (ReactSharedInternals.T = null, Internals.p = 2, fn)
256
- return fn();
257
- } finally {
258
- ReactSharedInternals.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f() && console.error(
259
- "flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task."
260
- );
261
- }
262
155
  };
263
- exports.preconnect = function(href, options) {
264
- "string" === typeof href && href ? null != options && "object" !== typeof options ? console.error(
265
- "ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.",
266
- getValueDescriptorExpectingEnumForWarning(options)
267
- ) : null != options && "string" !== typeof options.crossOrigin && console.error(
268
- "ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.",
269
- getValueDescriptorExpectingObjectForWarning(options.crossOrigin)
270
- ) : console.error(
271
- "ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
272
- getValueDescriptorExpectingObjectForWarning(href)
273
- );
274
- "string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals.d.C(href, options));
156
+ useRouter = function useFlightRouter() {
157
+ return useContext3(ReactRouterContext);
275
158
  };
276
- exports.prefetchDNS = function(href) {
277
- if ("string" !== typeof href || !href)
278
- console.error(
279
- "ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
280
- getValueDescriptorExpectingObjectForWarning(href)
281
- );
282
- else if (1 < arguments.length) {
283
- var options = arguments[1];
284
- "object" === typeof options && options.hasOwnProperty("crossOrigin") ? console.error(
285
- "ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.",
286
- getValueDescriptorExpectingEnumForWarning(options)
287
- ) : console.error(
288
- "ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.",
289
- getValueDescriptorExpectingEnumForWarning(options)
290
- );
291
- }
292
- "string" === typeof href && Internals.d.D(href);
159
+ }
160
+ } catch {
161
+ }
162
+ }
163
+
164
+ // src/navigate.ts
165
+ var isBrowser2 = typeof window !== "undefined";
166
+ function navigate(to, options = {}) {
167
+ const { navigate: routerNavigate } = getRouterContext();
168
+ routerNavigate(to, options);
169
+ }
170
+ function patternToRegex(pattern) {
171
+ const paramNames = [];
172
+ let regexStr = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\\\[\.\.\.(\w+)\\\]/g, (_, name) => {
173
+ paramNames.push(name);
174
+ return "(.+)";
175
+ }).replace(/\\\[(\w+)\\\]/g, (_, name) => {
176
+ paramNames.push(name);
177
+ return "([^/]+)";
178
+ }).replace(/:(\w+)/g, (_, name) => {
179
+ paramNames.push(name);
180
+ return "([^/]+)";
181
+ });
182
+ regexStr = `^${regexStr}$`;
183
+ return {
184
+ regex: new RegExp(regexStr),
185
+ paramNames
186
+ };
187
+ }
188
+ function matchRoute(pathname, pattern) {
189
+ const { regex, paramNames } = patternToRegex(pattern);
190
+ const match = pathname.match(regex);
191
+ if (!match) {
192
+ return { matched: false, params: {} };
193
+ }
194
+ const params = {};
195
+ paramNames.forEach((name, index) => {
196
+ params[name] = match[index + 1] || "";
197
+ });
198
+ return { matched: true, params };
199
+ }
200
+ function parseParams(pathname, pattern) {
201
+ const { params } = matchRoute(pathname, pattern);
202
+ return params;
203
+ }
204
+ function findRoute(pathname, routes) {
205
+ for (const route of routes) {
206
+ const { matched, params } = matchRoute(pathname, route.path);
207
+ if (matched) {
208
+ return {
209
+ route,
210
+ params,
211
+ pathname
293
212
  };
294
- exports.preinit = function(href, options) {
295
- "string" === typeof href && href ? null == options || "object" !== typeof options ? console.error(
296
- "ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.",
297
- getValueDescriptorExpectingEnumForWarning(options)
298
- ) : "style" !== options.as && "script" !== options.as && console.error(
299
- 'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are "style" and "script".',
300
- getValueDescriptorExpectingEnumForWarning(options.as)
301
- ) : console.error(
302
- "ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
303
- getValueDescriptorExpectingObjectForWarning(href)
304
- );
305
- if ("string" === typeof href && options && "string" === typeof options.as) {
306
- var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
307
- "style" === as ? Internals.d.S(
308
- href,
309
- "string" === typeof options.precedence ? options.precedence : void 0,
310
- {
311
- crossOrigin,
312
- integrity,
313
- fetchPriority
213
+ }
214
+ }
215
+ return null;
216
+ }
217
+ function generatePath(pattern, params = {}) {
218
+ let path = pattern;
219
+ path = path.replace(/\[(\w+)\]/g, (_, name) => {
220
+ return params[name] || "";
221
+ });
222
+ path = path.replace(/:(\w+)/g, (_, name) => {
223
+ return params[name] || "";
224
+ });
225
+ return path;
226
+ }
227
+ function isActive(pattern) {
228
+ const { path } = getRouterContext();
229
+ const { matched } = matchRoute(path, pattern);
230
+ return matched;
231
+ }
232
+ function redirect(url) {
233
+ if (isBrowser2) {
234
+ window.location.href = url;
235
+ }
236
+ throw new Error(`Redirect to: ${url}`);
237
+ }
238
+
239
+ // src/prefetch.ts
240
+ var isBrowser3 = typeof window !== "undefined";
241
+ var supportsIntersectionObserver = isBrowser3 && "IntersectionObserver" in window;
242
+ var prefetchedUrls = /* @__PURE__ */ new Set();
243
+ var prefetchingUrls = /* @__PURE__ */ new Set();
244
+ var viewportObservers = /* @__PURE__ */ new Map();
245
+ function prefetch(href, options = {}) {
246
+ if (!isBrowser3) return;
247
+ const {
248
+ priority = "auto",
249
+ includeModules = true,
250
+ includeData = false
251
+ } = options;
252
+ const url = normalizeUrl(href);
253
+ if (prefetchedUrls.has(url) || prefetchingUrls.has(url)) {
254
+ return;
255
+ }
256
+ prefetchingUrls.add(url);
257
+ createPrefetchLink(url, "document", priority);
258
+ if (includeModules) {
259
+ prefetchModules(url, priority);
260
+ }
261
+ if (includeData) {
262
+ prefetchData(url, priority);
263
+ }
264
+ prefetchedUrls.add(url);
265
+ prefetchingUrls.delete(url);
266
+ }
267
+ function prefetchAll(hrefs, options = {}) {
268
+ for (const href of hrefs) {
269
+ prefetch(href, options);
270
+ }
271
+ }
272
+ function isPrefetched(href) {
273
+ return prefetchedUrls.has(normalizeUrl(href));
274
+ }
275
+ function clearPrefetchCache() {
276
+ prefetchedUrls.clear();
277
+ prefetchingUrls.clear();
278
+ }
279
+ function createPrefetchLink(href, as, priority) {
280
+ if (!isBrowser3) return null;
281
+ const existing = document.querySelector(
282
+ `link[rel="prefetch"][href="${href}"], link[rel="modulepreload"][href="${href}"]`
283
+ );
284
+ if (existing) return existing;
285
+ const link = document.createElement("link");
286
+ if (as === "script") {
287
+ link.rel = "modulepreload";
288
+ } else {
289
+ link.rel = "prefetch";
290
+ link.as = as;
291
+ }
292
+ link.href = href;
293
+ if (priority !== "auto" && "fetchPriority" in link) {
294
+ link.fetchPriority = priority;
295
+ }
296
+ if (priority === "low" && "requestIdleCallback" in window) {
297
+ window.requestIdleCallback(() => {
298
+ document.head.appendChild(link);
299
+ });
300
+ } else {
301
+ document.head.appendChild(link);
302
+ }
303
+ return link;
304
+ }
305
+ function prefetchModules(href, priority) {
306
+ const manifest = window.__FLIGHT_MANIFEST__;
307
+ if (!manifest?.routes) return;
308
+ const routeModules = manifest.routes[href];
309
+ if (!routeModules) return;
310
+ for (const module of routeModules) {
311
+ createPrefetchLink(module, "script", priority);
312
+ }
313
+ }
314
+ function prefetchData(href, priority) {
315
+ const dataUrl = `/_flight/data${href === "/" ? "/index" : href}.json`;
316
+ createPrefetchLink(dataUrl, "fetch", priority);
317
+ }
318
+ var sharedObserver = null;
319
+ var observerCallbacks = /* @__PURE__ */ new Map();
320
+ function getViewportObserver() {
321
+ if (!supportsIntersectionObserver) return null;
322
+ if (!sharedObserver) {
323
+ sharedObserver = new IntersectionObserver(
324
+ (entries) => {
325
+ for (const entry of entries) {
326
+ if (entry.isIntersecting) {
327
+ const callback = observerCallbacks.get(entry.target);
328
+ if (callback) {
329
+ callback();
330
+ sharedObserver?.unobserve(entry.target);
331
+ observerCallbacks.delete(entry.target);
314
332
  }
315
- ) : "script" === as && Internals.d.X(href, {
316
- crossOrigin,
317
- integrity,
318
- fetchPriority,
319
- nonce: "string" === typeof options.nonce ? options.nonce : void 0
320
- });
333
+ }
321
334
  }
322
- };
323
- exports.preinitModule = function(href, options) {
324
- var encountered = "";
325
- "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
326
- void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "script" !== options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingEnumForWarning(options.as) + ".");
327
- if (encountered)
328
- console.error(
329
- "ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s",
330
- encountered
331
- );
332
- else
333
- switch (encountered = options && "string" === typeof options.as ? options.as : "script", encountered) {
334
- case "script":
335
- break;
336
- default:
337
- encountered = getValueDescriptorExpectingEnumForWarning(encountered), console.error(
338
- 'ReactDOM.preinitModule(): Currently the only supported "as" type for this function is "script" but received "%s" instead. This warning was generated for `href` "%s". In the future other module types will be supported, aligning with the import-attributes proposal. Learn more here: (https://github.com/tc39/proposal-import-attributes)',
339
- encountered,
340
- href
341
- );
335
+ },
336
+ {
337
+ // Start prefetching when link is 25% visible or within 100px of viewport
338
+ rootMargin: "100px",
339
+ threshold: 0.25
340
+ }
341
+ );
342
+ }
343
+ return sharedObserver;
344
+ }
345
+ function observeForPrefetch(element, href) {
346
+ if (!supportsIntersectionObserver) {
347
+ return () => {
348
+ };
349
+ }
350
+ const observer = getViewportObserver();
351
+ if (!observer) return () => {
352
+ };
353
+ const callback = () => {
354
+ prefetch(href, { priority: "low" });
355
+ };
356
+ observerCallbacks.set(element, callback);
357
+ observer.observe(element);
358
+ const cleanup = () => {
359
+ observer.unobserve(element);
360
+ observerCallbacks.delete(element);
361
+ viewportObservers.delete(element);
362
+ };
363
+ viewportObservers.set(element, cleanup);
364
+ return cleanup;
365
+ }
366
+ function setupIntentPrefetch(element, href) {
367
+ if (!isBrowser3) return () => {
368
+ };
369
+ let prefetchTriggered = false;
370
+ const handleIntent = () => {
371
+ if (!prefetchTriggered) {
372
+ prefetchTriggered = true;
373
+ prefetch(href, { priority: "auto" });
374
+ }
375
+ };
376
+ element.addEventListener("mouseenter", handleIntent, { passive: true });
377
+ element.addEventListener("focus", handleIntent, { passive: true });
378
+ element.addEventListener("touchstart", handleIntent, { passive: true });
379
+ return () => {
380
+ element.removeEventListener("mouseenter", handleIntent);
381
+ element.removeEventListener("focus", handleIntent);
382
+ element.removeEventListener("touchstart", handleIntent);
383
+ };
384
+ }
385
+ function normalizeUrl(href) {
386
+ if (isBrowser3 && !href.startsWith("http")) {
387
+ try {
388
+ const url = new URL(href, window.location.origin);
389
+ return url.pathname + url.search;
390
+ } catch {
391
+ return href;
392
+ }
393
+ }
394
+ return href;
395
+ }
396
+
397
+ // src/prefetch-links.ts
398
+ var isBrowser4 = typeof window !== "undefined";
399
+ var PrefetchPageLinks = null;
400
+ if (typeof globalThis !== "undefined") {
401
+ try {
402
+ const React3 = globalThis.React;
403
+ if (React3?.createElement && "useEffect" in React3) {
404
+ const { useEffect: useEffect3, useState: useState2 } = React3;
405
+ PrefetchPageLinks = function FlightPrefetchPageLinks({
406
+ page,
407
+ options = {}
408
+ }) {
409
+ const [shouldRender, setShouldRender] = useState2(false);
410
+ useEffect3(() => {
411
+ if (!isBrowser4) return;
412
+ if (isPrefetched(page)) {
413
+ return;
342
414
  }
343
- if ("string" === typeof href)
344
- if ("object" === typeof options && null !== options) {
345
- if (null == options.as || "script" === options.as)
346
- encountered = getCrossOriginStringAs(
347
- options.as,
348
- options.crossOrigin
349
- ), Internals.d.M(href, {
350
- crossOrigin: encountered,
351
- integrity: "string" === typeof options.integrity ? options.integrity : void 0,
352
- nonce: "string" === typeof options.nonce ? options.nonce : void 0
353
- });
354
- } else null == options && Internals.d.M(href);
355
- };
356
- exports.preload = function(href, options) {
357
- var encountered = "";
358
- "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
359
- null == options || "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : "string" === typeof options.as && options.as || (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
360
- encountered && console.error(
361
- 'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel="preload" as="..." />` tag.%s',
362
- encountered
363
- );
364
- if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
365
- encountered = options.as;
366
- var crossOrigin = getCrossOriginStringAs(
367
- encountered,
368
- options.crossOrigin
369
- );
370
- Internals.d.L(href, encountered, {
371
- crossOrigin,
372
- integrity: "string" === typeof options.integrity ? options.integrity : void 0,
373
- nonce: "string" === typeof options.nonce ? options.nonce : void 0,
374
- type: "string" === typeof options.type ? options.type : void 0,
375
- fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
376
- referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
377
- imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
378
- imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
379
- media: "string" === typeof options.media ? options.media : void 0
415
+ prefetch(page, {
416
+ priority: "low",
417
+ includeModules: true,
418
+ ...options
380
419
  });
381
- }
382
- };
383
- exports.preloadModule = function(href, options) {
384
- var encountered = "";
385
- "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
386
- void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
387
- encountered && console.error(
388
- 'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel="modulepreload" as="..." />` tag.%s',
389
- encountered
390
- );
391
- "string" === typeof href && (options ? (encountered = getCrossOriginStringAs(
392
- options.as,
393
- options.crossOrigin
394
- ), Internals.d.m(href, {
395
- as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
396
- crossOrigin: encountered,
397
- integrity: "string" === typeof options.integrity ? options.integrity : void 0
398
- })) : Internals.d.m(href));
399
- };
400
- exports.requestFormReset = function(form) {
401
- Internals.d.r(form);
420
+ setShouldRender(false);
421
+ }, [page, options]);
422
+ return null;
402
423
  };
403
- exports.unstable_batchedUpdates = function(fn, a) {
404
- return fn(a);
405
- };
406
- exports.useFormState = function(action, initialState, permalink) {
407
- return resolveDispatcher().useFormState(action, initialState, permalink);
408
- };
409
- exports.useFormStatus = function() {
410
- return resolveDispatcher().useHostTransitionStatus();
411
- };
412
- exports.version = "19.2.3";
413
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
414
- })();
424
+ }
425
+ } catch {
415
426
  }
416
- });
417
-
418
- // ../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/index.js
419
- var require_react_dom = __commonJS({
420
- "../../node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/index.js"(exports, module) {
421
- "use strict";
422
- function checkDCE() {
423
- if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== "function") {
424
- return;
425
- }
426
- if (process.env.NODE_ENV !== "production") {
427
- throw new Error("^_^");
428
- }
429
- try {
430
- __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);
431
- } catch (err) {
432
- console.error(err);
433
- }
427
+ }
428
+ function prefetchPages(pages, options = {}) {
429
+ if (!isBrowser4) return;
430
+ for (const page of pages) {
431
+ if (!isPrefetched(page)) {
432
+ prefetch(page, {
433
+ priority: "low",
434
+ ...options
435
+ });
434
436
  }
435
- if (process.env.NODE_ENV === "production") {
436
- checkDCE();
437
- module.exports = require_react_dom_production();
438
- } else {
439
- module.exports = require_react_dom_development();
437
+ }
438
+ }
439
+ function prefetchWhenIdle(page, options = {}) {
440
+ if (!isBrowser4) return;
441
+ const doPrefetch = () => {
442
+ if (!isPrefetched(page)) {
443
+ prefetch(page, {
444
+ priority: "low",
445
+ ...options
446
+ });
440
447
  }
448
+ };
449
+ if ("requestIdleCallback" in window) {
450
+ window.requestIdleCallback(doPrefetch, { timeout: 3e3 });
451
+ } else {
452
+ setTimeout(doPrefetch, 100);
441
453
  }
442
- });
454
+ }
443
455
 
444
456
  // src/react/Link.tsx
445
- var import_react_dom = __toESM(require_react_dom(), 1);
446
457
  import { useCallback, useEffect, useRef } from "react";
458
+ import { flushSync } from "react-dom";
447
459
  import { jsx } from "react/jsx-runtime";
448
- var isBrowser = typeof window !== "undefined";
460
+ var isBrowser5 = typeof window !== "undefined";
449
461
  function isViewTransitionSupported() {
450
- return isBrowser && "startViewTransition" in document;
462
+ return isBrowser5 && "startViewTransition" in document;
451
463
  }
452
464
  function isExternalUrl(href) {
453
465
  if (!href) return false;
@@ -470,14 +482,14 @@ function handleLinkClick(href, options, event) {
470
482
  const { viewTransition, ...navOptions } = options;
471
483
  if (viewTransition && isViewTransitionSupported()) {
472
484
  document.startViewTransition(() => {
473
- (0, import_react_dom.flushSync)(() => {
485
+ flushSync(() => {
474
486
  navigate2(href, navOptions);
475
487
  });
476
488
  });
477
489
  } else {
478
490
  navigate2(href, navOptions);
479
491
  }
480
- if (options.scroll !== false) {
492
+ if (options.scroll !== false && isBrowser5) {
481
493
  window.scrollTo({ top: 0, left: 0, behavior: "instant" });
482
494
  }
483
495
  }
@@ -510,7 +522,7 @@ function Link({
510
522
  [href, isExternal, target, replace, scroll, viewTransition, onClick]
511
523
  );
512
524
  useEffect(() => {
513
- if (isExternal || !isBrowser || prefetchStrategy === "none") {
525
+ if (isExternal || !isBrowser5 || prefetchStrategy === "none") {
514
526
  return;
515
527
  }
516
528
  const link = linkRef.current;
@@ -546,9 +558,9 @@ function Link({
546
558
  // src/react/RouterProvider.tsx
547
559
  import { createContext, useContext, useState, useEffect as useEffect2 } from "react";
548
560
  import { jsx as jsx2 } from "react/jsx-runtime";
549
- var isBrowser2 = typeof window !== "undefined";
550
- function navigateTo(to, options = {}) {
551
- if (!isBrowser2) return;
561
+ var isBrowser6 = typeof window !== "undefined";
562
+ function navigateTo2(to, options = {}) {
563
+ if (!isBrowser6) return;
552
564
  const { replace = false, scroll = true, state } = options;
553
565
  if (replace) {
554
566
  window.history.replaceState(state ?? null, "", to);
@@ -562,22 +574,22 @@ function navigateTo(to, options = {}) {
562
574
  var defaultContext = {
563
575
  path: "/",
564
576
  searchParams: new URLSearchParams(),
565
- navigate: navigateTo,
566
- back: () => isBrowser2 && window.history.back(),
567
- forward: () => isBrowser2 && window.history.forward()
577
+ navigate: navigateTo2,
578
+ back: () => isBrowser6 && window.history.back(),
579
+ forward: () => isBrowser6 && window.history.forward()
568
580
  };
569
- var RouterContext = createContext(defaultContext);
570
- function useRouter() {
571
- return useContext(RouterContext);
581
+ var RouterContext2 = createContext(defaultContext);
582
+ function useRouter2() {
583
+ return useContext(RouterContext2);
572
584
  }
573
- function RouterProvider({
585
+ function RouterProvider2({
574
586
  children,
575
587
  initialPath,
576
588
  basePath = ""
577
589
  }) {
578
590
  const [routerState, setRouterState] = useState(() => {
579
- const path = isBrowser2 ? window.location.pathname : initialPath || "/";
580
- const searchParams = isBrowser2 ? new URLSearchParams(window.location.search) : new URLSearchParams();
591
+ const path = isBrowser6 ? window.location.pathname : initialPath || "/";
592
+ const searchParams = isBrowser6 ? new URLSearchParams(window.location.search) : new URLSearchParams();
581
593
  let normalizedPath = path;
582
594
  if (basePath && path.startsWith(basePath)) {
583
595
  normalizedPath = path.slice(basePath.length) || "/";
@@ -585,13 +597,13 @@ function RouterProvider({
585
597
  return {
586
598
  path: normalizedPath,
587
599
  searchParams,
588
- navigate: navigateTo,
589
- back: () => isBrowser2 && window.history.back(),
590
- forward: () => isBrowser2 && window.history.forward()
600
+ navigate: navigateTo2,
601
+ back: () => isBrowser6 && window.history.back(),
602
+ forward: () => isBrowser6 && window.history.forward()
591
603
  };
592
604
  });
593
605
  useEffect2(() => {
594
- if (!isBrowser2) return;
606
+ if (!isBrowser6) return;
595
607
  const handlePopState = () => {
596
608
  let path = window.location.pathname;
597
609
  if (basePath && path.startsWith(basePath)) {
@@ -619,20 +631,20 @@ function RouterProvider({
619
631
  }));
620
632
  });
621
633
  }, [basePath]);
622
- return /* @__PURE__ */ jsx2(RouterContext.Provider, { value: routerState, children });
634
+ return /* @__PURE__ */ jsx2(RouterContext2.Provider, { value: routerState, children });
623
635
  }
624
636
 
625
637
  // src/react/hooks.ts
626
638
  import { useContext as useContext2, useSyncExternalStore } from "react";
627
- var isBrowser3 = typeof window !== "undefined";
639
+ var isBrowser7 = typeof window !== "undefined";
628
640
  function getPathnameSnapshot() {
629
- return isBrowser3 ? window.location.pathname : "/";
641
+ return isBrowser7 ? window.location.pathname : "/";
630
642
  }
631
643
  function getPathnameServerSnapshot() {
632
644
  return "/";
633
645
  }
634
646
  function subscribeToPathname(callback) {
635
- if (!isBrowser3) return () => {
647
+ if (!isBrowser7) return () => {
636
648
  };
637
649
  window.addEventListener("popstate", callback);
638
650
  const unsubscribe = subscribe(callback);
@@ -649,7 +661,7 @@ function usePathname() {
649
661
  );
650
662
  }
651
663
  function useSearchParams() {
652
- const { searchParams } = useContext2(RouterContext);
664
+ const { searchParams } = useContext2(RouterContext2);
653
665
  return searchParams;
654
666
  }
655
667
  function useParams() {
@@ -657,8 +669,8 @@ function useParams() {
657
669
  }
658
670
  export {
659
671
  Link,
660
- RouterContext,
661
- RouterProvider,
672
+ RouterContext2 as RouterContext,
673
+ RouterProvider2 as RouterProvider,
662
674
  clearPrefetchCache,
663
675
  findRoute,
664
676
  generatePath,
@@ -679,30 +691,6 @@ export {
679
691
  subscribe,
680
692
  useParams,
681
693
  usePathname,
682
- useRouter,
694
+ useRouter2 as useRouter,
683
695
  useSearchParams
684
696
  };
685
- /*! Bundled license information:
686
-
687
- react-dom/cjs/react-dom.production.js:
688
- (**
689
- * @license React
690
- * react-dom.production.js
691
- *
692
- * Copyright (c) Meta Platforms, Inc. and affiliates.
693
- *
694
- * This source code is licensed under the MIT license found in the
695
- * LICENSE file in the root directory of this source tree.
696
- *)
697
-
698
- react-dom/cjs/react-dom.development.js:
699
- (**
700
- * @license React
701
- * react-dom.development.js
702
- *
703
- * Copyright (c) Meta Platforms, Inc. and affiliates.
704
- *
705
- * This source code is licensed under the MIT license found in the
706
- * LICENSE file in the root directory of this source tree.
707
- *)
708
- */