@owlmeans/web-router 0.1.18-rc.50 → 0.1.18-rc.52
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/README.md +124 -21
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/web-router/SKILL.md +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,46 +1,149 @@
|
|
|
1
1
|
# @owlmeans/web-router
|
|
2
2
|
|
|
3
|
-
The default OwlMeans in-browser routing plugin
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
- Provides `useParams`, `useLocation`, `useNavigate`, `outlet()`, `provider()` via the service
|
|
12
|
-
- Used internally by `@owlmeans/web-client`'s `makeContext` — not typically used directly
|
|
3
|
+
The default OwlMeans in-browser routing plugin: standard URL routing over the browser History API,
|
|
4
|
+
a pure route matcher from `@owlmeans/router`, and a React provider, outlet and hooks — with no
|
|
5
|
+
third-party router. It registers itself as a `RouterPlugin` on the `@owlmeans/router` host, and
|
|
6
|
+
`@owlmeans/web-client` / `@owlmeans/web-panel` call `appendWebRouter` in their `makeContext`, so a
|
|
7
|
+
web app gets it without importing anything. An app imports it directly only for a custom context
|
|
8
|
+
setup or to reach the plugin's components and hooks outside the `context.router()` facade. To route
|
|
9
|
+
with react-router instead, add `@owlmeans/web-router-react-router` (higher priority, wins the
|
|
10
|
+
cascade); an SSR or React Native host is a plugin of its own.
|
|
13
11
|
|
|
14
12
|
## Installation
|
|
15
13
|
|
|
16
14
|
```bash
|
|
17
|
-
bun add @owlmeans/web-router@^0.1.18-rc.
|
|
15
|
+
bun add @owlmeans/web-router@^0.1.18-rc.52
|
|
18
16
|
```
|
|
19
17
|
|
|
18
|
+
`react` is a peer dependency.
|
|
19
|
+
|
|
20
|
+
## Concepts
|
|
21
|
+
|
|
22
|
+
- **Router host** — the `RouterService` of `@owlmeans/router`, registered once per context
|
|
23
|
+
(`ensureRouterService`). Its facade (`provider`, `outlet`, `compile`, `useParams`, `useLocation`,
|
|
24
|
+
`useNavigate`, `useSearchParams`) delegates to the active plugin.
|
|
25
|
+
- **Browser plugin** — `makeBrowserRouterPlugin()`: alias `BROWSER_ROUTER`, priority 0, mode
|
|
26
|
+
`'browser'`, `match` always true — the universal browser fallback any higher-priority plugin
|
|
27
|
+
outranks.
|
|
28
|
+
- **Compile** — `compile(routes)` flattens and ranks the neutral `RouteObject[]`
|
|
29
|
+
(`{ index?, path?, children?, Component? }`) into matchable branches; synchronous.
|
|
30
|
+
- **Route chain** — `BrowserRouterProvider` re-matches on every history change and renders the chain
|
|
31
|
+
through `RouteChain`; each `<Outlet/>` renders the next-deeper match. A match without a
|
|
32
|
+
`Component` is a pass-through, as in react-router's implicit outlet.
|
|
33
|
+
- **Route syntax** — static segments, `:param`, nested routes and index routes; a static segment
|
|
34
|
+
outranks a `:param` sibling. No splat or optional segments.
|
|
35
|
+
|
|
20
36
|
## Usage
|
|
21
37
|
|
|
22
|
-
|
|
38
|
+
### Default wiring
|
|
39
|
+
|
|
40
|
+
Nothing to do with `@owlmeans/web-client` or `@owlmeans/web-panel`. A context assembled by hand
|
|
41
|
+
registers the plugin itself:
|
|
23
42
|
|
|
24
43
|
```typescript
|
|
25
44
|
import { appendWebRouter } from '@owlmeans/web-router'
|
|
26
45
|
|
|
27
|
-
appendWebRouter(context)
|
|
46
|
+
appendWebRouter(context) // ensures the router host, then registers the browser plugin
|
|
28
47
|
```
|
|
29
48
|
|
|
30
|
-
|
|
49
|
+
### Read the route in a component
|
|
50
|
+
|
|
51
|
+
Inside an OwlMeans app, reach the hooks through the facade so the active plugin answers:
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { useContext } from '@owlmeans/client'
|
|
55
|
+
|
|
56
|
+
export const UserScreen = () => {
|
|
57
|
+
const context = useContext()
|
|
58
|
+
const { id } = context.router().useParams<{ id: string }>()
|
|
59
|
+
const [query] = context.router().useSearchParams()
|
|
60
|
+
const navigate = context.router().useNavigate()
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<button onClick={() => navigate(`/users/${id}/edit`, { state: { from: query.get('tab') } })}>
|
|
64
|
+
edit
|
|
65
|
+
</button>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
```
|
|
31
69
|
|
|
32
|
-
|
|
70
|
+
`navigate(to, { replace?, state? })` takes a path string, a `{ pathname?, search?, hash? }`
|
|
71
|
+
object, or a number for history steps; an absolute `http…` string is a full-page navigation.
|
|
72
|
+
The setter returned by `useSearchParams` (`set(next, { replace?, state? })`) rewrites the search part
|
|
73
|
+
of the current path.
|
|
33
74
|
|
|
34
|
-
|
|
75
|
+
### Use the plugin standalone
|
|
35
76
|
|
|
36
|
-
|
|
77
|
+
The same components and hooks are exported directly — what the package's own browser harness does:
|
|
37
78
|
|
|
38
|
-
|
|
79
|
+
```tsx
|
|
80
|
+
import { createRoot } from 'react-dom/client'
|
|
81
|
+
import type { RouteObject } from '@owlmeans/router'
|
|
82
|
+
import { makeBrowserRouterPlugin, Outlet, useParams } from '@owlmeans/web-router'
|
|
39
83
|
|
|
40
|
-
|
|
84
|
+
const Layout = () => <main><Outlet /></main>
|
|
85
|
+
const Home = () => <p>home</p>
|
|
86
|
+
const User = () => <p>user {useParams().id}</p>
|
|
41
87
|
|
|
42
|
-
|
|
88
|
+
const routes: RouteObject[] = [
|
|
89
|
+
{ path: '', Component: Layout, children: [
|
|
90
|
+
{ index: true, Component: Home },
|
|
91
|
+
{ path: 'users', children: [{ path: ':id', Component: User }] }, // component-less group passes through
|
|
92
|
+
] },
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
const plugin = makeBrowserRouterPlugin()
|
|
96
|
+
const Provider = plugin.provider()
|
|
97
|
+
createRoot(document.getElementById('root')!).render(<Provider router={plugin.compile(routes)} />)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Switch to react-router
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { appendReactRouter } from '@owlmeans/web-router-react-router'
|
|
104
|
+
|
|
105
|
+
appendReactRouter(context) // priority 100 outranks the browser plugin
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## API
|
|
109
|
+
|
|
110
|
+
| Symbol | Kind | Purpose |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| `appendWebRouter(ctx)` | function | `ensureRouterService(ctx)` + register the browser plugin; returns the context |
|
|
113
|
+
| `makeWebRouterService()` | function | back-compat: a new router host pre-loaded with the browser plugin |
|
|
114
|
+
| `makeBrowserRouterPlugin()` | function | the `RouterPlugin` itself |
|
|
115
|
+
| `BROWSER_ROUTER` | const | `'owlmeans-browser-router'` — the plugin alias |
|
|
116
|
+
| `BrowserRouterProvider` | component | `{ router: LibraryRouter }` — subscribes to history and renders the match chain |
|
|
117
|
+
| `Outlet` | component | renders the next-deeper match |
|
|
118
|
+
| `RouteChain` | component | `{ depth }` — renders the chain from a depth, skipping component-less matches |
|
|
119
|
+
| `useParams`, `useLocation`, `useNavigate`, `useSearchParams` | hooks | the plugin's hooks; throw outside the provider |
|
|
120
|
+
| `createBrowserHistory()` | function | `BrowserHistory` over `window.history` + `popstate`; an inert stub without `window` |
|
|
121
|
+
| `OwlLibraryRouter` | type | `{ routes, branches }` — what `compile` returns |
|
|
122
|
+
| `RouterState` | type | `{ location, matches, navigate }` — the provider's React context value |
|
|
123
|
+
| `BrowserHistory` | type | `location`, `push`, `replace`, `go`, `listen` |
|
|
124
|
+
|
|
125
|
+
## Common pitfalls
|
|
126
|
+
|
|
127
|
+
- A hook used outside `BrowserRouterProvider` throws
|
|
128
|
+
`owlmeans-browser-router: router hook used outside of the router provider`.
|
|
129
|
+
- Calling the plugin's hooks directly bypasses the cascade; in an app, use `context.router().…` so a
|
|
130
|
+
switched plugin keeps working.
|
|
131
|
+
- Splat (`*`) and optional segments are not supported; declare explicit routes.
|
|
132
|
+
- `makeWebRouterService()` builds a separate host; prefer `appendWebRouter`, which reuses the
|
|
133
|
+
context's host.
|
|
134
|
+
- `noRouter` works on `<App>` only — `<PanelApp>` accepts the prop by type but still mounts the
|
|
135
|
+
router.
|
|
136
|
+
|
|
137
|
+
## Related packages
|
|
138
|
+
|
|
139
|
+
- [`@owlmeans/router`](../router) — the router host, `RouterPlugin` contract and pure matcher
|
|
140
|
+
- [`@owlmeans/web-router-react-router`](../web-router-react-router) — opt-in react-router v7 plugin
|
|
141
|
+
- [`@owlmeans/client`](../client) — builds `RouteObject[]` from the entrypoint tree and exposes `context.router()`
|
|
43
142
|
- [`@owlmeans/web-client`](../web-client) — calls `appendWebRouter` inside `makeContext`
|
|
143
|
+
- [`@owlmeans/web-panel`](../web-panel) — the panel layer, wired the same way
|
|
144
|
+
|
|
145
|
+
The `web-router` skill describes this plugin; the `router-plugins` skill covers the plugin contract,
|
|
146
|
+
cascade selection and authoring a new plugin.
|
|
44
147
|
|
|
45
148
|
<!-- owlmeans:agent-guidance:start -->
|
|
46
149
|
## Agent guidance
|
|
@@ -50,7 +153,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
50
153
|
your project's skill store (`.agents/skills/`):
|
|
51
154
|
|
|
52
155
|
```sh
|
|
53
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
156
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.54
|
|
54
157
|
```
|
|
55
158
|
|
|
56
159
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/web-router",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.52",
|
|
5
|
+
"generatedAt": "2026-10-15T10:20:01.313Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -8,7 +8,7 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/web-router
|
|
9
9
|
|
|
10
10
|
**Layer:** Web (React), build level L2
|
|
11
|
-
**Install:** `"@owlmeans/web-router": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/web-router": "^0.1.18-rc.52"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
This package **is the default OwlMeans in-browser router** — a minimal, react-router-free
|
|
14
14
|
implementation of standard URL routing over the browser History API. It registers itself as a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/web-router",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.52",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@owlmeans/dep-config": "workspace:*",
|
|
29
|
-
"@owlmeans/test-ui": "^0.1.18-rc.
|
|
29
|
+
"@owlmeans/test-ui": "^0.1.18-rc.52",
|
|
30
30
|
"@types/node": "^26.6.4",
|
|
31
31
|
"@types/react": "^19.3.0",
|
|
32
32
|
"@vitejs/plugin-react": "^6.1.1",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@owlmeans/context": "^0.1.18-rc.34",
|
|
42
|
-
"@owlmeans/router": "^0.1.18-rc.
|
|
42
|
+
"@owlmeans/router": "^0.1.18-rc.34"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|