Update docs
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s

This commit is contained in:
2026-04-25 20:28:38 +02:00
parent de4b09324d
commit f4654a938a
20 changed files with 2120 additions and 1202 deletions

View File

@@ -1,96 +1,187 @@
# Routing: `Router()` & Utilities
# Routing: `router( )` & Utilities
SigPro includes a built-in, lightweight **Hash Router** to create Single Page Applications (SPA). It manages the URL state, matches components to paths, and handles the lifecycle of your pages automatically.
SigPro includes a builtin, lightweight **hash router** to create singlepage applications (SPA). It manages the URL hash, matches components to routes with dynamic segments (`:id`), and automatically cleans up each page when you navigate away.
## Router Signature
## Function Signature
```typescript
Router(routes: Route[]): HTMLElement
router(routes: Route[]): HTMLElement
```
### Route Object
| Property | Type | Description |
| :--- | :--- | :--- |
| **`path`** | `string` | The URL fragment (e.g., `"/"`, `"/user/:id"`, or `"*"`). |
| **`component`** | `Function` | A function that returns a Node, a String, or a reactive View. |
| **`path`** | `string` | The URL fragment pattern (e.g. `"/"`, `"/user/:id"`, or `"*"` for catchall). |
| **`component`** | `Function` | A function that returns a Node, a string, or a reactive view. Receives `params` object as argument. |
**Returns:** A `div` element (with class `"router-hook"`) that acts as the router outlet. The router automatically destroys the previous view and mounts the matched component when the hash changes.
---
## Usage Patterns
### 1. Defining Routes
The `Router` returns a `div` element with the class `.router-transition`. When the hash changes, the router destroys the previous view and mounts the new one inside this container.
Place the `router` element where you want the page content to appear. Inside the routes array, define your routes.
```javascript
const App = () => Div({ class: "app-layout" }, [
Navbar(),
// The router outlet is placed here
Router([
{ path: "/", component: Home },
{ path: "/profile/:id", component: (params) => UserProfile(params.id) },
{ path: "*", component: () => H1("404 Not Found") }
])
]);
const Home = () => h1("Home Page");
const UserProfile = (params) => h1(`User ID: ${params.id}`);
const NotFound = () => h1("404 Page not found");
const App = () =>
div({ class: "app-layout" }, [
nav([
a({ href: "#/" }, "Home"),
a({ href: "#/user/42" }, "User 42")
]),
router([
{ path: "/", component: Home },
{ path: "/user/:id", component: UserProfile },
{ path: "*", component: NotFound }
])
]);
mount(App, "#app");
```
### 2. Dynamic Segments (`:id`)
The router automatically parses URL parameters (like `:id`) and passes them as an object to the component function. You can also access them globally via `Router.params()`.
When a route contains a colonprefixed segment (like `:id`), the router extracts the corresponding value from the current hash and passes it as a property inside the `params` object to the component function.
```javascript
// If the URL is #/profile/42
// If the hash is #/user/42
const UserProfile = (params) => {
return H1(`User ID is: ${params.id}`); // Displays "User ID is: 42"
console.log(params.id); // "42"
return div(`User ${params.id}`);
};
```
### 3. Accessing Route Parameters Anywhere
The router maintains a reactive signal `router.params` that always holds the parameters of the currently matched route. You can read it anywhere in your app.
```javascript
watch(() => {
const params = router.params();
console.log("Current route params:", params);
});
```
---
## Navigation Utilities
SigPro provides a set of programmatic methods to control the history and read the state.
SigPro provides several helper functions to control navigation and read the router state.
### `router.to(path)`
Navigates to the given path. It automatically formats the hash (e.g. `"/dashboard"` becomes `"#/dashboard"`). You can pass either a full hash string or a path without the `#`.
### `Router.to(path)`
Navigates to a specific path. It automatically formats the hash (e.g., `/home` becomes `#/home`).
```javascript
Button({ onclick: () => Router.to("/dashboard") }, "Go to Dashboard")
button({ onclick: () => router.to("/dashboard") }, "Go to Dashboard")
```
### `Router.back()`
Goes back to the previous page in the browser history.
### `router.back()`
Goes back one step in the browsers history, just like calling `history.back()`.
```javascript
Button({ onclick: () => Router.back() }, "Back")
button({ onclick: () => router.back() }, "Back")
```
### `Router.path()`
Returns the current path (without the `#`).
### `router.path()`
Returns the current route path **without the leading `#`**. This is a plain string, not a signal.
```javascript
Watch(() => {
console.log("Current path is:", Router.path());
console.log(router.path()); // e.g. "/user/42"
```
---
## Automatic Cleanup
Every time you navigate to a new route, the router calls `.destroy()` on the previous view. This recursively disposes of:
- All `watch` effects created inside that page
- All event listeners attached via SigPros event binding
- Any nested `when`, `each`, or `router` instances
**No manual cleanup is required** memory leaks are prevented automatically.
---
## Reactive Route Parameters
`router.params` is a **reactive signal** (created with `$({})`). You can watch it to react to parameter changes without remounting the whole router outlet.
```javascript
watch(() => router.params(), (params) => {
console.log("Params changed:", params);
// e.g. fetch new data when the :id changes
});
```
---
## Technical Behavior
## Styling the Router Outlet
* **Automatic Cleanup**: Every time you navigate, the router calls `.destroy()` on the previous view. This ensures that all **signals, effects, and event listeners** from the old page are purged from memory.
* **Reactive Params**: `Router.params` is a signal (`$`). You can react to parameter changes without re-mounting the entire router outlet.
* **Hash-Based**: By using `window.location.hash`, SigPro works out-of-the-box on any static hosting (like GitHub Pages or Vercel) without needing server-side redirects.
---
## Styling the transition of Router
The router returns a standard `div` with the `.router-transition` class. You can easily style it or add transitions:
The router returns a `div` with the class `"router-hook"`. You can style it just like any other element:
```css
.router-transition {
.router-hook {
display: block;
min-height: 100vh;
animation: fadeIn 0.3s ease;
min-height: 60vh;
animation: fadeIn 0.2s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
```
```
If you want the router outlet to have no layout impact, you can set `display: contents` on it.
---
## Complete Example
```javascript
import { $, router, mount } from "sigpro";
const Home = () => div("Welcome home");
const About = () => div("About us");
const User = (params) => div(`User profile: ${params.id}`);
const App = () =>
div([
nav([
a({ href: "#/" }, "Home"),
a({ href: "#/about" }, "About"),
a({ href: "#/user/5" }, "User 5")
]),
router([
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/user/:id", component: User },
{ path: "*", component: () => div("404 Not found") }
])
]);
mount(App, "#app");
```
---
## Summary
| Function | Description |
| :--- | :--- |
| `router(routes)` | Creates a router outlet. |
| `router.to(path)` | Navigates to a new hash route. |
| `router.back()` | Goes back in history. |
| `router.path()` | Returns the current path without `#`. |
| `router.params()` | Reactive signal of the current route parameters. |