@fluixi/core 1.0.0-alpha.100

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.
Files changed (253) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +334 -0
  3. package/dist/cdn/core.global.js +2 -0
  4. package/dist/cli/generate.cjs +5639 -0
  5. package/dist/cli/generate.d.ts +7 -0
  6. package/dist/cli/generate.d.ts.map +1 -0
  7. package/dist/cli/generate.js +2580 -0
  8. package/dist/cli/generate.mjs +5644 -0
  9. package/dist/cli/index.cjs +5639 -0
  10. package/dist/cli/index.d.ts +7 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +2580 -0
  13. package/dist/cli/index.mjs +5644 -0
  14. package/dist/cli/run.cjs +64 -0
  15. package/dist/cli/run.d.ts +3 -0
  16. package/dist/cli/run.d.ts.map +1 -0
  17. package/dist/cli/run.js +62 -0
  18. package/dist/cli/run.mjs +40 -0
  19. package/dist/fluixi.d.ts +5 -0
  20. package/dist/src/cdn/chunk-RKBFEFZP.mjs +987 -0
  21. package/dist/src/cdn/core.cjs +1592 -0
  22. package/dist/src/cdn/core.d.ts +16 -0
  23. package/dist/src/cdn/core.d.ts.map +1 -0
  24. package/dist/src/cdn/core.js +15 -0
  25. package/dist/src/cdn/core.mjs +714 -0
  26. package/dist/src/cdn/router-V2THK27H.mjs +74 -0
  27. package/dist/src/index.cjs +1711 -0
  28. package/dist/src/index.d.ts +4 -0
  29. package/dist/src/index.d.ts.map +1 -0
  30. package/dist/src/index.js +11 -0
  31. package/dist/src/index.mjs +1833 -0
  32. package/dist/src/jsx-dev-runtime.cjs +26 -0
  33. package/dist/src/jsx-dev-runtime.d.ts +2 -0
  34. package/dist/src/jsx-dev-runtime.d.ts.map +1 -0
  35. package/dist/src/jsx-dev-runtime.js +1 -0
  36. package/dist/src/jsx-dev-runtime.mjs +24 -0
  37. package/dist/src/jsx-runtime.cjs +26 -0
  38. package/dist/src/jsx-runtime.d.ts +7 -0
  39. package/dist/src/jsx-runtime.d.ts.map +1 -0
  40. package/dist/src/jsx-runtime.js +8 -0
  41. package/dist/src/jsx-runtime.mjs +24 -0
  42. package/dist/src/lib/client/chunk-FDOPDB6Z.mjs +53 -0
  43. package/dist/src/lib/client/index.cjs +1210 -0
  44. package/dist/src/lib/client/index.d.ts +51 -0
  45. package/dist/src/lib/client/index.d.ts.map +1 -0
  46. package/dist/src/lib/client/index.js +174 -0
  47. package/dist/src/lib/client/index.mjs +293 -0
  48. package/dist/src/lib/client/router-4PTBPZLQ.mjs +891 -0
  49. package/dist/src/lib/context/context.cjs +81 -0
  50. package/dist/src/lib/context/context.d.ts +73 -0
  51. package/dist/src/lib/context/context.d.ts.map +1 -0
  52. package/dist/src/lib/context/context.js +93 -0
  53. package/dist/src/lib/context/context.mjs +64 -0
  54. package/dist/src/lib/context/index.cjs +83 -0
  55. package/dist/src/lib/context/index.d.ts +3 -0
  56. package/dist/src/lib/context/index.d.ts.map +1 -0
  57. package/dist/src/lib/context/index.js +1 -0
  58. package/dist/src/lib/context/index.mjs +64 -0
  59. package/dist/src/lib/control-flow.cjs +35 -0
  60. package/dist/src/lib/control-flow.d.ts +4 -0
  61. package/dist/src/lib/control-flow.d.ts.map +1 -0
  62. package/dist/src/lib/control-flow.js +1 -0
  63. package/dist/src/lib/control-flow.mjs +25 -0
  64. package/dist/src/lib/core.cjs +1710 -0
  65. package/dist/src/lib/core.d.ts +91 -0
  66. package/dist/src/lib/core.d.ts.map +1 -0
  67. package/dist/src/lib/core.js +158 -0
  68. package/dist/src/lib/core.mjs +1833 -0
  69. package/dist/src/lib/env/index.cjs +44 -0
  70. package/dist/src/lib/env/index.d.ts +26 -0
  71. package/dist/src/lib/env/index.d.ts.map +1 -0
  72. package/dist/src/lib/env/index.js +31 -0
  73. package/dist/src/lib/env/index.mjs +23 -0
  74. package/dist/src/lib/i18n/index.cjs +123 -0
  75. package/dist/src/lib/i18n/index.d.ts +110 -0
  76. package/dist/src/lib/i18n/index.d.ts.map +1 -0
  77. package/dist/src/lib/i18n/index.js +164 -0
  78. package/dist/src/lib/i18n/index.mjs +103 -0
  79. package/dist/src/lib/index.cjs +598 -0
  80. package/dist/src/lib/index.d.ts +81 -0
  81. package/dist/src/lib/index.d.ts.map +1 -0
  82. package/dist/src/lib/index.js +130 -0
  83. package/dist/src/lib/index.mjs +688 -0
  84. package/dist/src/lib/isomorphic.cjs +90 -0
  85. package/dist/src/lib/isomorphic.d.ts +114 -0
  86. package/dist/src/lib/isomorphic.d.ts.map +1 -0
  87. package/dist/src/lib/isomorphic.js +132 -0
  88. package/dist/src/lib/isomorphic.mjs +69 -0
  89. package/dist/src/lib/jsx-runtime/index.cjs +21 -0
  90. package/dist/src/lib/jsx-runtime/index.d.ts +13 -0
  91. package/dist/src/lib/jsx-runtime/index.d.ts.map +1 -0
  92. package/dist/src/lib/jsx-runtime/index.js +13 -0
  93. package/dist/src/lib/jsx-runtime/index.mjs +4 -0
  94. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +21 -0
  95. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts +2 -0
  96. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts.map +1 -0
  97. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.js +1 -0
  98. package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +4 -0
  99. package/dist/src/lib/plugins/fluixi-routes-plugin.cjs +302 -0
  100. package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts +35 -0
  101. package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts.map +1 -0
  102. package/dist/src/lib/plugins/fluixi-routes-plugin.js +118 -0
  103. package/dist/src/lib/plugins/fluixi-routes-plugin.mjs +271 -0
  104. package/dist/src/lib/plugins/index.cjs +311 -0
  105. package/dist/src/lib/plugins/index.d.ts +6 -0
  106. package/dist/src/lib/plugins/index.d.ts.map +1 -0
  107. package/dist/src/lib/plugins/index.js +7 -0
  108. package/dist/src/lib/plugins/index.mjs +279 -0
  109. package/dist/src/lib/plugins/route-codegen.cjs +73 -0
  110. package/dist/src/lib/plugins/route-codegen.d.ts +12 -0
  111. package/dist/src/lib/plugins/route-codegen.d.ts.map +1 -0
  112. package/dist/src/lib/plugins/route-codegen.js +80 -0
  113. package/dist/src/lib/plugins/route-codegen.mjs +52 -0
  114. package/dist/src/lib/plugins/route-scanner.cjs +189 -0
  115. package/dist/src/lib/plugins/route-scanner.d.ts +38 -0
  116. package/dist/src/lib/plugins/route-scanner.d.ts.map +1 -0
  117. package/dist/src/lib/plugins/route-scanner.js +215 -0
  118. package/dist/src/lib/plugins/route-scanner.mjs +158 -0
  119. package/dist/src/lib/plugins/vite.cjs +27 -0
  120. package/dist/src/lib/plugins/vite.d.ts +3 -0
  121. package/dist/src/lib/plugins/vite.d.ts.map +1 -0
  122. package/dist/src/lib/plugins/vite.js +1 -0
  123. package/dist/src/lib/plugins/vite.mjs +6 -0
  124. package/dist/src/lib/render/await.cjs +38 -0
  125. package/dist/src/lib/render/await.d.ts +26 -0
  126. package/dist/src/lib/render/await.d.ts.map +1 -0
  127. package/dist/src/lib/render/await.js +45 -0
  128. package/dist/src/lib/render/await.mjs +17 -0
  129. package/dist/src/lib/render/component.cjs +221 -0
  130. package/dist/src/lib/render/component.d.ts +296 -0
  131. package/dist/src/lib/render/component.d.ts.map +1 -0
  132. package/dist/src/lib/render/component.js +514 -0
  133. package/dist/src/lib/render/component.mjs +214 -0
  134. package/dist/src/lib/render/deferred.cjs +175 -0
  135. package/dist/src/lib/render/deferred.d.ts +36 -0
  136. package/dist/src/lib/render/deferred.d.ts.map +1 -0
  137. package/dist/src/lib/render/deferred.js +141 -0
  138. package/dist/src/lib/render/deferred.mjs +158 -0
  139. package/dist/src/lib/render/index.cjs +573 -0
  140. package/dist/src/lib/render/index.d.ts +98 -0
  141. package/dist/src/lib/render/index.d.ts.map +1 -0
  142. package/dist/src/lib/render/index.js +180 -0
  143. package/dist/src/lib/render/index.mjs +590 -0
  144. package/dist/src/lib/render/lazy.cjs +67 -0
  145. package/dist/src/lib/render/lazy.d.ts +49 -0
  146. package/dist/src/lib/render/lazy.d.ts.map +1 -0
  147. package/dist/src/lib/render/lazy.js +105 -0
  148. package/dist/src/lib/render/lazy.mjs +50 -0
  149. package/dist/src/lib/render/suspense.cjs +141 -0
  150. package/dist/src/lib/render/suspense.d.ts +65 -0
  151. package/dist/src/lib/render/suspense.d.ts.map +1 -0
  152. package/dist/src/lib/render/suspense.js +196 -0
  153. package/dist/src/lib/render/suspense.mjs +136 -0
  154. package/dist/src/lib/render/versions.cjs +35 -0
  155. package/dist/src/lib/render/versions.d.ts +2 -0
  156. package/dist/src/lib/render/versions.d.ts.map +1 -0
  157. package/dist/src/lib/render/versions.js +21 -0
  158. package/dist/src/lib/render/versions.mjs +14 -0
  159. package/dist/src/lib/router/data.cjs +228 -0
  160. package/dist/src/lib/router/data.d.ts +142 -0
  161. package/dist/src/lib/router/data.d.ts.map +1 -0
  162. package/dist/src/lib/router/data.js +258 -0
  163. package/dist/src/lib/router/data.mjs +214 -0
  164. package/dist/src/lib/router/index.cjs +921 -0
  165. package/dist/src/lib/router/index.d.ts +274 -0
  166. package/dist/src/lib/router/index.d.ts.map +1 -0
  167. package/dist/src/lib/router/index.js +904 -0
  168. package/dist/src/lib/router/index.mjs +938 -0
  169. package/dist/src/lib/router/scroll.cjs +79 -0
  170. package/dist/src/lib/router/scroll.d.ts +19 -0
  171. package/dist/src/lib/router/scroll.d.ts.map +1 -0
  172. package/dist/src/lib/router/scroll.js +68 -0
  173. package/dist/src/lib/router/scroll.mjs +58 -0
  174. package/dist/src/lib/router/transition.cjs +75 -0
  175. package/dist/src/lib/router/transition.d.ts +81 -0
  176. package/dist/src/lib/router/transition.d.ts.map +1 -0
  177. package/dist/src/lib/router/transition.js +136 -0
  178. package/dist/src/lib/router/transition.mjs +54 -0
  179. package/dist/src/lib/server/hydration.cjs +169 -0
  180. package/dist/src/lib/server/hydration.d.ts +198 -0
  181. package/dist/src/lib/server/hydration.d.ts.map +1 -0
  182. package/dist/src/lib/server/hydration.js +345 -0
  183. package/dist/src/lib/server/hydration.mjs +148 -0
  184. package/dist/src/lib/server/index.cjs +406 -0
  185. package/dist/src/lib/server/index.d.ts +115 -0
  186. package/dist/src/lib/server/index.d.ts.map +1 -0
  187. package/dist/src/lib/server/index.js +164 -0
  188. package/dist/src/lib/server/index.mjs +384 -0
  189. package/dist/src/lib/server/reactive.cjs +197 -0
  190. package/dist/src/lib/server/reactive.d.ts +239 -0
  191. package/dist/src/lib/server/reactive.d.ts.map +1 -0
  192. package/dist/src/lib/server/reactive.js +413 -0
  193. package/dist/src/lib/server/reactive.mjs +176 -0
  194. package/dist/src/lib/storage/cache.cjs +51 -0
  195. package/dist/src/lib/storage/cache.d.ts +18 -0
  196. package/dist/src/lib/storage/cache.d.ts.map +1 -0
  197. package/dist/src/lib/storage/cache.js +42 -0
  198. package/dist/src/lib/storage/cache.mjs +30 -0
  199. package/dist/src/lib/storage/index.cjs +246 -0
  200. package/dist/src/lib/storage/index.d.ts +83 -0
  201. package/dist/src/lib/storage/index.d.ts.map +1 -0
  202. package/dist/src/lib/storage/index.js +179 -0
  203. package/dist/src/lib/storage/index.mjs +231 -0
  204. package/dist/src/lib/storage/persisted.cjs +91 -0
  205. package/dist/src/lib/storage/persisted.d.ts +53 -0
  206. package/dist/src/lib/storage/persisted.d.ts.map +1 -0
  207. package/dist/src/lib/storage/persisted.js +75 -0
  208. package/dist/src/lib/storage/persisted.mjs +70 -0
  209. package/dist/src/lib/theme/color-scheme.cjs +281 -0
  210. package/dist/src/lib/theme/color-scheme.d.ts +61 -0
  211. package/dist/src/lib/theme/color-scheme.d.ts.map +1 -0
  212. package/dist/src/lib/theme/color-scheme.js +120 -0
  213. package/dist/src/lib/theme/color-scheme.mjs +265 -0
  214. package/dist/src/lib/theme/index.cjs +267 -0
  215. package/dist/src/lib/theme/index.d.ts +78 -0
  216. package/dist/src/lib/theme/index.d.ts.map +1 -0
  217. package/dist/src/lib/theme/index.js +135 -0
  218. package/dist/src/lib/theme/index.mjs +251 -0
  219. package/dist/src/lib/theme/provider.cjs +346 -0
  220. package/dist/src/lib/theme/provider.d.ts +34 -0
  221. package/dist/src/lib/theme/provider.d.ts.map +1 -0
  222. package/dist/src/lib/theme/provider.js +60 -0
  223. package/dist/src/lib/theme/provider.mjs +332 -0
  224. package/dist/src/lib/utils/index.cjs +209 -0
  225. package/dist/src/lib/utils/index.d.ts +286 -0
  226. package/dist/src/lib/utils/index.d.ts.map +1 -0
  227. package/dist/src/lib/utils/index.js +434 -0
  228. package/dist/src/lib/utils/index.mjs +188 -0
  229. package/dist/src/routes.cjs +37 -0
  230. package/dist/src/routes.d.ts +22 -0
  231. package/dist/src/routes.d.ts.map +1 -0
  232. package/dist/src/routes.js +20 -0
  233. package/dist/src/routes.mjs +17 -0
  234. package/dist/src/server.cjs +405 -0
  235. package/dist/src/server.d.ts +63 -0
  236. package/dist/src/server.d.ts.map +1 -0
  237. package/dist/src/server.js +62 -0
  238. package/dist/src/server.mjs +382 -0
  239. package/dist/src/utils.cjs +21 -0
  240. package/dist/src/utils.d.ts +10 -0
  241. package/dist/src/utils.d.ts.map +1 -0
  242. package/dist/src/utils.js +9 -0
  243. package/dist/src/utils.mjs +4 -0
  244. package/dist/src/version.generated.cjs +26 -0
  245. package/dist/src/version.generated.d.ts +3 -0
  246. package/dist/src/version.generated.d.ts.map +1 -0
  247. package/dist/src/version.generated.js +3 -0
  248. package/dist/src/version.generated.mjs +5 -0
  249. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  250. package/package.json +164 -0
  251. package/src/index.ts +19 -0
  252. package/types/fluixi.d.ts +5 -0
  253. package/types/vinxi.d.ts +50 -0
@@ -0,0 +1,921 @@
1
+ /*! @fluixi/core v1.0.0-alpha.100 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/lib/router/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ A: () => A,
25
+ ActionForm: () => ActionForm,
26
+ Link: () => Link,
27
+ Outlet: () => Outlet,
28
+ Redirect: () => Redirect,
29
+ Router: () => Router,
30
+ action: () => action,
31
+ cache: () => cache,
32
+ createAsync: () => createAsync,
33
+ createBrowserHistory: () => import_router2.createBrowserHistory,
34
+ createMemoryHistory: () => import_router2.createMemoryHistory,
35
+ lazy: () => lazy,
36
+ matchPath: () => import_router2.matchPath,
37
+ matchRoutes: () => import_router2.matchRoutes,
38
+ prefersReducedMotion: () => prefersReducedMotion,
39
+ preloadRoutes: () => preloadRoutes,
40
+ revalidate: () => revalidate,
41
+ runWithOwner: () => import_signal7.runWithOwner,
42
+ select: () => select,
43
+ supportsViewTransitions: () => supportsViewTransitions,
44
+ useAction: () => useAction,
45
+ useIsRouting: () => useIsRouting,
46
+ useLevelParams: () => useLevelParams,
47
+ useLinkNavigation: () => useLinkNavigation,
48
+ useLocation: () => useLocation,
49
+ useMatch: () => useMatch,
50
+ useNavigate: () => useNavigate,
51
+ useParam: () => useParam,
52
+ useParamSelector: () => useParamSelector,
53
+ useParams: () => useParams,
54
+ useRouteData: () => useRouteData,
55
+ useRouter: () => useRouter,
56
+ useSearchParams: () => useSearchParams,
57
+ useSubmission: () => useSubmission,
58
+ useSubmissions: () => useSubmissions
59
+ });
60
+ module.exports = __toCommonJS(index_exports);
61
+ var import_signal5 = require("@fluixi/reactive/signal");
62
+
63
+ // src/lib/router/transition.ts
64
+ function supportsViewTransitions() {
65
+ return typeof document !== "undefined" && typeof document.startViewTransition === "function";
66
+ }
67
+ function prefersReducedMotion() {
68
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
69
+ return false;
70
+ }
71
+ try {
72
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
73
+ } catch {
74
+ return false;
75
+ }
76
+ }
77
+ function shouldAnimate(mode) {
78
+ return mode !== "none" && supportsViewTransitions() && !prefersReducedMotion();
79
+ }
80
+ function prepareComponents(components) {
81
+ const pending = [];
82
+ for (const component of components) {
83
+ const preload = component?.preload;
84
+ if (typeof preload === "function") {
85
+ try {
86
+ const result = preload();
87
+ if (result && typeof result.then === "function") {
88
+ pending.push(result.catch(() => void 0));
89
+ }
90
+ } catch {
91
+ }
92
+ }
93
+ }
94
+ return pending.length ? Promise.all(pending).then(() => void 0) : null;
95
+ }
96
+ function runTransition(mode, commit) {
97
+ if (!shouldAnimate(mode)) {
98
+ return Promise.resolve(commit()).then(() => void 0);
99
+ }
100
+ const start = document.startViewTransition;
101
+ try {
102
+ const transition = start.call(document, () => commit());
103
+ transition.finished?.catch(() => void 0);
104
+ transition.ready?.catch(() => void 0);
105
+ return transition.updateCallbackDone.catch(() => void 0);
106
+ } catch {
107
+ return Promise.resolve(commit()).then(() => void 0);
108
+ }
109
+ }
110
+
111
+ // src/lib/router/index.ts
112
+ var import_dom3 = require("@fluixi/dom");
113
+ var import_signal6 = require("@fluixi/reactive/signal");
114
+ var import_object = require("@fluixi/utils/object");
115
+ var import_compare = require("@fluixi/utils/compare");
116
+
117
+ // src/lib/router/scroll.ts
118
+ var STORE = "fx:scroll";
119
+ var KEEP = 100;
120
+ function keepScroll(initial) {
121
+ const read2 = () => {
122
+ try {
123
+ return JSON.parse(sessionStorage.getItem(STORE) ?? "{}");
124
+ } catch {
125
+ return {};
126
+ }
127
+ };
128
+ const positions = read2();
129
+ const write = () => {
130
+ const keys = Object.keys(positions);
131
+ for (const key of keys.slice(0, Math.max(0, keys.length - KEEP))) delete positions[key];
132
+ try {
133
+ sessionStorage.setItem(STORE, JSON.stringify(positions));
134
+ } catch {
135
+ }
136
+ };
137
+ let current = initial.key;
138
+ const save = () => {
139
+ if (current === void 0) return;
140
+ delete positions[current];
141
+ positions[current] = window.scrollY;
142
+ write();
143
+ };
144
+ const restoration = history.scrollRestoration;
145
+ history.scrollRestoration = "manual";
146
+ window.addEventListener("pagehide", save);
147
+ const to = (top) => window.scrollTo({ top, left: 0, behavior: "instant" });
148
+ const toHash = (hash) => {
149
+ if (!hash || hash === "#") return false;
150
+ const target = document.getElementById(decodeURIComponent(hash.slice(1)));
151
+ target?.scrollIntoView({ behavior: "instant" });
152
+ return target !== null;
153
+ };
154
+ return {
155
+ leave: save,
156
+ arrive(location, from) {
157
+ current = location.key;
158
+ if (location.action === "pop" || from === void 0) {
159
+ const y = location.key === void 0 ? void 0 : positions[location.key];
160
+ if (y !== void 0) to(y);
161
+ return;
162
+ }
163
+ if (location.action === "replace" && location.pathname === from.pathname) return;
164
+ if (!toHash(location.hash)) to(0);
165
+ },
166
+ dispose() {
167
+ window.removeEventListener("pagehide", save);
168
+ history.scrollRestoration = restoration;
169
+ }
170
+ };
171
+ }
172
+
173
+ // src/lib/router/index.ts
174
+ var import_router = require("@fluixi/router");
175
+
176
+ // src/lib/router/data.ts
177
+ var import_signal2 = require("@fluixi/reactive/signal");
178
+ var import_signal3 = require("@fluixi/reactive/signal");
179
+
180
+ // src/lib/context/context.ts
181
+ var import_dom = require("@fluixi/dom");
182
+ var import_signal = require("@fluixi/reactive/signal");
183
+ function createContext(defaultValue, name) {
184
+ const context = (0, import_signal.createContext)(defaultValue, name);
185
+ const Provider = (props) => (
186
+ // Children stay a getter: the reactive Provider reads them after stamping the value on
187
+ // its owner. Reading `props.children` here would render them, and any <Outlet/> in them,
188
+ // before the context exists.
189
+ context.Provider({
190
+ value: props.value,
191
+ get children() {
192
+ return props.children;
193
+ },
194
+ debug: props.debug
195
+ })
196
+ );
197
+ return {
198
+ id: context.id,
199
+ Provider: (0, import_dom.asProvider)(Provider),
200
+ defaultValue
201
+ };
202
+ }
203
+
204
+ // src/lib/router/data.ts
205
+ var revalidationListeners = /* @__PURE__ */ new Set();
206
+ function onRevalidate(listener) {
207
+ revalidationListeners.add(listener);
208
+ return () => void revalidationListeners.delete(listener);
209
+ }
210
+ var reloadMounted = () => {
211
+ for (const listener of [...revalidationListeners]) listener();
212
+ };
213
+ function cache(fn, name, options = {}) {
214
+ const { ttl = Infinity, staleWhileRevalidate = true } = options;
215
+ return (...args) => {
216
+ const store = options.cache ?? (0, import_signal3.currentResourceCache)();
217
+ const key = name + ":" + JSON.stringify(args);
218
+ const fetchFresh = () => {
219
+ const running = store.inflight.get(key);
220
+ if (running) return running;
221
+ const promise = Promise.resolve(fn(...args)).then(
222
+ (value) => {
223
+ store.set(key, { value, timestamp: Date.now() });
224
+ store.inflight.delete(key);
225
+ return value;
226
+ },
227
+ (error) => {
228
+ store.inflight.delete(key);
229
+ throw error;
230
+ }
231
+ );
232
+ store.inflight.set(key, promise);
233
+ return promise;
234
+ };
235
+ const hit = store.get(key);
236
+ if (hit && (ttl === Infinity || Date.now() - hit.timestamp <= ttl)) return Promise.resolve(hit.value);
237
+ if (hit && staleWhileRevalidate) {
238
+ fetchFresh().then(reloadMounted, () => void 0);
239
+ return Promise.resolve(hit.value);
240
+ }
241
+ return fetchFresh();
242
+ };
243
+ }
244
+ function revalidate(key, store) {
245
+ const names = typeof key === "string" ? [key] : Array.isArray(key) ? key : null;
246
+ drop(names ?? key, store ?? (0, import_signal3.currentResourceCache)());
247
+ if (names && !store) tellOtherTabs(names);
248
+ }
249
+ function drop(what, store) {
250
+ const matches = Array.isArray(what) ? (k) => what.some((n) => k === n || k.startsWith(n + ":")) : what;
251
+ for (const k of [...store.keys()]) if (matches(k)) store.delete(k);
252
+ reloadMounted();
253
+ }
254
+ var TABS_KEY = "fluixi:revalidate";
255
+ function tellOtherTabs(names) {
256
+ try {
257
+ localStorage.setItem(TABS_KEY, JSON.stringify({ names, at: Date.now() + Math.random() }));
258
+ } catch {
259
+ }
260
+ }
261
+ if (typeof window !== "undefined") {
262
+ window.addEventListener("storage", (event) => {
263
+ if (event.key !== TABS_KEY || !event.newValue) return;
264
+ try {
265
+ const names = JSON.parse(event.newValue).names;
266
+ if (Array.isArray(names) && names.every((n) => typeof n === "string")) drop(names, (0, import_signal3.currentResourceCache)());
267
+ } catch {
268
+ }
269
+ });
270
+ }
271
+ globalThis[/* @__PURE__ */ Symbol.for("fluixi.revalidate")] = (names) => revalidate(names);
272
+ function createAsync(fetcher, source) {
273
+ const [data] = (0, import_signal2.createResource)(source || (() => true), fetcher);
274
+ return data;
275
+ }
276
+ var submissionState = /* @__PURE__ */ new Map();
277
+ function getSubmissionSignal(url) {
278
+ if (!submissionState.has(url)) {
279
+ submissionState.set(
280
+ url,
281
+ (0, import_signal2.createSignal)(void 0)
282
+ );
283
+ }
284
+ return submissionState.get(url);
285
+ }
286
+ var submissionsState = /* @__PURE__ */ new Map();
287
+ function getSubmissionsSignal(url) {
288
+ if (!submissionsState.has(url)) submissionsState.set(url, (0, import_signal2.createSignal)([]));
289
+ return submissionsState.get(url);
290
+ }
291
+ function action(fn, name, options = {}) {
292
+ const actionUrl = name || fn.name || "action";
293
+ const submit = async (...args) => {
294
+ const input = args.length > 1 ? args : args[0];
295
+ const [, setSubmission] = getSubmissionSignal(actionUrl);
296
+ const [, setSubmissions] = getSubmissionsSignal(actionUrl);
297
+ let entry;
298
+ const drop2 = () => setSubmissions((list) => list.filter((s) => s !== entry));
299
+ const settle = (next) => {
300
+ setSubmissions((list) => list.map((s) => s === entry ? next : s));
301
+ entry = next;
302
+ };
303
+ const clear = () => {
304
+ setSubmission(void 0);
305
+ drop2();
306
+ };
307
+ const retry = () => {
308
+ drop2();
309
+ return submit(...args);
310
+ };
311
+ entry = {
312
+ input,
313
+ pending: true,
314
+ clear,
315
+ retry
316
+ };
317
+ setSubmission(entry);
318
+ setSubmissions((list) => [...list, entry]);
319
+ try {
320
+ const result = await fn(...args);
321
+ setSubmission({
322
+ input,
323
+ result,
324
+ pending: false,
325
+ clear,
326
+ retry
327
+ });
328
+ drop2();
329
+ const stale = typeof options.invalidates === "function" ? options.invalidates(result) : options.invalidates;
330
+ for (const key of stale ?? []) revalidate(key);
331
+ return result;
332
+ } catch (error) {
333
+ const failed = {
334
+ input,
335
+ error,
336
+ pending: false,
337
+ clear,
338
+ retry
339
+ };
340
+ setSubmission(failed);
341
+ settle(failed);
342
+ throw error;
343
+ }
344
+ };
345
+ submit.url = actionUrl;
346
+ submit.with = (args) => action((...a) => fn(args, ...a), name, options);
347
+ return submit;
348
+ }
349
+ function useSubmission(actionFn) {
350
+ const [submission] = getSubmissionSignal(actionFn.url);
351
+ return submission;
352
+ }
353
+ function useSubmissions(actionFn) {
354
+ const [submissions] = getSubmissionsSignal(actionFn.url);
355
+ return submissions;
356
+ }
357
+ function useAction(actionFn) {
358
+ return actionFn;
359
+ }
360
+ var RouteDataContext = createContext(void 0, "route-data");
361
+ var RouteDataProvider = RouteDataContext.Provider;
362
+
363
+ // src/lib/router/index.ts
364
+ var import_router2 = require("@fluixi/router");
365
+
366
+ // src/lib/render/lazy.ts
367
+ var import_dom2 = require("@fluixi/dom");
368
+ var import_signal4 = require("@fluixi/reactive/signal");
369
+ function fromChunk(value) {
370
+ if (value != null && (typeof value === "object" || typeof value === "function")) {
371
+ try {
372
+ value["$lazy"] = true;
373
+ } catch {
374
+ }
375
+ }
376
+ return value;
377
+ }
378
+ function lazy(loader, options) {
379
+ let resolved;
380
+ let promise;
381
+ let component;
382
+ function load() {
383
+ if (!promise) {
384
+ promise = loader().then((mod) => resolved = mod.default);
385
+ }
386
+ return promise;
387
+ }
388
+ if (options?.preload) load();
389
+ const LazyWrapper = ((props) => {
390
+ if (resolved) {
391
+ const C = resolved;
392
+ return fromChunk((0, import_signal4.untrack)(() => C(props)));
393
+ }
394
+ if (!component) {
395
+ const [resource] = (0, import_signal4.createResource)(() => load(), { transport: false });
396
+ component = resource;
397
+ if (resource.error) throw resource.error;
398
+ }
399
+ return (0, import_signal4.createMemo)(() => {
400
+ const C = component();
401
+ return C ? fromChunk((0, import_dom2.createComponent)(C, props)) : void 0;
402
+ });
403
+ });
404
+ LazyWrapper.preload = () => load().then(() => void 0);
405
+ LazyWrapper.$lazy = true;
406
+ LazyWrapper.loader = loader;
407
+ return LazyWrapper;
408
+ }
409
+
410
+ // src/lib/router/index.ts
411
+ var import_signal7 = require("@fluixi/reactive/signal");
412
+ var RouterContext = (0, import_signal6.createContext)(void 0, "router");
413
+ var OutletContext = (0, import_signal6.createContext)(void 0, "outlet");
414
+ var LevelParamsContext = (0, import_signal6.createContext)(void 0, "route-params");
415
+ var RouteDataContext2 = (0, import_signal6.createContext)(void 0, "route-data");
416
+ function renderLayer(m, depth, base) {
417
+ let data;
418
+ const loader = m.route.data;
419
+ if (typeof loader === "function") {
420
+ let cancelled = false;
421
+ (0, import_signal5.onCleanup)(() => {
422
+ cancelled = true;
423
+ });
424
+ const owner = (0, import_signal5.getOwner)();
425
+ const router = (0, import_signal6.useContext)(RouterContext);
426
+ let watching = false;
427
+ const trackDeps = (deps) => {
428
+ if (watching || cancelled) return;
429
+ watching = true;
430
+ (0, import_signal5.runWithOwner)(owner, () => {
431
+ let first = true;
432
+ (0, import_signal5.createEffect)(() => {
433
+ deps();
434
+ if (first) first = false;
435
+ else (0, import_signal5.untrack)(() => void refetch());
436
+ });
437
+ });
438
+ };
439
+ let readsLocation;
440
+ const [resource, { refetch }] = (0, import_signal5.createResource)(() => {
441
+ const params = (0, import_signal5.untrack)(base.params);
442
+ const location = (0, import_signal5.untrack)(base.location);
443
+ readsLocation = false;
444
+ const result = loader(
445
+ {
446
+ params: () => params,
447
+ location: () => {
448
+ readsLocation = true;
449
+ return location;
450
+ }
451
+ },
452
+ owner,
453
+ () => cancelled,
454
+ trackDeps
455
+ );
456
+ return router ? router.trackLoad(result) : result;
457
+ });
458
+ (0, import_signal5.onCleanup)(
459
+ onRevalidate(() => {
460
+ if ((0, import_signal5.untrack)(() => base.matched()[depth]?.route) !== m.route) return;
461
+ void refetch();
462
+ })
463
+ );
464
+ let loadedFor = (0, import_signal5.untrack)(() => JSON.stringify(base.matched()[depth]?.params ?? {}));
465
+ let searchedFor = (0, import_signal5.untrack)(() => base.location().search);
466
+ (0, import_signal5.createEffect)(() => {
467
+ const now = base.matched()[depth];
468
+ const search = base.location().search;
469
+ if (now?.route !== m.route) return;
470
+ const params = JSON.stringify(now.params ?? {});
471
+ const paramsMoved = params !== loadedFor;
472
+ const searchMoved = readsLocation !== false && search !== searchedFor;
473
+ loadedFor = params;
474
+ searchedFor = search;
475
+ if (paramsMoved || searchMoved) (0, import_signal5.untrack)(() => void refetch());
476
+ });
477
+ data = () => {
478
+ const error = resource.error;
479
+ if (error !== void 0 && error !== null) throw error;
480
+ const r = resource;
481
+ if (r.state === "refreshing") return r.latest;
482
+ return resource();
483
+ };
484
+ Object.defineProperty(data, "loading", { get: () => resource.loading });
485
+ Object.defineProperty(data, "state", { get: () => resource.state });
486
+ }
487
+ const buildPage = () => RouteDataContext2.Provider({
488
+ value: data,
489
+ get children() {
490
+ return LevelParamsContext.Provider({
491
+ value: m.params,
492
+ get children() {
493
+ return OutletContext.Provider({
494
+ value: { depth, ...base },
495
+ get children() {
496
+ return (0, import_dom3.createComponent)(m.component, {});
497
+ }
498
+ });
499
+ }
500
+ });
501
+ }
502
+ });
503
+ if (!data) return { view: buildPage(), ready: () => true };
504
+ const res = data;
505
+ const isLoading = () => {
506
+ const state = res.state;
507
+ return state === void 0 ? res.loading : state === "pending" || state === "unresolved";
508
+ };
509
+ const [ready, setReady] = (0, import_signal5.createSignal)((0, import_signal5.untrack)(() => !isLoading()));
510
+ (0, import_signal5.createEffect)(() => setReady(!isLoading()));
511
+ return { view: (0, import_signal5.createMemo)(() => ready() ? buildPage() : null), ready };
512
+ }
513
+ function renderChild(ctx) {
514
+ const childIdx = ctx.depth + 1;
515
+ const [childComp, setChildComp] = (0, import_signal5.createSignal)(
516
+ (0, import_signal5.untrack)(() => ctx.matched()[childIdx]?.component)
517
+ );
518
+ (0, import_signal5.createEffect)(() => {
519
+ const c = ctx.matched()[childIdx]?.component;
520
+ if ((0, import_signal5.untrack)(childComp) !== c) setChildComp(() => c);
521
+ });
522
+ const owner = (0, import_signal5.getOwner)();
523
+ let shown = null;
524
+ let pending = null;
525
+ const drop2 = (layer) => layer?.dispose();
526
+ (0, import_signal5.onCleanup)(() => {
527
+ drop2(shown);
528
+ drop2(pending);
529
+ shown = pending = null;
530
+ });
531
+ const incoming = (0, import_signal5.createMemo)(() => {
532
+ const component = childComp();
533
+ if (!component) return null;
534
+ const m = (0, import_signal5.untrack)(() => ctx.matched())[childIdx];
535
+ return (0, import_signal5.runWithOwner)(
536
+ owner,
537
+ () => (0, import_signal5.createRoot)((dispose) => ({
538
+ ...renderLayer(m, childIdx, { matched: ctx.matched, params: ctx.params, location: ctx.location }),
539
+ dispose
540
+ }))
541
+ );
542
+ });
543
+ return (0, import_signal5.createMemo)(() => {
544
+ const next = incoming();
545
+ if (!next) {
546
+ drop2(shown);
547
+ drop2(pending);
548
+ shown = pending = null;
549
+ return ctx.notFound ? ctx.notFound() : null;
550
+ }
551
+ if (next === shown) return shown.view;
552
+ if (pending && pending !== next) drop2(pending);
553
+ pending = next;
554
+ if (shown && !next.ready()) return shown.view;
555
+ drop2(shown);
556
+ shown = next;
557
+ pending = null;
558
+ return shown.view;
559
+ });
560
+ }
561
+ function renderNotFound(notFound) {
562
+ if (notFound == null) return buildDefaultNotFound();
563
+ return typeof notFound === "function" ? (0, import_dom3.createComponent)(notFound, {}) : notFound;
564
+ }
565
+ function buildDefaultNotFound() {
566
+ const el = (0, import_dom3.createNativeElement)("div");
567
+ (0, import_dom3.setAttribute)(el, "class", "fx-not-found");
568
+ (0, import_dom3.setAttribute)(el, "role", "main");
569
+ (0, import_dom3.setAttribute)(
570
+ el,
571
+ "style",
572
+ "min-height:60vh;display:grid;place-content:center;gap:.25rem;text-align:center;font-family:system-ui,-apple-system,sans-serif"
573
+ );
574
+ const h1 = (0, import_dom3.createNativeElement)("h1");
575
+ (0, import_dom3.setAttribute)(h1, "style", "margin:0;font-size:2.5rem;font-weight:700");
576
+ (0, import_dom3.insert)(h1, "404");
577
+ const p = (0, import_dom3.createNativeElement)("p");
578
+ (0, import_dom3.setAttribute)(p, "style", "margin:0;opacity:.7");
579
+ (0, import_dom3.insert)(p, "This page could not be found.");
580
+ el.appendChild(h1);
581
+ el.appendChild(p);
582
+ return el;
583
+ }
584
+ var pendingTransitionMode;
585
+ function Router(props) {
586
+ const history2 = props.history ?? (0, import_router.createBrowserHistory)();
587
+ const router = (0, import_router.createRouter)({
588
+ routes: props.routes,
589
+ base: props.base,
590
+ history: history2
591
+ });
592
+ const [state, setState] = (0, import_signal5.createSignal)(router.state());
593
+ const [navigating, setNavigating] = (0, import_signal5.createSignal)(false);
594
+ const [loads, setLoads] = (0, import_signal5.createSignal)(0);
595
+ let navigationId = 0;
596
+ const scroll = history2.window ? keepScroll(router.state().location) : void 0;
597
+ let arriving = scroll ? { id: 0, location: router.state().location, from: void 0 } : null;
598
+ const [arrived, setArrived] = (0, import_signal5.createSignal)(0);
599
+ const takeMode = () => {
600
+ const mode = pendingTransitionMode ?? (props.transition ?? "auto");
601
+ pendingTransitionMode = void 0;
602
+ return mode;
603
+ };
604
+ const unsub = router.subscribe((next) => {
605
+ const id = ++navigationId;
606
+ const mode = takeMode();
607
+ setNavigating(true);
608
+ if (scroll) {
609
+ scroll.leave();
610
+ arriving = { id, location: next.location, from: (0, import_signal5.untrack)(state).location };
611
+ }
612
+ const prepared = prepareComponents(
613
+ (next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
614
+ );
615
+ const commit = () => {
616
+ setState(next);
617
+ const flushed = (0, import_signal5.flush)();
618
+ if (id === navigationId) setNavigating(false);
619
+ if (scroll) setArrived(id);
620
+ return flushed;
621
+ };
622
+ if (!prepared) {
623
+ void runTransition(mode, commit);
624
+ return;
625
+ }
626
+ void prepared.then(() => {
627
+ if (id !== navigationId) return;
628
+ return runTransition(mode, commit);
629
+ });
630
+ });
631
+ (0, import_signal5.onCleanup)(() => {
632
+ unsub();
633
+ scroll?.dispose();
634
+ router.destroy();
635
+ navigationId++;
636
+ });
637
+ const matched = (0, import_signal5.createMemo)(
638
+ () => (state().match?.matched ?? []).filter((m) => m.component)
639
+ );
640
+ const ctx = {
641
+ router,
642
+ location: (0, import_signal5.createMemo)(() => state().location),
643
+ params: (0, import_signal5.createMemo)(() => state().match?.params ?? {}),
644
+ isRouting: () => navigating() || loads() > 0,
645
+ // Counted by the promise, not by an owner: a load a newer navigation superseded still
646
+ // settles and uncounts itself, and a resource seeded from the server never calls it.
647
+ trackLoad(result) {
648
+ if (result && typeof result.finally === "function") {
649
+ setLoads((n) => n + 1);
650
+ void result.finally(() => setLoads((n) => n - 1)).catch(() => {
651
+ });
652
+ }
653
+ return result;
654
+ }
655
+ };
656
+ if (scroll) {
657
+ const nextFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (fn) => setTimeout(fn, 0);
658
+ (0, import_signal5.createEffect)(() => {
659
+ const id = arrived();
660
+ if (ctx.isRouting()) return;
661
+ const next = arriving;
662
+ if (!next || next.id !== id || id !== navigationId) return;
663
+ arriving = null;
664
+ nextFrame(() => {
665
+ if (id === navigationId) scroll.arrive(next.location, next.from);
666
+ });
667
+ });
668
+ }
669
+ const root = {
670
+ depth: -1,
671
+ matched,
672
+ params: ctx.params,
673
+ location: ctx.location,
674
+ // Only the root carries this: renderChild shows it when the URL matched nothing.
675
+ notFound: () => renderNotFound(props.notFound)
676
+ };
677
+ let rootView;
678
+ return RouterContext.Provider({
679
+ value: ctx,
680
+ get children() {
681
+ return rootView ??= renderChild(root);
682
+ }
683
+ });
684
+ }
685
+ function Outlet() {
686
+ const ctx = (0, import_signal6.useContext)(OutletContext);
687
+ if (!ctx) return null;
688
+ return renderChild(ctx);
689
+ }
690
+ function useIsRouting(options = {}) {
691
+ const routing = (0, import_signal6.useContext)(RouterContext)?.isRouting ?? (() => false);
692
+ const delay = options.delay ?? 0;
693
+ if (delay <= 0) return routing;
694
+ const [late, setLate] = (0, import_signal5.createSignal)(false);
695
+ (0, import_signal5.createEffect)(() => {
696
+ if (!routing()) {
697
+ setLate(false);
698
+ return;
699
+ }
700
+ const timer = setTimeout(() => setLate(true), delay);
701
+ (0, import_signal5.onCleanup)(() => clearTimeout(timer));
702
+ });
703
+ return () => routing() && late();
704
+ }
705
+ function Redirect(props) {
706
+ const ctx = (0, import_signal6.useContext)(RouterContext);
707
+ if (ctx && typeof window !== "undefined") {
708
+ let cancelled = false;
709
+ (0, import_signal5.onCleanup)(() => cancelled = true);
710
+ queueMicrotask(() => {
711
+ if (!cancelled) ctx.router.navigate(props.to, { replace: props.replace !== false });
712
+ });
713
+ }
714
+ return null;
715
+ }
716
+ var _ssrRouterStub = {
717
+ router: { navigate: () => {
718
+ } },
719
+ location: () => ({ pathname: "", search: "", hash: "", query: {} }),
720
+ params: () => ({}),
721
+ isRouting: () => false,
722
+ trackLoad: (result) => result
723
+ };
724
+ function useRouter() {
725
+ const ctx = (0, import_signal6.useContext)(RouterContext);
726
+ if (ctx) return ctx;
727
+ if (typeof window === "undefined") return _ssrRouterStub;
728
+ throw new Error("[router] useRouter must be used within <Router>");
729
+ }
730
+ function useParams() {
731
+ const params = useRouter().params;
732
+ return (0, import_signal5.createMemo)(() => params(), {}, {
733
+ equals: (a, b) => JSON.stringify(a) === JSON.stringify(b)
734
+ });
735
+ }
736
+ function useLevelParams() {
737
+ return (0, import_signal6.useContext)(LevelParamsContext) ?? {};
738
+ }
739
+ function useParam(key) {
740
+ const params = useParams();
741
+ return (0, import_signal5.createMemo)(() => params()[key]);
742
+ }
743
+ function useParamSelector(selector, equals) {
744
+ const params = useParams();
745
+ return (0, import_signal5.createMemo)(
746
+ () => selector(params()),
747
+ void 0,
748
+ equals ? { equals } : void 0
749
+ );
750
+ }
751
+ function useMatch(path) {
752
+ const location = useLocation();
753
+ return (0, import_signal5.createMemo)(
754
+ () => (0, import_router.matchPath)(typeof path === "function" ? path() : path, location.pathname)
755
+ );
756
+ }
757
+ function useSearchParams() {
758
+ const location = useLocation();
759
+ const navigate = useNavigate();
760
+ const params = (0, import_signal5.createMemo)(() => location.query);
761
+ const setParams = (next, options) => {
762
+ const current = new URLSearchParams(location.search);
763
+ for (const [k, v] of Object.entries(next)) {
764
+ if (v === null) current.delete(k);
765
+ else current.set(k, v);
766
+ }
767
+ const search = current.toString();
768
+ navigate(location.pathname + (search ? `?${search}` : ""), options);
769
+ };
770
+ return [params, setParams];
771
+ }
772
+ function select(source, key) {
773
+ const equals = (a, b) => (0, import_compare.deepEqual)(a, b);
774
+ if (key !== void 0) {
775
+ return (0, import_signal5.createMemo)(
776
+ () => (0, import_object.get)(source(), key),
777
+ void 0,
778
+ { equals }
779
+ );
780
+ }
781
+ return (0, import_signal5.createMemo)(source, void 0, { equals });
782
+ }
783
+ function useLocation() {
784
+ const { location } = useRouter();
785
+ return new Proxy({}, {
786
+ get: (_t, key) => location()[key],
787
+ has: (_t, key) => key in location(),
788
+ ownKeys: () => Reflect.ownKeys(location()),
789
+ getOwnPropertyDescriptor: (_t, key) => Object.getOwnPropertyDescriptor(location(), key)
790
+ });
791
+ }
792
+ function useLinkNavigation(options = {}) {
793
+ const ctx = (0, import_signal6.useContext)(RouterContext);
794
+ return (event) => {
795
+ if (!ctx || event.defaultPrevented || event.button !== 0) return;
796
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
797
+ const target = event.target;
798
+ const anchor = target?.closest?.("a");
799
+ if (!anchor || !anchor.getAttribute("href")) return;
800
+ if (anchor.target && anchor.target !== "_self") return;
801
+ if (anchor.hasAttribute("download")) return;
802
+ if (/(^|\s)external(\s|$)/.test(anchor.getAttribute("rel") ?? "")) return;
803
+ const url = new URL(anchor.href);
804
+ if (url.protocol !== "http:" && url.protocol !== "https:") return;
805
+ if (url.origin !== window.location.origin) return;
806
+ if (url.hash && url.pathname === window.location.pathname && url.search === window.location.search) return;
807
+ if (options.shouldNavigate && !options.shouldNavigate(url, anchor)) return;
808
+ event.preventDefault();
809
+ pendingTransitionMode = options.transition;
810
+ ctx.router.navigate(url.pathname + url.search + url.hash, { replace: options.replace });
811
+ };
812
+ }
813
+ function useNavigate() {
814
+ const { router } = useRouter();
815
+ return (to, options) => {
816
+ pendingTransitionMode = options?.transition;
817
+ router.navigate(to, options);
818
+ };
819
+ }
820
+ function useRouteData() {
821
+ const acc = (0, import_signal6.useContext)(RouteDataContext2);
822
+ return acc ?? (() => void 0);
823
+ }
824
+ var read = (v) => typeof v === "function" ? v() : v;
825
+ var LINK_OWN_PROPS = /* @__PURE__ */ new Set([
826
+ "href",
827
+ "slot",
828
+ "class",
829
+ "className",
830
+ "active",
831
+ "activeClass",
832
+ "replace",
833
+ "children"
834
+ ]);
835
+ function Link(props) {
836
+ const ctx = (0, import_signal6.useContext)(RouterContext);
837
+ const navigate = () => ctx.router.navigate(read(props.href) ?? "", { replace: read(props.replace) });
838
+ const a = (0, import_dom3.createNativeElement)("a");
839
+ (0, import_dom3.setAttribute)(a, "href", read(props.href) ?? "");
840
+ if (props.slot) (0, import_dom3.setAttribute)(a, "slot", read(props.slot));
841
+ for (const k of Object.keys(props)) {
842
+ if (LINK_OWN_PROPS.has(k)) continue;
843
+ const v = props[k];
844
+ if (typeof v === "function") {
845
+ if (/^on[A-Z]/.test(k)) continue;
846
+ const read2 = v;
847
+ const apply = () => {
848
+ const value = read2();
849
+ if (value == null || value === false) a.removeAttribute?.(k);
850
+ else (0, import_dom3.setAttribute)(a, k, String(value));
851
+ };
852
+ if (typeof a.addEventListener === "function") (0, import_signal5.createEffect)(apply);
853
+ else apply();
854
+ continue;
855
+ }
856
+ if (v != null) (0, import_dom3.setAttribute)(a, k, String(v));
857
+ }
858
+ if (typeof a.addEventListener === "function") {
859
+ a.addEventListener("click", (e) => {
860
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
861
+ if (!ctx) return;
862
+ e.preventDefault();
863
+ navigate();
864
+ });
865
+ } else {
866
+ const base = read(props.className ?? props.class) ?? "";
867
+ if (base) (0, import_dom3.setAttribute)(a, "class", base);
868
+ }
869
+ if (typeof a.addEventListener === "function") {
870
+ (0, import_signal5.createEffect)(() => {
871
+ const href = read(props.href) ?? "";
872
+ a.setAttribute("href", href);
873
+ const base = read(props.className ?? props.class) ?? "";
874
+ const activeClass = read(props.activeClass) ?? "";
875
+ const active = read(props.active) ?? ctx?.location().pathname === href;
876
+ a.className = [base, active ? activeClass : ""].filter(Boolean).join(" ");
877
+ });
878
+ }
879
+ const linkChildren = props.children;
880
+ if (linkChildren != null) (0, import_dom3.insert)(a, linkChildren);
881
+ return a;
882
+ }
883
+ var A = Link;
884
+ function ActionForm(props) {
885
+ const action2 = props.action;
886
+ const cls = props.className ?? props.class;
887
+ const url = action2.url ?? "";
888
+ const form = (0, import_dom3.createNativeElement)("form");
889
+ (0, import_dom3.setAttribute)(form, "method", "post");
890
+ if (url) (0, import_dom3.setAttribute)(form, "action", url);
891
+ if (cls) (0, import_dom3.setAttribute)(form, "class", cls);
892
+ for (const k of Object.keys(props)) {
893
+ if (k === "action" || k === "children" || k === "class" || k === "className") continue;
894
+ const v = props[k];
895
+ if (v != null && typeof v !== "function") (0, import_dom3.setAttribute)(form, k, String(v));
896
+ }
897
+ if (typeof form.addEventListener === "function") {
898
+ form.addEventListener("submit", (e) => {
899
+ e.preventDefault();
900
+ const data = {};
901
+ new FormData(form).forEach((v, k) => {
902
+ data[k] = v;
903
+ });
904
+ Promise.resolve(action2(data)).catch(() => {
905
+ });
906
+ });
907
+ }
908
+ const children = props.children;
909
+ if (children != null) (0, import_dom3.insert)(form, children);
910
+ return form;
911
+ }
912
+ async function preloadRoutes(routes, pathname) {
913
+ const match = (0, import_router.matchRoutes)(routes, pathname);
914
+ if (!match) return;
915
+ const loads = [];
916
+ for (const m of match.matched) {
917
+ const c = m.component;
918
+ if (c && typeof c.preload === "function") loads.push(c.preload());
919
+ }
920
+ await Promise.all(loads);
921
+ }