@ossido-labs/ossido-router 0.1.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.
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/esm/components/CriticalCss.d.ts +13 -0
- package/dist/esm/components/CriticalCss.js +22 -0
- package/dist/esm/components/CriticalCss.js.map +1 -0
- package/dist/esm/components/Link.d.ts +30 -0
- package/dist/esm/components/Link.js +47 -0
- package/dist/esm/components/Link.js.map +1 -0
- package/dist/esm/components/Matches.d.ts +7 -0
- package/dist/esm/components/Matches.js +22 -0
- package/dist/esm/components/Matches.js.map +1 -0
- package/dist/esm/components/NotFound.d.ts +5 -0
- package/dist/esm/components/NotFound.js +22 -0
- package/dist/esm/components/NotFound.js.map +1 -0
- package/dist/esm/components/NotFoundDefaultContent.d.ts +7 -0
- package/dist/esm/components/NotFoundDefaultContent.js +29 -0
- package/dist/esm/components/NotFoundDefaultContent.js.map +1 -0
- package/dist/esm/components/OssidoErrorBoundary.d.ts +39 -0
- package/dist/esm/components/OssidoErrorBoundary.js +48 -0
- package/dist/esm/components/OssidoErrorBoundary.js.map +1 -0
- package/dist/esm/components/Redirect.d.ts +11 -0
- package/dist/esm/components/Redirect.js +21 -0
- package/dist/esm/components/Redirect.js.map +1 -0
- package/dist/esm/components/RouteDataLoader.d.ts +21 -0
- package/dist/esm/components/RouteDataLoader.js +27 -0
- package/dist/esm/components/RouteDataLoader.js.map +1 -0
- package/dist/esm/components/RouteMatch.d.ts +15 -0
- package/dist/esm/components/RouteMatch.js +81 -0
- package/dist/esm/components/RouteMatch.js.map +1 -0
- package/dist/esm/components/RouterContext.d.ts +56 -0
- package/dist/esm/components/RouterContext.js +32 -0
- package/dist/esm/components/RouterContext.js.map +1 -0
- package/dist/esm/components/RouterContextProvider.d.ts +10 -0
- package/dist/esm/components/RouterContextProvider.js +122 -0
- package/dist/esm/components/RouterContextProvider.js.map +1 -0
- package/dist/esm/components/RouterProvider.d.ts +15 -0
- package/dist/esm/components/RouterProvider.js +28 -0
- package/dist/esm/components/RouterProvider.js.map +1 -0
- package/dist/esm/data/resourceCache.d.ts +75 -0
- package/dist/esm/data/resourceCache.js +148 -0
- package/dist/esm/data/resourceCache.js.map +1 -0
- package/dist/esm/hooks/useRoute.d.ts +14 -0
- package/dist/esm/hooks/useRoute.js +22 -0
- package/dist/esm/hooks/useRoute.js.map +1 -0
- package/dist/esm/hooks/useRouter.d.ts +47 -0
- package/dist/esm/hooks/useRouter.js +49 -0
- package/dist/esm/hooks/useRouter.js.map +1 -0
- package/dist/esm/hot.d.ts +9 -0
- package/dist/esm/hot.js +32 -0
- package/dist/esm/hot.js.map +1 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/route.d.ts +70 -0
- package/dist/esm/route.js +50 -0
- package/dist/esm/route.js.map +1 -0
- package/dist/esm/router.d.ts +27 -0
- package/dist/esm/router.js +52 -0
- package/dist/esm/router.js.map +1 -0
- package/dist/esm/types.d.ts +63 -0
- package/dist/esm/utils/from-url-to-parsed-location.d.ts +2 -0
- package/dist/esm/utils/from-url-to-parsed-location.js +15 -0
- package/dist/esm/utils/from-url-to-parsed-location.js.map +1 -0
- package/dist/esm/utils/match-route.d.ts +16 -0
- package/dist/esm/utils/match-route.js +72 -0
- package/dist/esm/utils/match-route.js.map +1 -0
- package/dist/esm/utils/preload-route-chain.d.ts +16 -0
- package/dist/esm/utils/preload-route-chain.js +31 -0
- package/dist/esm/utils/preload-route-chain.js.map +1 -0
- package/dist/esm/utils/view-transition.d.ts +18 -0
- package/dist/esm/utils/view-transition.js +35 -0
- package/dist/esm/utils/view-transition.js.map +1 -0
- package/dist/esm/utils.d.ts +6 -0
- package/dist/esm/utils.js +20 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preload-route-chain.js","names":[],"sources":["../../../src/utils/preload-route-chain.ts"],"sourcesContent":["import type { Route } from '../route';\nimport type { RouterInstanceType } from '../router';\n\nimport { matchRoute } from './match-route';\n\n/**\n * Preload the code of the route matching `pathname` and of every layout that\n * wraps it, so a subsequent render commits the components eagerly instead of\n * suspending on their `React.lazy` chunk.\n *\n * Used ahead of the *initial* render on both sides — the server before\n * streaming (a suspending route would push the page content into an\n * out-of-order late chunk, painting an empty shell first) and the client\n * before hydration (so the first client render matches that inline HTML).\n * Client-side navigation has its own preload in `RouterContext`.\n *\n * A failed chunk load resolves anyway: the render then falls back to the lazy\n * component, which surfaces the load error through the route's error boundary.\n */\nexport async function preloadRouteChain(\n router: RouterInstanceType,\n pathname?: string,\n): Promise<void> {\n const matched = matchRoute(router.routesById, pathname);\n if (!matched) return;\n\n const pending: Array<Promise<void>> = [];\n for (\n let node: Route | undefined = matched;\n node;\n node = node.isRoot ? undefined : node.options.getParentRoute?.()\n ) {\n const preload = node.component.preload;\n if (preload) pending.push(preload().catch(() => undefined));\n }\n\n await Promise.all(pending);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,eAAsB,kBACpB,QACA,UACe;CACf,MAAM,UAAU,WAAW,OAAO,YAAY,QAAQ;CACtD,IAAI,CAAC,SAAS;CAEd,MAAM,UAAgC,CAAC;CACvC,KACE,IAAI,OAA0B,SAC9B,MACA,OAAO,KAAK,SAAS,SAAY,KAAK,QAAQ,iBAAiB,GAC/D;EACA,MAAM,UAAU,KAAK,UAAU;EAC/B,IAAI,SAAS,QAAQ,KAAK,QAAQ,CAAC,CAAC,YAAY,MAAS,CAAC;CAC5D;CAEA,MAAM,QAAQ,IAAI,OAAO;AAC3B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the app opted into view transitions at build time. Baked in via the
|
|
3
|
+
* vite `define` (`__OSSIDO_VIEW_TRANSITIONS__`); `false` when the define is
|
|
4
|
+
* absent (tests / SSR), keeping transitions opt-in.
|
|
5
|
+
*/
|
|
6
|
+
export declare const VIEW_TRANSITIONS_ENABLED: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Run a router `commit` inside `document.startViewTransition` when `enabled`, the
|
|
9
|
+
* API is supported, and the user hasn't requested reduced motion — otherwise run
|
|
10
|
+
* it directly.
|
|
11
|
+
*
|
|
12
|
+
* The commit's React state updates are wrapped in `flushSync` so the DOM shows
|
|
13
|
+
* the new page before the API captures its "after" snapshot; React state updates
|
|
14
|
+
* are async and wouldn't be applied in time otherwise. This is safe because the
|
|
15
|
+
* router prefetches the destination's data + code before committing, so the new
|
|
16
|
+
* route renders synchronously (no Suspense fallback flash).
|
|
17
|
+
*/
|
|
18
|
+
export declare function runCommit(commit: () => void, enabled: boolean): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { flushSync } from "react-dom";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/view-transition.ts
|
|
4
|
+
/**
|
|
5
|
+
* Whether the app opted into view transitions at build time. Baked in via the
|
|
6
|
+
* vite `define` (`__OSSIDO_VIEW_TRANSITIONS__`); `false` when the define is
|
|
7
|
+
* absent (tests / SSR), keeping transitions opt-in.
|
|
8
|
+
*/
|
|
9
|
+
const VIEW_TRANSITIONS_ENABLED = typeof __OSSIDO_VIEW_TRANSITIONS__ !== "undefined" && __OSSIDO_VIEW_TRANSITIONS__;
|
|
10
|
+
/**
|
|
11
|
+
* Run a router `commit` inside `document.startViewTransition` when `enabled`, the
|
|
12
|
+
* API is supported, and the user hasn't requested reduced motion — otherwise run
|
|
13
|
+
* it directly.
|
|
14
|
+
*
|
|
15
|
+
* The commit's React state updates are wrapped in `flushSync` so the DOM shows
|
|
16
|
+
* the new page before the API captures its "after" snapshot; React state updates
|
|
17
|
+
* are async and wouldn't be applied in time otherwise. This is safe because the
|
|
18
|
+
* router prefetches the destination's data + code before committing, so the new
|
|
19
|
+
* route renders synchronously (no Suspense fallback flash).
|
|
20
|
+
*/
|
|
21
|
+
function runCommit(commit, enabled) {
|
|
22
|
+
const doc = typeof document !== "undefined" ? document : void 0;
|
|
23
|
+
const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
24
|
+
if (enabled && doc?.startViewTransition && !prefersReducedMotion) {
|
|
25
|
+
doc.startViewTransition(() => {
|
|
26
|
+
flushSync(commit);
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
commit();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { VIEW_TRANSITIONS_ENABLED, runCommit };
|
|
35
|
+
//# sourceMappingURL=view-transition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-transition.js","names":[],"sources":["../../../src/utils/view-transition.ts"],"sourcesContent":["import { flushSync } from 'react-dom';\n\ndeclare const __OSSIDO_VIEW_TRANSITIONS__: boolean;\n\n/**\n * Whether the app opted into view transitions at build time. Baked in via the\n * vite `define` (`__OSSIDO_VIEW_TRANSITIONS__`); `false` when the define is\n * absent (tests / SSR), keeping transitions opt-in.\n */\nexport const VIEW_TRANSITIONS_ENABLED =\n typeof __OSSIDO_VIEW_TRANSITIONS__ !== 'undefined' &&\n __OSSIDO_VIEW_TRANSITIONS__;\n\n/** A `Document` that may expose the View Transitions API. */\ninterface ViewTransitionDocument {\n startViewTransition?: (callback: () => void) => unknown;\n}\n\n/**\n * Run a router `commit` inside `document.startViewTransition` when `enabled`, the\n * API is supported, and the user hasn't requested reduced motion — otherwise run\n * it directly.\n *\n * The commit's React state updates are wrapped in `flushSync` so the DOM shows\n * the new page before the API captures its \"after\" snapshot; React state updates\n * are async and wouldn't be applied in time otherwise. This is safe because the\n * router prefetches the destination's data + code before committing, so the new\n * route renders synchronously (no Suspense fallback flash).\n */\nexport function runCommit(commit: () => void, enabled: boolean): void {\n const doc =\n typeof document !== 'undefined'\n ? (document as unknown as ViewTransitionDocument)\n : undefined;\n\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n\n if (enabled && doc?.startViewTransition && !prefersReducedMotion) {\n doc.startViewTransition(() => {\n flushSync(commit);\n });\n return;\n }\n\n commit();\n}\n"],"mappings":";;;;;;;;AASA,MAAa,2BACX,OAAO,gCAAgC,eACvC;;;;;;;;;;;;AAkBF,SAAgB,UAAU,QAAoB,SAAwB;CACpE,MAAM,MACJ,OAAO,aAAa,cACf,WACD;CAEN,MAAM,uBACJ,OAAO,WAAW,eAClB,OAAO,aAAa,kCAAkC,CAAC,CAAC,YAAY;CAEtE,IAAI,WAAW,KAAK,uBAAuB,CAAC,sBAAsB;EAChE,IAAI,0BAA0B;GAC5B,UAAU,MAAM;EAClB,CAAC;EACD;CACF;CAEA,OAAO;AACT"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Segment } from './types';
|
|
2
|
+
export declare function joinPaths(paths: Array<string | undefined>): string;
|
|
3
|
+
export declare function parsePathname(pathname?: string): Array<Segment>;
|
|
4
|
+
export declare function trimPathLeft(path: string): string;
|
|
5
|
+
export declare function trimPathRight(path: string): string;
|
|
6
|
+
export declare function trimPath(path: string): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/utils.ts
|
|
2
|
+
function joinPaths(paths) {
|
|
3
|
+
return cleanPath(paths.filter(Boolean).join("/"));
|
|
4
|
+
}
|
|
5
|
+
function cleanPath(path) {
|
|
6
|
+
return path.replace(/\/{2,}/g, "/");
|
|
7
|
+
}
|
|
8
|
+
function trimPathLeft(path) {
|
|
9
|
+
return path === "/" ? path : path.replace(/^\/{1,}/, "");
|
|
10
|
+
}
|
|
11
|
+
function trimPathRight(path) {
|
|
12
|
+
return path === "/" ? path : path.replace(/\/{1,}$/, "");
|
|
13
|
+
}
|
|
14
|
+
function trimPath(path) {
|
|
15
|
+
return trimPathRight(trimPathLeft(path));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { joinPaths, trimPath, trimPathLeft, trimPathRight };
|
|
20
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../src/utils.ts"],"sourcesContent":["import type { Segment } from './types';\n\nexport function joinPaths(paths: Array<string | undefined>): string {\n return cleanPath(paths.filter(Boolean).join('/'));\n}\n\nfunction cleanPath(path: string): string {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/');\n}\n\nexport function parsePathname(pathname?: string): Array<Segment> {\n if (!pathname) {\n return [];\n }\n\n pathname = cleanPath(pathname);\n\n const segments: Array<Segment> = [];\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1);\n segments.push({\n type: 'pathname',\n value: '/',\n });\n }\n\n if (!pathname) {\n return segments;\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean);\n\n segments.push(\n ...split.map((part): Segment => {\n if (part === '$' || part === '*') {\n return {\n type: 'wildcard',\n value: part,\n };\n }\n\n if (part.charAt(0) === '$') {\n return {\n type: 'param',\n value: part,\n };\n }\n\n return {\n type: 'pathname',\n value: part,\n };\n }),\n );\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1);\n segments.push({\n type: 'pathname',\n value: '/',\n });\n }\n\n return segments;\n}\nexport function trimPathLeft(path: string): string {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '');\n}\nexport function trimPathRight(path: string): string {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '');\n}\nexport function trimPath(path: string): string {\n return trimPathRight(trimPathLeft(path));\n}\n"],"mappings":";AAEA,SAAgB,UAAU,OAA0C;CAClE,OAAO,UAAU,MAAM,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC;AAClD;AAEA,SAAS,UAAU,MAAsB;CAEvC,OAAO,KAAK,QAAQ,WAAW,GAAG;AACpC;AA2DA,SAAgB,aAAa,MAAsB;CACjD,OAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AACA,SAAgB,cAAc,MAAsB;CAClD,OAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AACA,SAAgB,SAAS,MAAsB;CAC7C,OAAO,cAAc,aAAa,IAAI,CAAC;AACzC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ossido-labs/ossido-router",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "React routing component for the framework ossido. Ossido is the react/rust fullstack framework",
|
|
8
|
+
"homepage": "https://ossido.dev",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "tsdown --watch",
|
|
11
|
+
"build": "tsdown && tsc -p tsconfig.build.json",
|
|
12
|
+
"prepack": "bun run build",
|
|
13
|
+
"lint": "oxlint",
|
|
14
|
+
"format": "oxfmt --check .",
|
|
15
|
+
"format:fix": "oxfmt .",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"test": "vitest run"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/ossido-labs/ossido.git",
|
|
23
|
+
"directory": "packages/ossido-router"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [],
|
|
26
|
+
"author": "Chris Schofield <chris@childishforces.com>",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"types": "dist/esm/index.d.ts",
|
|
30
|
+
"main": "dist/esm/index.js",
|
|
31
|
+
"module": "dist/esm/index.js",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"exports": {
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./dist/esm/index.d.ts",
|
|
39
|
+
"default": "./dist/esm/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"react": ">=19.0.0",
|
|
45
|
+
"react-dom": ">=19.0.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"react-intersection-observer": "^9.13.0",
|
|
49
|
+
"@ossido-labs/ossido-ui": "0.1.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@testing-library/react": "16.3.0",
|
|
53
|
+
"@types/react": "19.1.8",
|
|
54
|
+
"@types/react-dom": "19.1.6",
|
|
55
|
+
"@vitejs/plugin-react-swc": "4.3.2",
|
|
56
|
+
"happy-dom": "18.0.1",
|
|
57
|
+
"react": "^19.2.8",
|
|
58
|
+
"react-dom": "^19.2.8",
|
|
59
|
+
"tsdown": "0.22.14",
|
|
60
|
+
"vite": "^8.1.5",
|
|
61
|
+
"vite-config": "1.0.0",
|
|
62
|
+
"vitest": "4.1.10"
|
|
63
|
+
}
|
|
64
|
+
}
|