Skip to content

Commit b0ce185

Browse files
authored
[add] 404 page route (#17)
1 parent ff0ff88 commit b0ce185

File tree

10 files changed

+1263
-1157
lines changed

10 files changed

+1263
-1157
lines changed

Contributing.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ git clone https://github.com/EasyWebApp/cell-router.git ~/Desktop/cell-router
99
cd ~/Desktop/cell-router
1010

1111
pnpm i
12+
pnpm setup-browser
1213
npm start
1314
```

ReadMe.md

Lines changed: 87 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,22 @@ https://web-cell.dev/cell-router/preview/
1313

1414
## Feature
1515

16-
- [x] `<iframe />`-like **Route Component** as a **Page Container**
16+
- [x] **Route Component** as a **Page Configuration**
1717

18-
- [x] **Page Link** (support `<a />`, `<area />` & `<form />`)
18+
- [x] **Path Matching** with [`new URLPattern()`][7] (`*` for HTTP `404`)
1919

20+
- [x] **Page Link** (support `<a />`, `<area />` & `<form />`)
2021
- `<a href="route/path">Page title</a>`
2122
- `<a href="route/path" title="Page title">Example page</a>`
2223
- `<a href="#page-section">Page section</a>` (Scroll to an Anchor smoothly)
23-
- `<form method="get" action="route/path" />` (Form Data processed by `URLSearchParams`)
24+
- `<form method="get" action="route/path" />` (Form Data processed by `new URLSearchParams()`)
25+
- custom component with `href` property
2426

2527
- [x] **Path Mode**: `location.hash` (default) & `history.pushState()`
2628

27-
- [x] **Async Loading** (based on `import()` ECMAScript syntax)
29+
- [x] **Async Loading** (based on `async`/`await` or `import()` ECMAScript syntax)
2830

29-
- [x] [View Transition API][7] based **Page Transition Animation**
31+
- [x] [View Transition API][8] based **Page Transition Animation**
3032

3133
## Version
3234

@@ -82,17 +84,11 @@ npm install parcel @parcel/config-default @parcel/transformer-typescript-tsc -D
8284
```tsx
8385
import { DOMRenderer } from 'dom-renderer';
8486
import { FC } from 'web-cell';
85-
import { CellRouter, createRouter, PageProps } from 'cell-router';
87+
import { createRouter, PageProps } from 'cell-router';
8688

87-
const { Route, Link } = createRouter();
89+
const { Router, Route, Link } = createRouter();
8890

89-
const TestPage: FC<PageProps> = ({
90-
className,
91-
style,
92-
path,
93-
history,
94-
...data
95-
}) => (
91+
const TestPage: FC<PageProps> = ({ className, style, path, history, ...data }) => (
9692
<ul {...{ className, style }}>
9793
<li>Path: {path}</li>
9894
<li>Data: {JSON.stringify(data)}</li>
@@ -105,14 +101,12 @@ new DOMRenderer().render(
105101
<Link to="test?a=1">Test</Link>
106102
<Link to="example/2">Example</Link>
107103
</nav>
108-
<CellRouter className="router">
109-
<Route
110-
path=""
111-
component={props => <div {...props}>Home Page</div>}
112-
/>
104+
<Router>
105+
<Route path="" component={() => <h1>Home Page</h1>} />
113106
<Route path="test" component={TestPage} />
114107
<Route path="example/:id" component={TestPage} />
115-
</CellRouter>
108+
<Route path="*" component={() => <h1>404 Not Found</h1>} />
109+
</Router>
116110
</>
117111
);
118112
```
@@ -129,43 +123,94 @@ new DOMRenderer().render(
129123
}
130124
```
131125

126+
#### `source/Dynamic.tsx`
127+
128+
```tsx
129+
import { FC } from 'web-cell';
130+
import { PageProps } from 'cell-router';
131+
132+
const DynamicPage: FC<PageProps> = ({ path, id, ...props }) => (
133+
<div {...props}>
134+
<h1>Dynamic</h1>
135+
<pre>
136+
<code>{JSON.stringify({ path, id, ...props }, null, 4)}</code>
137+
</pre>
138+
</div>
139+
);
140+
export default DynamicPage;
141+
```
142+
143+
#### `source/Async.tsx`
144+
145+
```tsx
146+
import { FC, observer } from 'web-cell';
147+
import { sleep } from 'web-utility';
148+
import { PageProps } from 'cell-router';
149+
150+
export const AsyncPage: FC<PageProps> = observer(async props => {
151+
await sleep();
152+
153+
return (
154+
<div {...props}>
155+
<h1>Async</h1>
156+
<pre>
157+
<code>{JSON.stringify(props, null, 4)}</code>
158+
</pre>
159+
</div>
160+
);
161+
});
162+
```
163+
132164
#### `source/index.tsx`
133165

134166
```tsx
135167
import { DOMRenderer } from 'dom-renderer';
136168
import { FC, lazy } from 'web-cell';
137-
import { CellRouter, createRouter, PageProps } from 'cell-router';
169+
import { createRouter, PageProps } from 'cell-router';
170+
171+
import { AsyncPage } from './Async';
138172

139-
const { Route, Link } = createRouter();
173+
const { Router, Route, Link } = createRouter();
140174

141-
const TestPage: FC<PageProps> = ({
142-
className,
143-
style,
144-
path,
145-
history,
146-
...data
147-
}) => (
175+
const SyncPage: FC<PageProps> = ({ className, style, path, history, ...data }) => (
148176
<ul {...{ className, style }}>
149177
<li>Path: {path}</li>
150178
<li>Data: {JSON.stringify(data)}</li>
151179
</ul>
152180
);
153-
const AsyncPage = lazy(() => import('./Async'));
181+
const DynamicPage = lazy(() => import('./Dynamic'));
154182

155183
new DOMRenderer().render(
156184
<>
157185
<nav>
158-
<Link to="test?a=1">Test</Link>
159-
<Link to="example/2">Example</Link>
186+
<Link to="sync?a=1">Sync</Link>
187+
<Link to="dynamic/2">Dynamic</Link>
188+
<Link to="async/3">Async</Link>
160189
</nav>
161-
<CellRouter className="router">
162-
<Route
163-
path=""
164-
component={props => <div {...props}>Home Page</div>}
165-
/>
166-
<Route path="test" component={TestPage} />
167-
<Route path="example/:id" component={AsyncPage} />
168-
</CellRouter>
190+
<Router>
191+
<Route path="sync" component={SyncPage} />
192+
<Route path="dynamic/:id" component={DynamicPage} />
193+
<Route path="async/:id" component={AsyncPage} />
194+
</Router>
195+
</>
196+
);
197+
```
198+
199+
### Custom Link Component
200+
201+
```tsx
202+
import { Button } from 'boot-cell';
203+
import { createRouter } from 'cell-router';
204+
import { DOMRenderer } from 'dom-renderer';
205+
206+
const { Router, Route, Button: XButton } = createRouter({ linkTags: { Button } });
207+
208+
new DOMRenderer().render(
209+
<>
210+
<XButton href="route/path">Example Page</XButton>
211+
<Router>
212+
<Route path="route/path" component={() => <h1>Example Page</h1>} />
213+
</Router>
169214
</>
170215
);
171216
```
@@ -176,4 +221,5 @@ new DOMRenderer().render(
176221
[4]: https://libraries.io/npm/cell-router
177222
[5]: https://github.com/EasyWebApp/cell-router/actions/workflows/main.yml
178223
[6]: https://nodei.co/npm/cell-router/
179-
[7]: https://developer.chrome.com/docs/web-platform/view-transitions/
224+
[7]: https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API
225+
[8]: https://developer.chrome.com/docs/web-platform/view-transitions/

package.json

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cell-router",
3-
"version": "4.0.3",
3+
"version": "4.0.4",
44
"license": "LGPL-3.0",
55
"description": "Web Component Router based on WebCell & MobX",
66
"keywords": [
@@ -26,36 +26,36 @@
2626
"dependencies": {
2727
"@swc/helpers": "^0.5.17",
2828
"dom-renderer": "^2.6.2",
29-
"mobx": "^6.13.7",
29+
"mobx": "^6.15.0",
3030
"regenerator-runtime": "^0.14.1",
3131
"urlpattern-polyfill": "^10.1.0",
32-
"web-cell": "^3.2.1",
33-
"web-utility": "^4.5.1"
32+
"web-cell": "^3.2.2",
33+
"web-utility": "^4.6.1"
3434
},
3535
"devDependencies": {
36-
"@parcel/config-default": "~2.15.4",
37-
"@parcel/packager-ts": "~2.15.4",
38-
"@parcel/transformer-less": "~2.15.4",
39-
"@parcel/transformer-typescript-tsc": "~2.15.4",
40-
"@parcel/transformer-typescript-types": "~2.15.4",
36+
"@parcel/config-default": "~2.16.0",
37+
"@parcel/packager-ts": "~2.16.0",
38+
"@parcel/transformer-less": "~2.16.0",
39+
"@parcel/transformer-typescript-tsc": "~2.16.0",
40+
"@parcel/transformer-typescript-types": "~2.16.0",
4141
"@types/jest": "^29.5.14",
4242
"cross-env": "^10.0.0",
43-
"dotenv": "^17.2.1",
43+
"dotenv": "^17.2.2",
4444
"element-internals-polyfill": "^3.0.2",
4545
"fs-match": "^1.7.3",
4646
"husky": "^9.1.7",
4747
"jest": "^29.7.0",
4848
"jest-environment-jsdom": "^29.7.0",
4949
"koapache": "^2.2.2",
50-
"lint-staged": "^16.1.5",
51-
"parcel": "~2.15.4",
50+
"lint-staged": "^16.2.1",
51+
"parcel": "~2.16.0",
5252
"prettier": "^3.6.2",
5353
"process": "^0.11.10",
54-
"puppeteer-core": "^24.16.2",
54+
"puppeteer-core": "^24.22.3",
5555
"rimraf": "^6.0.1",
56-
"ts-jest": "^29.4.1",
57-
"typedoc": "^0.28.10",
58-
"typedoc-plugin-mdn-links": "^5.0.8",
56+
"ts-jest": "^29.4.4",
57+
"typedoc": "^0.28.13",
58+
"typedoc-plugin-mdn-links": "^5.0.9",
5959
"typescript": "~5.9.2"
6060
},
6161
"pnpm": {
@@ -67,7 +67,8 @@
6767
]
6868
},
6969
"scripts": {
70-
"prepare": "husky && app-find chrome msedge firefox -c",
70+
"prepare": "husky",
71+
"setup-browser": "app-find chrome msedge firefox -c",
7172
"preview": "cd test/ && rimraf ../.parcel-cache/ dist/ && parcel --open",
7273
"pack-preview": "cd test/ && rimraf ../.parcel-cache/ dist/ && parcel build --public-url=. --dist-dir=../docs/preview/",
7374
"pack-dist": "rimraf dist/ && parcel build source/index.ts",
@@ -81,7 +82,8 @@
8182
"singleQuote": true,
8283
"trailingComma": "none",
8384
"arrowParens": "avoid",
84-
"tabWidth": 4
85+
"tabWidth": 4,
86+
"printWidth": 100
8587
},
8688
"jest": {
8789
"preset": "ts-jest",

0 commit comments

Comments
 (0)