@kasperrt/smolter 0.0.1 → 0.3.0

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 (246) hide show
  1. package/{src/internal → .generated}/client/index.ts +1 -0
  2. package/.generated/core/environment.ts +43 -0
  3. package/{src/internal → .generated}/core/errors.ts +1 -1
  4. package/{src/internal → .generated}/core/index.ts +2 -0
  5. package/.generated/core/navigation-router.ts +107 -0
  6. package/.generated/core/navigation.ts +147 -0
  7. package/.generated/core/presentation.ts +108 -0
  8. package/.generated/core/resource-types.ts +44 -0
  9. package/.generated/core/resources.ts +444 -0
  10. package/.generated/core/responses.ts +86 -0
  11. package/{src/internal → .generated}/core/router.ts +136 -63
  12. package/.generated/core/serialize.ts +20 -0
  13. package/.generated/core/store.ts +25 -0
  14. package/.generated/core/submission.ts +116 -0
  15. package/{src/internal → .generated}/core/types.ts +18 -1
  16. package/.generated/core/url.ts +29 -0
  17. package/.generated/core/utils.ts +5 -0
  18. package/.generated/preact/await.tsx +41 -0
  19. package/.generated/preact/client.tsx +93 -0
  20. package/.generated/preact/context.ts +59 -0
  21. package/.generated/preact/document.tsx +198 -0
  22. package/{src/internal → .generated}/preact/fetcher.ts +43 -23
  23. package/.generated/preact/form.ts +58 -0
  24. package/{src/internal → .generated}/preact/hooks.ts +25 -28
  25. package/.generated/preact/index.ts +34 -0
  26. package/.generated/preact/lazy-route.ts +100 -0
  27. package/.generated/preact/navigation-state.ts +9 -0
  28. package/.generated/preact/navigation.tsx +147 -0
  29. package/.generated/preact/root-context.ts +21 -0
  30. package/.generated/preact/root-data.ts +45 -0
  31. package/.generated/preact/route-hooks.tsx +170 -0
  32. package/.generated/preact/route-types.ts +76 -0
  33. package/.generated/preact/router.tsx +107 -0
  34. package/{src/internal → .generated}/preact/routes.ts +17 -9
  35. package/.generated/react/context.ts +59 -0
  36. package/.generated/react/data.ts +25 -0
  37. package/{src/internal → .generated}/react/fetcher.ts +13 -11
  38. package/.generated/react/form.ts +58 -0
  39. package/{src/internal → .generated}/react/hooks.ts +9 -14
  40. package/{src/internal/preact → .generated/react}/index.ts +5 -1
  41. package/{src/internal → .generated}/react/link.ts +13 -21
  42. package/.generated/react/resources/components.tsx +404 -0
  43. package/{src/internal → .generated}/react/routes.ts +17 -9
  44. package/.generated/server/application.tsx +185 -0
  45. package/.generated/server/assets.ts +19 -0
  46. package/.generated/server/handler.ts +69 -0
  47. package/.generated/server/http.ts +55 -0
  48. package/{src/internal → .generated}/server/index.ts +4 -17
  49. package/.generated/server/node.ts +4 -0
  50. package/.generated/server/preact.ts +7 -0
  51. package/.generated/vite/application/browser-boundary.ts +42 -0
  52. package/.generated/vite/application/lazy-files.ts +136 -0
  53. package/.generated/vite/application/vite.ts +144 -0
  54. package/{src/internal → .generated}/vite/index.ts +4 -2
  55. package/.generated/vite/preact.ts +24 -0
  56. package/.generated/vite/react.ts +18 -0
  57. package/{src/internal → .generated}/vite/transport.ts +2 -1
  58. package/CHANGELOG.md +54 -0
  59. package/README.md +269 -55
  60. package/dist/client/deserialize.js +10 -0
  61. package/dist/{internal/client → client}/index.d.ts +1 -0
  62. package/dist/client/index.js +46 -0
  63. package/dist/core/environment.d.ts +12 -0
  64. package/dist/core/environment.js +23 -0
  65. package/dist/core/errors.js +7 -0
  66. package/dist/{internal/core → core}/index.d.ts +2 -0
  67. package/dist/core/match.js +33 -0
  68. package/dist/core/navigation-router.d.ts +15 -0
  69. package/dist/core/navigation-router.js +64 -0
  70. package/dist/core/navigation.d.ts +15 -0
  71. package/dist/core/navigation.js +92 -0
  72. package/dist/core/presentation.d.ts +5 -0
  73. package/dist/core/presentation.js +69 -0
  74. package/dist/core/resource-types.d.ts +37 -0
  75. package/dist/core/resources.d.ts +19 -0
  76. package/dist/core/resources.js +345 -0
  77. package/dist/core/responses.d.ts +15 -0
  78. package/dist/core/responses.js +48 -0
  79. package/dist/{internal/core → core}/router.d.ts +1 -1
  80. package/dist/core/router.js +204 -0
  81. package/dist/core/serialize.d.ts +5 -0
  82. package/dist/core/serialize.js +17 -0
  83. package/dist/core/store.d.ts +6 -0
  84. package/dist/core/store.js +21 -0
  85. package/dist/core/submission.d.ts +30 -0
  86. package/dist/core/submission.js +41 -0
  87. package/dist/{internal/core → core}/types.d.ts +16 -1
  88. package/dist/core/url.d.ts +7 -0
  89. package/dist/core/url.js +12 -0
  90. package/dist/core/utils.d.ts +5 -0
  91. package/dist/core/utils.js +5 -0
  92. package/dist/files/index.js +64 -0
  93. package/dist/preact/await.d.ts +7 -0
  94. package/dist/preact/await.js +19 -0
  95. package/dist/preact/client.d.ts +7 -0
  96. package/dist/preact/client.js +67 -0
  97. package/dist/preact/context.d.ts +18 -0
  98. package/dist/preact/context.js +23 -0
  99. package/dist/preact/document.d.ts +15 -0
  100. package/dist/preact/document.js +155 -0
  101. package/dist/{internal/preact → preact}/fetcher.d.ts +9 -5
  102. package/dist/preact/fetcher.js +45 -0
  103. package/dist/{internal/preact → preact}/form.d.ts +5 -6
  104. package/dist/preact/form.js +21 -0
  105. package/dist/{internal/preact → preact}/hooks.d.ts +7 -6
  106. package/dist/preact/hooks.js +25 -0
  107. package/dist/preact/index.d.ts +18 -0
  108. package/dist/preact/index.js +15 -0
  109. package/dist/preact/lazy-route.d.ts +19 -0
  110. package/dist/preact/lazy-route.js +51 -0
  111. package/dist/preact/navigation-state.d.ts +2 -0
  112. package/dist/preact/navigation-state.js +9 -0
  113. package/dist/preact/navigation.d.ts +28 -0
  114. package/dist/preact/navigation.js +60 -0
  115. package/dist/preact/root-context.d.ts +13 -0
  116. package/dist/preact/root-context.js +9 -0
  117. package/dist/preact/root-data.d.ts +8 -0
  118. package/dist/preact/root-data.js +28 -0
  119. package/dist/preact/route-hooks.d.ts +32 -0
  120. package/dist/preact/route-hooks.js +94 -0
  121. package/dist/preact/route-types.d.ts +54 -0
  122. package/dist/preact/router.d.ts +16 -0
  123. package/dist/preact/router.js +63 -0
  124. package/dist/{internal/preact → preact}/routes.d.ts +1 -1
  125. package/dist/preact/routes.js +12 -0
  126. package/dist/{internal/preact → preact}/runtime.js +1 -1
  127. package/dist/react/context.d.ts +18 -0
  128. package/dist/react/context.js +23 -0
  129. package/dist/react/data.d.ts +5 -0
  130. package/dist/react/data.js +3 -0
  131. package/dist/{internal/react → react}/fetcher.d.ts +2 -2
  132. package/dist/react/fetcher.js +34 -0
  133. package/dist/{internal/react → react}/form.d.ts +5 -6
  134. package/dist/react/form.js +21 -0
  135. package/dist/react/hooks.js +25 -0
  136. package/dist/{internal/react → react}/index.d.ts +1 -1
  137. package/dist/react/index.js +10 -0
  138. package/dist/{internal/react → react}/link.d.ts +2 -2
  139. package/dist/react/link.js +27 -0
  140. package/dist/react/resources/components.d.ts +64 -0
  141. package/dist/react/resources/components.js +239 -0
  142. package/dist/{internal/react → react}/routes.d.ts +1 -1
  143. package/dist/react/routes.js +12 -0
  144. package/dist/react/runtime.js +1 -0
  145. package/dist/server/application.d.ts +4 -0
  146. package/dist/server/application.js +119 -0
  147. package/dist/server/assets.d.ts +5 -0
  148. package/dist/server/assets.js +7 -0
  149. package/dist/server/handler.d.ts +19 -0
  150. package/dist/server/handler.js +22 -0
  151. package/dist/server/http.d.ts +4 -0
  152. package/dist/server/http.js +27 -0
  153. package/dist/{internal/server → server}/index.d.ts +2 -3
  154. package/dist/server/index.js +76 -0
  155. package/dist/server/node.d.ts +3 -0
  156. package/dist/server/node.js +3 -0
  157. package/dist/server/preact.d.ts +3 -0
  158. package/dist/server/preact.js +4 -0
  159. package/dist/vite/application/browser-boundary.d.ts +3 -0
  160. package/dist/vite/application/browser-boundary.js +35 -0
  161. package/dist/vite/application/lazy-files.d.ts +2 -0
  162. package/dist/vite/application/lazy-files.js +87 -0
  163. package/dist/vite/application/vite.d.ts +9 -0
  164. package/dist/vite/application/vite.js +101 -0
  165. package/dist/{internal/vite → vite}/index.d.ts +2 -1
  166. package/dist/vite/index.js +104 -0
  167. package/dist/vite/preact.d.ts +11 -0
  168. package/dist/vite/preact.js +15 -0
  169. package/dist/vite/react.d.ts +9 -0
  170. package/dist/vite/react.js +14 -0
  171. package/dist/{internal/vite → vite}/transport.d.ts +1 -1
  172. package/dist/vite/transport.js +35 -0
  173. package/jsr.json +28 -11
  174. package/package.json +119 -38
  175. package/dist/client.d.ts +0 -2
  176. package/dist/client.js +0 -2
  177. package/dist/core.d.ts +0 -2
  178. package/dist/core.js +0 -2
  179. package/dist/files.d.ts +0 -2
  180. package/dist/files.js +0 -2
  181. package/dist/internal/client/deserialize.js +0 -11
  182. package/dist/internal/client/index.js +0 -44
  183. package/dist/internal/core/errors.js +0 -6
  184. package/dist/internal/core/index.js +0 -6
  185. package/dist/internal/core/match.js +0 -27
  186. package/dist/internal/core/router.js +0 -189
  187. package/dist/internal/core/types.js +0 -5
  188. package/dist/internal/core/url.d.ts +0 -2
  189. package/dist/internal/core/url.js +0 -6
  190. package/dist/internal/files/index.js +0 -77
  191. package/dist/internal/preact/context.d.ts +0 -18
  192. package/dist/internal/preact/context.js +0 -20
  193. package/dist/internal/preact/fetcher.js +0 -28
  194. package/dist/internal/preact/form.js +0 -41
  195. package/dist/internal/preact/hooks.js +0 -35
  196. package/dist/internal/preact/index.d.ts +0 -9
  197. package/dist/internal/preact/index.js +0 -7
  198. package/dist/internal/preact/link.d.ts +0 -12
  199. package/dist/internal/preact/link.js +0 -28
  200. package/dist/internal/preact/routes.js +0 -22
  201. package/dist/internal/react/context.d.ts +0 -18
  202. package/dist/internal/react/context.js +0 -20
  203. package/dist/internal/react/fetcher.js +0 -28
  204. package/dist/internal/react/form.js +0 -41
  205. package/dist/internal/react/hooks.js +0 -35
  206. package/dist/internal/react/index.js +0 -7
  207. package/dist/internal/react/link.js +0 -28
  208. package/dist/internal/react/routes.js +0 -22
  209. package/dist/internal/react/runtime.js +0 -2
  210. package/dist/internal/server/index.js +0 -81
  211. package/dist/internal/vite/index.js +0 -132
  212. package/dist/internal/vite/transport.js +0 -42
  213. package/dist/preact.d.ts +0 -2
  214. package/dist/preact.js +0 -2
  215. package/dist/react.d.ts +0 -2
  216. package/dist/react.js +0 -2
  217. package/dist/server.d.ts +0 -2
  218. package/dist/server.js +0 -2
  219. package/dist/vite.d.ts +0 -2
  220. package/dist/vite.js +0 -2
  221. package/src/client.ts +0 -2
  222. package/src/core.ts +0 -2
  223. package/src/files.ts +0 -2
  224. package/src/internal/core/url.ts +0 -6
  225. package/src/internal/preact/context.ts +0 -46
  226. package/src/internal/preact/form.ts +0 -79
  227. package/src/internal/preact/link.ts +0 -46
  228. package/src/internal/react/context.ts +0 -46
  229. package/src/internal/react/form.ts +0 -79
  230. package/src/internal/react/index.ts +0 -13
  231. package/src/preact.ts +0 -2
  232. package/src/react.ts +0 -2
  233. package/src/server.ts +0 -2
  234. package/src/vite.ts +0 -2
  235. /package/{src/internal → .generated}/client/deserialize.ts +0 -0
  236. /package/{src/internal → .generated}/core/match.ts +0 -0
  237. /package/{src/internal → .generated}/files/index.ts +0 -0
  238. /package/{src/internal → .generated}/preact/runtime.ts +0 -0
  239. /package/{src/internal → .generated}/react/runtime.ts +0 -0
  240. /package/dist/{internal/client → client}/deserialize.d.ts +0 -0
  241. /package/dist/{internal/core → core}/errors.d.ts +0 -0
  242. /package/dist/{internal/core → core}/match.d.ts +0 -0
  243. /package/dist/{internal/files → files}/index.d.ts +0 -0
  244. /package/dist/{internal/preact → preact}/runtime.d.ts +0 -0
  245. /package/dist/{internal/react → react}/hooks.d.ts +0 -0
  246. /package/dist/{internal/react → react}/runtime.d.ts +0 -0
@@ -0,0 +1,33 @@
1
+ //#region .generated/core/match.ts
2
+ /** Associate a URL pattern with a module while retaining its inferred handler types. */
3
+ function defineRoute(path, module) {
4
+ return {
5
+ ...module,
6
+ path
7
+ };
8
+ }
9
+ /** Static segments, :params and a terminal * wildcard; first match wins. */
10
+ function matchRoutes(routes, pathname) {
11
+ const segments = pathname.replace(/\/$/, "").split("/");
12
+ for (const route of routes) {
13
+ const parts = route.path.replace(/\/$/, "").split("/");
14
+ const params = {};
15
+ if ((parts.length === segments.length || parts.at(-1) === "*") && parts.every((part, index) => {
16
+ const value = segments[index];
17
+ if (part === "*") {
18
+ params["*"] = segments.slice(index).join("/");
19
+ return true;
20
+ }
21
+ if (part[0] === ":" && value) {
22
+ params[part.slice(1)] = new URLSearchParams(`=${value.replace(/[+&]/g, encodeURIComponent)}`).get("");
23
+ return true;
24
+ }
25
+ return part === value;
26
+ })) return {
27
+ route,
28
+ params
29
+ };
30
+ }
31
+ }
32
+ //#endregion
33
+ export { defineRoute, matchRoutes };
@@ -0,0 +1,15 @@
1
+ import type { Route, Router, RouterOptions } from "./types.ts";
2
+ /** Navigation and subscriptions without the loader/action engine. */
3
+ export type NavigationRouter = Pick<Router, "routes" | "getSnapshot" | "subscribe" | "start" | "navigate" | "dispose">;
4
+ /** Route modules for navigation only; data handlers require createDataRouter. */
5
+ export type NavigationRoute = Route & {
6
+ loader?: never;
7
+ action?: never;
8
+ clientLoader?: never;
9
+ clientAction?: never;
10
+ shouldRevalidate?: never;
11
+ };
12
+ /** Initial URL and optional browser history for navigation-only routing. */
13
+ export type NavigationRouterOptions = Pick<RouterOptions, "url" | "browser">;
14
+ /** Create a route matcher and history store without data requests or fetchers. */
15
+ export declare function createRouter(routes: readonly NavigationRoute[], options?: NavigationRouterOptions): NavigationRouter;
@@ -0,0 +1,64 @@
1
+ import { matchRoutes } from "./match.js";
2
+ import { internalURL } from "./url.js";
3
+ //#region .generated/core/navigation-router.ts
4
+ /** Create a route matcher and history store without data requests or fetchers. */
5
+ function createRouter(routes, options = {}) {
6
+ const browser = options.browser && typeof window !== "undefined";
7
+ const listeners = /* @__PURE__ */ new Set();
8
+ let users = 0;
9
+ const resolve = (url) => {
10
+ const match = matchRoutes(routes, url.pathname);
11
+ return {
12
+ url: url.href,
13
+ path: match?.route.path,
14
+ params: match?.params ?? {},
15
+ state: "idle",
16
+ loaded: true
17
+ };
18
+ };
19
+ let snapshot = resolve(new URL(options.url ?? (browser ? location.href : "/"), "http://localhost"));
20
+ const update = (url) => {
21
+ if (url.href === snapshot.url) return;
22
+ snapshot = resolve(url);
23
+ for (const listener of listeners) listener();
24
+ };
25
+ const pop = () => update(new URL(location.href));
26
+ return {
27
+ routes,
28
+ getSnapshot: () => snapshot,
29
+ subscribe(listener) {
30
+ listeners.add(listener);
31
+ return () => {
32
+ listeners.delete(listener);
33
+ };
34
+ },
35
+ start() {
36
+ if (!users++ && browser) {
37
+ addEventListener("popstate", pop);
38
+ addEventListener("hashchange", pop);
39
+ pop();
40
+ }
41
+ return () => {
42
+ if (!--users && browser) {
43
+ removeEventListener("popstate", pop);
44
+ removeEventListener("hashchange", pop);
45
+ }
46
+ };
47
+ },
48
+ async navigate(href, operation) {
49
+ const url = internalURL(snapshot.url, href);
50
+ if (!url) return;
51
+ if (browser) history[operation?.replace ? "replaceState" : "pushState"](operation?.state ?? null, "", url);
52
+ update(url);
53
+ },
54
+ dispose() {
55
+ listeners.clear();
56
+ if (browser) {
57
+ removeEventListener("popstate", pop);
58
+ removeEventListener("hashchange", pop);
59
+ }
60
+ }
61
+ };
62
+ }
63
+ //#endregion
64
+ export { createRouter };
@@ -0,0 +1,15 @@
1
+ import type { Router } from "./types.ts";
2
+ export type NavigationType = "POP" | "PUSH" | "REPLACE";
3
+ export interface NavigationSnapshot {
4
+ type: NavigationType;
5
+ state: unknown;
6
+ key: string;
7
+ preventScrollReset: boolean;
8
+ }
9
+ export declare function scrollPositions(router: Router): Map<string, [number, number]>;
10
+ export declare function navigationStore(router: Router): {
11
+ getSnapshot: () => NavigationSnapshot;
12
+ subscribe(listener: () => void): () => void;
13
+ update(next: NavigationSnapshot): void;
14
+ };
15
+ export declare function connectNavigation(router: Router): void;
@@ -0,0 +1,92 @@
1
+ import { navigationClick } from "./url.js";
2
+ import { handoffDocument, leaveDocument, resolveApplicationURL } from "./environment.js";
3
+ import { createStore } from "./store.js";
4
+ //#region .generated/core/navigation.ts
5
+ var scrollHistory = /* @__PURE__ */ new WeakMap();
6
+ function scrollPositions(router) {
7
+ let positions = scrollHistory.get(router);
8
+ if (!positions) {
9
+ positions = /* @__PURE__ */ new Map();
10
+ scrollHistory.set(router, positions);
11
+ }
12
+ return positions;
13
+ }
14
+ var stores = /* @__PURE__ */ new WeakMap();
15
+ function createNavigationStore() {
16
+ return createStore({
17
+ type: "POP",
18
+ state: typeof history === "undefined" ? null : history.state?.state,
19
+ key: typeof history === "undefined" ? "initial" : history.state?.key ?? "initial",
20
+ preventScrollReset: false
21
+ });
22
+ }
23
+ function navigationStore(router) {
24
+ let store = stores.get(router);
25
+ if (!store) {
26
+ store = createNavigationStore();
27
+ stores.set(router, store);
28
+ }
29
+ return store;
30
+ }
31
+ function connectNavigation(router) {
32
+ const store = navigationStore(router);
33
+ const navigate = router.navigate;
34
+ let sequence = 0;
35
+ let pending;
36
+ const committed = () => {
37
+ if (!pending || router.getSnapshot().state !== "idle") return;
38
+ const next = pending;
39
+ pending = void 0;
40
+ if (next.type !== "POP") history.replaceState(next, "", location.href);
41
+ store.update(next);
42
+ };
43
+ const unsubscribe = router.subscribe(committed);
44
+ const rememberScroll = () => {
45
+ scrollPositions(router).set(store.getSnapshot().key, [window.scrollX, window.scrollY]);
46
+ };
47
+ router.navigate = async (href, options = {}) => {
48
+ const destination = resolveApplicationURL(new URL(href, router.getSnapshot().url));
49
+ if (destination.origin !== location.origin) {
50
+ leaveDocument(destination);
51
+ return;
52
+ }
53
+ rememberScroll();
54
+ const current = ++sequence;
55
+ pending = {
56
+ type: options.replace ? "REPLACE" : "PUSH",
57
+ state: options.state ?? null,
58
+ key: `${Date.now().toString(36)}-${current}`,
59
+ preventScrollReset: options.preventScrollReset ?? false
60
+ };
61
+ await navigate(href, options);
62
+ committed();
63
+ };
64
+ const pop = () => {
65
+ rememberScroll();
66
+ pending = {
67
+ ...history.state,
68
+ type: "POP",
69
+ key: history.state?.key ?? "initial",
70
+ preventScrollReset: false
71
+ };
72
+ committed();
73
+ };
74
+ const handoff = (event) => {
75
+ const anchor = event.target instanceof Element ? event.target.closest("a[href]") : null;
76
+ if (!(anchor instanceof HTMLAnchorElement) || !navigationClick(event, anchor)) return;
77
+ const target = resolveApplicationURL(new URL(anchor.href));
78
+ handoffDocument(event, target);
79
+ };
80
+ if (typeof document !== "undefined") document.addEventListener("click", handoff);
81
+ window.addEventListener("popstate", pop);
82
+ const dispose = router.dispose;
83
+ router.dispose = () => {
84
+ pending = void 0;
85
+ unsubscribe();
86
+ window.removeEventListener("popstate", pop);
87
+ if (typeof document !== "undefined") document.removeEventListener("click", handoff);
88
+ dispose();
89
+ };
90
+ }
91
+ //#endregion
92
+ export { connectNavigation, navigationStore, scrollPositions };
@@ -0,0 +1,5 @@
1
+ import type { Router } from "./types.ts";
2
+ type CommitView = (update: () => void) => void;
3
+ export declare function pendingLocation(router: Router): URL | undefined;
4
+ export declare function retainRoute(router: Router, commitView: CommitView): void;
5
+ export {};
@@ -0,0 +1,69 @@
1
+ //#region .generated/core/presentation.ts
2
+ var pending = /* @__PURE__ */ new WeakMap();
3
+ function pendingLocation(router) {
4
+ const snapshot = pending.get(router)?.();
5
+ return snapshot?.state !== "idle" && snapshot?.url ? new URL(snapshot.url) : void 0;
6
+ }
7
+ function retainRoute(router, commitView) {
8
+ const read = router.getSnapshot;
9
+ pending.set(router, read);
10
+ let viewTransition;
11
+ const navigate = router.navigate;
12
+ router.navigate = (href, options = {}) => {
13
+ viewTransition = options.viewTransition;
14
+ return navigate(href, options);
15
+ };
16
+ let visible = read();
17
+ let revision = 0;
18
+ const listeners = /* @__PURE__ */ new Set();
19
+ const publish = () => {
20
+ for (const listener of listeners) listener();
21
+ };
22
+ const unsubscribe = router.subscribe(() => {
23
+ const next = read();
24
+ const current = ++revision;
25
+ if (next.state !== "idle" && visible.loaded) {
26
+ visible = {
27
+ ...visible,
28
+ state: next.state
29
+ };
30
+ publish();
31
+ return;
32
+ }
33
+ const commit = () => {
34
+ if (current !== revision) return;
35
+ commitView(() => {
36
+ visible = next;
37
+ publish();
38
+ });
39
+ };
40
+ const previousURL = new URL(visible.url);
41
+ const nextURL = new URL(next.url);
42
+ const changed = previousURL.pathname + previousURL.search !== nextURL.pathname + nextURL.search;
43
+ const component = (path) => {
44
+ const route = router.routes.find((item) => item.path === path);
45
+ return route?.resolveComponent?.() ?? route?.default;
46
+ };
47
+ const previousComponent = component(visible.path);
48
+ const sharedView = previousComponent && previousComponent === component(next.path);
49
+ if (changed && visible.loaded && viewTransition !== false && !sharedView && previousURL.pathname !== nextURL.pathname && typeof document !== "undefined" && typeof document.startViewTransition === "function" && !matchMedia("(prefers-reduced-motion: reduce)").matches) {
50
+ document.startViewTransition(commit).ready.catch(() => {});
51
+ return;
52
+ }
53
+ commit();
54
+ });
55
+ router.getSnapshot = () => visible;
56
+ router.subscribe = (listener) => {
57
+ listeners.add(listener);
58
+ return () => listeners.delete(listener);
59
+ };
60
+ const dispose = router.dispose;
61
+ router.dispose = () => {
62
+ unsubscribe();
63
+ pending.delete(router);
64
+ listeners.clear();
65
+ dispose();
66
+ };
67
+ }
68
+ //#endregion
69
+ export { pendingLocation, retainRoute };
@@ -0,0 +1,37 @@
1
+ export type Params = Readonly<Record<string, string>>;
2
+ export interface LoaderFunctionArgs {
3
+ params: Params;
4
+ signal: AbortSignal;
5
+ }
6
+ export interface ActionFunctionArgs<Input = unknown> {
7
+ input: Input;
8
+ params: Params;
9
+ signal: AbortSignal;
10
+ }
11
+ export interface DataResult<Data> {
12
+ data: Data | null;
13
+ error: string;
14
+ unexpected?: true;
15
+ }
16
+ export interface ResourceModule {
17
+ action?: (args: ActionFunctionArgs) => Promise<DataResult<unknown>>;
18
+ loader?: (args: LoaderFunctionArgs) => Promise<DataResult<unknown>>;
19
+ shouldRevalidate?: (args: ShouldRevalidateFunctionArgs) => boolean;
20
+ }
21
+ export interface ShouldRevalidateFunctionArgs {
22
+ actionResult: DataResult<unknown>;
23
+ defaultShouldRevalidate: boolean;
24
+ params: Params;
25
+ }
26
+ export type NavigationState = "idle" | "loading" | "submitting";
27
+ export interface RouteState {
28
+ actionData: unknown;
29
+ actionError: string;
30
+ actionState: "idle" | "submitting";
31
+ loaderData: unknown;
32
+ loaderError: string;
33
+ loaderInitialized: boolean;
34
+ loaderState: "idle" | "loading";
35
+ navigationState: NavigationState;
36
+ unexpectedError: boolean;
37
+ }
@@ -0,0 +1,19 @@
1
+ import type { DataResult, Params, ResourceModule, RouteState } from "./resource-types.ts";
2
+ export declare class ResourceRouter {
3
+ #private;
4
+ constructor(routes: ReadonlyMap<string, ResourceModule>);
5
+ dispose(): void;
6
+ getRoute(routeId: string): ResourceModule | null;
7
+ getSnapshot(routeId: string, params: Params): RouteState;
8
+ hydrateRoute<Data>(routeId: string, data: Data, params?: Params): void;
9
+ persist(routeId: string, params?: Params): void;
10
+ disposeRoute(routeId: string, params?: Params): void;
11
+ load<Data>(routeId: string, params?: Params, force?: boolean): Promise<DataResult<Data>>;
12
+ subscribe(routeId: string, params: Params, listener: () => void): () => void;
13
+ submit<Data>(routeId: string, input: unknown, params?: Params): Promise<DataResult<Data>>;
14
+ fetchLoader<Data>(routeId: string, params: Params, signal: AbortSignal): Promise<DataResult<Data>>;
15
+ fetchAction<Data>(routeId: string, input: unknown, params: Params, signal: AbortSignal): Promise<DataResult<Data>>;
16
+ retry(routeId: string, params: Params): Promise<DataResult<unknown>>;
17
+ reportUnexpected(routeId: string, params: Params): void;
18
+ }
19
+ export declare function createResourceRouter(routes: ReadonlyMap<string, ResourceModule>): ResourceRouter;