Skip to content

Commit 97602bc

Browse files
committed
release gh-pages
1 parent d9d230f commit 97602bc

16 files changed

+632
-0
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_includes

_layouts/index.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html lang="en" style="--color-scheme: steelblue">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>@t8/react-router | Straightforward and minimalist router for React apps</title>
7+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/base.css">
8+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/index.css">
9+
<link rel="icon" type="image/svg+xml" href="{{site.github.baseurl}}/favicon.svg">
10+
<link rel="prefetch" href="{{site.github.baseurl}}/start">
11+
<link rel="prefetch" href="{{site.github.baseurl}}/x/Route_matching">
12+
</head>
13+
<body>
14+
<div class="layout">
15+
<main>
16+
{{content}}
17+
</main>
18+
</div>
19+
20+
{% if content contains '<pre><code ' %}<link rel="stylesheet" href="https://unpkg.com/@highlightjs/[email protected]/styles/base16/material.min.css">
21+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/code.css">
22+
<script src="https://unpkg.com/@highlightjs/[email protected]/highlight.min.js"></script>
23+
<script>hljs.highlightAll()</script>{% elsif content contains '<pre ' %}<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/code.lightbulb.css">
24+
{% endif %}
25+
<script>
26+
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
27+
m[i].l=1*new Date();
28+
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
29+
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
30+
(window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
31+
ym(103784239, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
32+
</script>
33+
<noscript><div><img src="https://mc.yandex.com/watch/103784239" style="position:absolute;left:-9999px;" alt=""></div></noscript>
34+
</body>
35+
</html>

_layouts/section.html

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<!DOCTYPE html>
2+
<html lang="en" style="--color-scheme: steelblue">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>{{page.title | strip_html}} | @t8/react-router</title>
7+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/base.css">
8+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/section.css">
9+
<link rel="icon" type="image/svg+xml" href="{{site.github.baseurl}}/favicon.svg">
10+
{% unless page.next.id == '' %}<link rel="prefetch" href="{{site.github.baseurl}}/x/{{page.next.id}}">{% endunless %}
11+
{% unless page.prev.id == '' %}<link rel="prefetch" href="{{site.github.baseurl}}/x/{{page.prev.id}}">{% endunless %}
12+
</head>
13+
<body>
14+
<div class="layout">
15+
<div class="body">
16+
<nav>
17+
<ul>
18+
<li>{% if page.id == "Route_matching" %}<strong>Route matching</strong>{% else %}<a href="{{site.github.baseurl}}/x/Route_matching">Route matching</a>{% endif %}</li>
19+
<li>{% if page.id == "Route_navigation" %}<strong>Route navigation</strong>{% else %}<a href="{{site.github.baseurl}}/x/Route_navigation">Route navigation</a>{% endif %}
20+
<ul>
21+
<li>Route link component</li>
22+
<li>Imperative route navigation</li>
23+
</ul>
24+
</li>
25+
<li>{% if page.id == "Routing_middleware" %}<strong>Routing middleware</strong>{% else %}<a href="{{site.github.baseurl}}/x/Routing_middleware">Routing middleware</a>{% endif %}</li>
26+
<li>{% if page.id == "Converting_HTML_links_to_SPA_route_links" %}<strong>Converting HTML links to SPA route links</strong>{% else %}<a href="{{site.github.baseurl}}/x/Converting_HTML_links_to_SPA_route_links">Converting HTML links to SPA route links</a>{% endif %}</li>
27+
<li>{% if page.id == "Router" %}<strong><code>&lt;Router&gt;</code></strong>{% else %}<a href="{{site.github.baseurl}}/x/Router"><code>&lt;Router&gt;</code></a>{% endif %}</li>
28+
<li>{% if page.id == "Unknown_routes" %}<strong>Unknown routes</strong>{% else %}<a href="{{site.github.baseurl}}/x/Unknown_routes">Unknown routes</a>{% endif %}</li>
29+
<li>{% if page.id == "Lazy_routes" %}<strong>Lazy routes</strong>{% else %}<a href="{{site.github.baseurl}}/x/Lazy_routes">Lazy routes</a>{% endif %}</li>
30+
<li>{% if page.id == "URL_parameters" %}<strong>URL parameters</strong>{% else %}<a href="{{site.github.baseurl}}/x/URL_parameters">URL parameters</a>{% endif %}</li>
31+
<li>{% if page.id == "Type-safe_routing" %}<strong>Type-safe routing</strong>{% else %}<a href="{{site.github.baseurl}}/x/Type-safe_routing">Type-safe routing</a>{% endif %}</li>
32+
</ul>
33+
<ul class="ref">
34+
<li><a href="https://github.com/t8js/react-router" target="_blank">GitHub</a></li>
35+
<li><a href="https://axtk.github.io/x/t8_react_router">Backstory</a></li>
36+
</ul>
37+
</nav>
38+
<main>
39+
<h1><a href="{{site.github.baseurl}}/">@t8/react-router</a></h1>
40+
{{content}}
41+
42+
<p class="pagenav">
43+
<span class="prev">
44+
<span class="icon"></span>
45+
{% if page.prev.id == '' %}<a href="{{site.github.baseurl}}/">Intro</a>{% else %}<a href="{{site.github.baseurl}}/x/{{page.prev.id}}">{{page.prev.title}}</a>{% endif %}
46+
</span>
47+
<span class="sep">|</span>
48+
{% if page.next.id == '' %}
49+
<span class="repo next">
50+
<a href="https://github.com/t8js/react-router" target="_blank">GitHub</a>
51+
<span class="icon"></span>
52+
</span>
53+
{% else %}
54+
<span class="next">
55+
<a href="{{site.github.baseurl}}/x/{{page.next.id}}">{{page.next.title}}</a>
56+
<span class="icon"></span>
57+
</span>
58+
{% endif %}
59+
</p>
60+
</main>
61+
</div>
62+
</div>
63+
64+
{% if content contains '<pre><code ' %}<link rel="stylesheet" href="https://unpkg.com/@highlightjs/[email protected]/styles/base16/material.min.css">
65+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/code.css">
66+
<script src="https://unpkg.com/@highlightjs/[email protected]/highlight.min.js"></script>
67+
<script>hljs.highlightAll()</script>{% elsif content contains '<pre ' %}<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/code.lightbulb.css">
68+
{% endif %}
69+
<script>
70+
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
71+
m[i].l=1*new Date();
72+
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
73+
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
74+
(window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
75+
ym(103784239, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
76+
</script>
77+
<noscript><div><img src="https://mc.yandex.com/watch/103784239" style="position:absolute;left:-9999px;" alt=""></div></noscript>
78+
</body>
79+
</html>

_layouts/start.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en" class="blank" style="--color-scheme: steelblue">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width">
6+
<meta http-equiv="refresh" content="0; URL={{site.github.baseurl}}/x/{{page.start_id}}">
7+
<title>@t8/react-router</title>
8+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/base.css">
9+
<link rel="icon" type="image/svg+xml" href="{{site.github.baseurl}}/favicon.svg">
10+
<script>window.location.replace("{{site.github.baseurl}}/x/{{page.start_id}}");</script>
11+
</head>
12+
<body>
13+
<div class="layout">
14+
<h1>@t8/react-router</h1>
15+
</div>
16+
17+
<script>
18+
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
19+
m[i].l=1*new Date();
20+
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
21+
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
22+
(window, document, "script", "https://mc.yandex.com/metrika/tag.js", "ym");
23+
ym(103784239, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true});
24+
</script>
25+
<noscript><div><img src="https://mc.yandex.com/watch/103784239" style="position:absolute;left:-9999px;" alt=""></div></noscript>
26+
</body>
27+
</html>

favicon.svg

Lines changed: 1 addition & 0 deletions
Loading

index.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
layout: index
3+
---
4+
5+
<section class="intro-title">
6+
<div class="badges">
7+
<p><a href="https://www.npmjs.com/package/@t8/react-router"><img src="https://flat.badgen.net/npm/v/@t8/react-router?labelColor=345&amp;color=46e" alt="npm"></a> <img src="https://flat.badgen.net/bundlephobia/minzip/@t8/react-router/?label=minzip&amp;labelColor=345&amp;color=46e&amp;r=0" alt="Lightweight"> <img src="https://flat.badgen.net/badge/TypeScript/%E2%9C%93?labelColor=345&amp;color=345" alt="TypeScript ✓"> <img src="https://flat.badgen.net/badge/CSR/%E2%9C%93?labelColor=345&amp;color=345" alt="CSR ✓"> <img src="https://flat.badgen.net/badge/SSR/%E2%9C%93?labelColor=345&amp;color=345" alt="SSR ✓"></p>
8+
</div>
9+
<h1>@t8/react-router</h1>
10+
<div class="description">
11+
<p><em>Straightforward and minimalist router for React apps</em></p>
12+
</div>
13+
<p class="actions">
14+
<a href="{{site.github.baseurl}}/start" class="primary button">Docs ›››</a>
15+
<span class="sep"></span>
16+
<a href="https://github.com/t8js/react-router" class="button" target="_blank">GitHub</a>
17+
</p>
18+
<p class="ref"><a href="https://axtk.github.io/x/t8_react_router">Backstory</a></p>
19+
<p class="installation"><code>npm i @t8/react-router</code></p>
20+
</section>
21+
22+
<section class="intro">
23+
<div class="features">
24+
<h2>Features</h2>
25+
<ul>
26+
<li>Consistent route matching in components and prop values</li>
27+
<li>Decoupled routes: no hierarchy as a prerequisite</li>
28+
<li>Similar to native navigation APIs</li>
29+
<li>Straightforward middleware hooks and lazy routes</li>
30+
<li>Type-safe routing and typed URL parameters</li>
31+
<li>Straightforward compatibility with SSR and CSR</li>
32+
<li>Utility hook to convert HTML links to SPA route links</li>
33+
</ul>
34+
</div>
35+
</section>

start.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
layout: start
3+
start_id: "Route_matching"
4+
---
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
layout: section
3+
id: "Converting_HTML_links_to_SPA_route_links"
4+
title: "Converting HTML links to SPA route links"
5+
prev:
6+
id: "Routing_middleware"
7+
title: "Routing middleware"
8+
next:
9+
id: "Router"
10+
title: "<code>&lt;Router&gt;</code>"
11+
---
12+
13+
<h2 id="converting-html-links-to-spa-route-links">Converting HTML links to SPA route links</h2>
14+
<p>A chunk of static HTML content is an example where the route link component can't be directly used but it still might be desirable to make plain HTML links in that content behave as SPA route links. The <code>useRouteLinks()</code> hook can be helpful here:</p>
15+
<pre><code class="language-jsx">import {useRef} from 'react';
16+
import {useRouteLinks} from '@t8/react-router';
17+
18+
let Content = ({value}) =&gt; {
19+
let containerRef = useRef(null);
20+
21+
useRouteLinks(containerRef);
22+
23+
return (
24+
&lt;div ref={containerRef}&gt;
25+
{value}
26+
&lt;/div&gt;
27+
);
28+
};
29+
</code></pre>
30+
<p>In this example, the <code>useRouteLinks()</code> hook makes all HTML links inside the container referenced by <code>containerRef</code> act as SPA route links.</p>
31+
<p>To be more specific as to which elements in the container should be converted to route links, a selector, or an HTML element, or a collection thereof, can be passed as the second parameter of <code>useRouteLinks()</code>:</p>
32+
<pre><code class="language-js">useRouteLinks(containerRef, '.content a');
33+
</code></pre>

x/Lazy_routes.html

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
layout: section
3+
id: "Lazy_routes"
4+
title: "Lazy routes"
5+
prev:
6+
id: "Unknown_routes"
7+
title: "Unknown routes"
8+
next:
9+
id: "URL_parameters"
10+
title: "URL parameters"
11+
---
12+
13+
<h2 id="lazy-routes">Lazy routes</h2>
14+
<p>Lazy routes are routes whose content is loaded on demand, when the route is visited.</p>
15+
<p>Enabling lazy routes doesn't require a specific routing setup. It's a combination of the <a href="{{site.github.baseurl}}/x/Route_matching">route matching</a> and lazily loaded React components (with <code>React.lazy()</code> and React's <code>&lt;Suspense&gt;</code>), processed by a code-splitting-capable build tool (like Esbuild, Webpack, Rollup, Vite):</p>
16+
<pre><code class="language-diff">+ import {Suspense} from 'react';
17+
import {A, useRoute} from '@t8/react-router';
18+
import {Intro} from './Intro';
19+
- import {Projects} from './Projects';
20+
+ import {Projects} from './Projects.lazy';
21+
22+
export const App = () =&gt; {
23+
let {withRoute} = useRoute();
24+
25+
return (
26+
&lt;&gt;
27+
&lt;nav&gt;
28+
&lt;A href="/"&gt;Intro&lt;/A&gt;
29+
&lt;A href="/projects"&gt;Projects&lt;/A&gt;
30+
&lt;/nav&gt;
31+
{withRoute('/', (
32+
&lt;Intro/&gt;
33+
))}
34+
{withRoute('/projects', (
35+
- &lt;Projects/&gt;
36+
+ &lt;Suspense fallback={&lt;p&gt;Loading...&lt;/p&gt;}&gt;
37+
+ &lt;Projects/&gt;
38+
+ &lt;/Suspense&gt;
39+
))}
40+
&lt;/&gt;
41+
);
42+
};
43+
</code></pre>
44+
<pre><code class="language-diff">+ // Projects.lazy.js
45+
+ import {lazy} from 'react';
46+
+
47+
+ export const Projects = lazy(() =&gt; import('./Projects'));
48+
</code></pre>
49+
<p><a href="https://codesandbox.io/p/sandbox/x75p5w?file=%2Fsrc%2FApp.jsx" target="_blank">Live demo</a></p>
50+
<p>In this example, the <code>&lt;Projects&gt;</code> component isn't loaded until the corresponding <code>/projects</code> route is visited. When it's first visited, while the component is being fetched, <code>&lt;p&gt;Loading...&lt;/p&gt;</code> shows up, as specified with the <code>fallback</code> prop of <code>&lt;Suspense&gt;</code>.</p>

x/Route_matching.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
layout: section
3+
id: "Route_matching"
4+
title: "Route matching"
5+
prev:
6+
id: ""
7+
title: ""
8+
next:
9+
id: "Route_navigation"
10+
title: "Route navigation"
11+
---
12+
13+
<h2 id="route-matching">Route matching</h2>
14+
<p>Rendering based on the URL with <code>@t8/react-router</code> is similar to conditional rendering with the ternary operator <code>matchesRoutePattern ? x : y</code>, equally applicable to components and prop values and resulting in a single consistent approach for both. This is a contrast to the component-, config-, or file-based route matching which are typically focused on component rendering, while route-based prop values have to be handled differently.</p>
15+
<pre><code class="language-jsx">import {useRoute} from '@t8/react-router';
16+
17+
let App = () =&gt; {
18+
let {withRoute} = useRoute();
19+
20+
// `withRoute(routePattern, x, y)` acts similarly to
21+
// `matchesRoutePattern ? x : y`
22+
return (
23+
&lt;&gt;
24+
&lt;header className={withRoute('/', 'full', 'compact')}&gt;
25+
&lt;h1&gt;App&lt;/h1&gt;
26+
&lt;/header&gt;
27+
{withRoute('/', (
28+
&lt;main&gt;
29+
&lt;h1&gt;Intro&lt;/h1&gt;
30+
&lt;/main&gt;
31+
))}
32+
{withRoute(/^\/sections\/(?&lt;id&gt;\d+)\/?$/, ({params}) =&gt; (
33+
&lt;main&gt;
34+
&lt;h1&gt;Section {params.id}&lt;/h1&gt;
35+
&lt;/main&gt;
36+
))}
37+
&lt;/&gt;
38+
);
39+
};
40+
</code></pre>
41+
<p><a href="https://codesandbox.io/p/sandbox/kqn8wr?file=%252Fsrc%252FApp.tsx" target="_blank">Live demo</a></p>
42+
<p>Note that both the header's <code>className</code> prop and the <code>&lt;main&gt;</code> component are rendered in a single way using the same route-matching function.</p>
43+
<p>🔹 The ternary route-matching function <code>withRoute(routePattern, x, y)</code> returned from the <code>useRoute()</code> hook has the semantics similar to the ternary conditional operator <code>matchesRoutePattern ? x : y</code>, commonly seen with the conditional rendering pattern, which reflects the fact that route-based rendering also falls under this category.</p>
44+
<p>🔹 <code>withRoute()</code> doesn't impose any route hierarchy by default, as it can be used with any route pattern anywhere in the app's components, offering sufficient flexibility to handle arbitrary route-based logic.</p>
45+
<p>🔹 <code>withRoute()</code> accepts route patterns of various types: <code>string | RegExp | (string | RegExp)[]</code>. The parameters of a regular expression route pattern (or of the first <code>RegExp</code> match in the array) are passed to the second and the third parameter of <code>withRoute()</code> if they are functions, as shown in the example above.</p>

0 commit comments

Comments
 (0)