@solidrt/router 0.0.64 → 0.0.66
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/AGENTS.md +68 -4
- package/README.md +59 -3
- package/package.json +3 -3
- package/src/router.tsx +2 -2
package/AGENTS.md
CHANGED
|
@@ -57,11 +57,75 @@ let item = createRoute({ // a value: typed pa
|
|
|
57
57
|
route, or with children a pathless layout. Children match in
|
|
58
58
|
declaration order.
|
|
59
59
|
|
|
60
|
+
## App structure
|
|
61
|
+
|
|
62
|
+
Split a routed app by role, so the entry reads as a map of the app:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
src/
|
|
66
|
+
index.tsx the entry: render(), the window and the route tree
|
|
67
|
+
app.tsx App, the root layout: what stays around every screen
|
|
68
|
+
(background, safe area, nav bar), renders <Outlet />
|
|
69
|
+
state.ts module-scope signals the screens share
|
|
70
|
+
routes/
|
|
71
|
+
home.tsx / one file per screen
|
|
72
|
+
settings.tsx /settings a layout: renders <Outlet />
|
|
73
|
+
settings/
|
|
74
|
+
theme.tsx /settings/theme its children, in a folder of its name
|
|
75
|
+
item.tsx /item/$id exports its route value (typed params)
|
|
76
|
+
not-found.tsx /$
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
// src/index.tsx
|
|
81
|
+
render(() => (
|
|
82
|
+
<window title="My app">
|
|
83
|
+
<Router initial="/">
|
|
84
|
+
<Route path="/" component={App}>
|
|
85
|
+
<Route path="/" component={Home} />
|
|
86
|
+
<SettingsRoutes />
|
|
87
|
+
<Route route={item} />
|
|
88
|
+
<Route path="/$" component={NotFound} />
|
|
89
|
+
</Route>
|
|
90
|
+
</Router>
|
|
91
|
+
</window>
|
|
92
|
+
))
|
|
93
|
+
|
|
94
|
+
// src/routes/settings.tsx: a section that owns its subtree
|
|
95
|
+
export function SettingsRoutes() {
|
|
96
|
+
return (
|
|
97
|
+
<Route path="/settings" component={Settings}>
|
|
98
|
+
<Route path="/" component={Overview} />
|
|
99
|
+
<Route path="/theme" component={Theme} />
|
|
100
|
+
</Route>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Prefer the JSX tree. The tree as values (`createRouter` at module scope)
|
|
106
|
+
is for code outside the component tree that must reach the router.
|
|
107
|
+
- The file layout is a convention, not a mechanism: a path comes from the
|
|
108
|
+
`path` of its `<Route>` and nothing reads the file system. Name a file
|
|
109
|
+
after the path so a screen is found by its link.
|
|
110
|
+
- index.tsx holds the window and the tree, nothing else. App-wide effects
|
|
111
|
+
(theme, focus navigation) go in `App`; a window prop that changes reads
|
|
112
|
+
state.ts.
|
|
113
|
+
- A screen is one file until it has children; then its children go in a
|
|
114
|
+
folder of its name. While the tree is small, write it whole in index.tsx.
|
|
115
|
+
When a section grows, its file exports a component returning its
|
|
116
|
+
`<Route>` subtree (`SettingsRoutes` above, a fragment for several
|
|
117
|
+
siblings), placed in the tree like a `<Route>`.
|
|
118
|
+
- A screen with typed params defines its `createRoute` value in its own
|
|
119
|
+
file, next to the `useParams(item)` that reads it; index.tsx places it.
|
|
120
|
+
- routes/ holds screens only. Pieces several screens share live beside it.
|
|
121
|
+
- With tabs, the tabs route goes under `App` and its component draws the
|
|
122
|
+
bar.
|
|
123
|
+
|
|
60
124
|
## Traps
|
|
61
125
|
|
|
62
126
|
- A `<Route>` is not an element: it evaluates to a route value. Only
|
|
63
|
-
`<Route>` elements go under `<Router>`
|
|
64
|
-
else there throws at mount.
|
|
127
|
+
`<Route>` elements, or components returning them, go under `<Router>`
|
|
128
|
+
or another `<Route>`; anything else there throws at mount.
|
|
65
129
|
- A route value has one place in one tree: placing it twice (two `<Route
|
|
66
130
|
route={x}>`, or a `children:` list and a `<Route route={x}>`) throws.
|
|
67
131
|
- With a JSX tree the router exists only inside `<Router>`: screens reach
|
|
@@ -71,7 +135,7 @@ let item = createRoute({ // a value: typed pa
|
|
|
71
135
|
screen reads a route only inside a handler or a hook call, never at
|
|
72
136
|
module scope.
|
|
73
137
|
- Route components take no props. State a screen shares with others is a
|
|
74
|
-
module-scope signal (
|
|
138
|
+
module-scope signal (state.ts above), not a prop.
|
|
75
139
|
- A layout route's component must render `<Outlet />` or its child never
|
|
76
140
|
appears; a route without a component is an outlet alone.
|
|
77
141
|
- `<Router>` registers its `onBack` before anything it renders. A dialog
|
|
@@ -93,4 +157,4 @@ let item = createRoute({ // a value: typed pa
|
|
|
93
157
|
`/a/b`) and an http(s) host.
|
|
94
158
|
- Tooling: `open_link` / `POST /__control__/link` opens a screen,
|
|
95
159
|
`get_location` / `GET /__control__/link` reads the path the router
|
|
96
|
-
publishes, `
|
|
160
|
+
publishes, `sol render --link <path>` renders that screen.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`@solidrt/router` makes screens addressable. A route tree maps a path like
|
|
4
4
|
`/settings/theme` to a screen, a stack holds where the app is, and the same
|
|
5
|
-
path is what a link from the OS, an MCP tool, `
|
|
5
|
+
path is what a link from the OS, an MCP tool, `sol render --link` or a saved
|
|
6
6
|
session carries. It is a layer over core: core reports links (`onLink`,
|
|
7
7
|
`env.launchLink`) and the back intent (`onBack`), the router decides what
|
|
8
8
|
they mean. An app can route by hand without it.
|
|
@@ -50,6 +50,62 @@ A `<Route>` is not an element: it evaluates to a route value that its
|
|
|
50
50
|
parent places in the tree, once, when `<Router>` mounts. The router made
|
|
51
51
|
this way is reached through the hooks (`useNavigate`, `useRouter`).
|
|
52
52
|
|
|
53
|
+
## App structure
|
|
54
|
+
|
|
55
|
+
A routed app splits by role, so the entry reads as a map of the app:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
src/
|
|
59
|
+
index.tsx the entry: render(), the window and the route tree
|
|
60
|
+
app.tsx App, the root layout: what stays around every screen
|
|
61
|
+
state.ts module-scope signals the screens share
|
|
62
|
+
routes/
|
|
63
|
+
home.tsx /
|
|
64
|
+
settings.tsx /settings a layout: renders <Outlet />
|
|
65
|
+
settings/
|
|
66
|
+
theme.tsx /settings/theme
|
|
67
|
+
item.tsx /item/$id
|
|
68
|
+
not-found.tsx /$
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The entry holds the window and the tree and nothing else. `App` is the
|
|
72
|
+
outermost layout route (the `Shell` above): the background, the safe area,
|
|
73
|
+
a nav bar, the app-wide effects, around an `<Outlet />`. State that screens
|
|
74
|
+
share is module-scope signals in `state.ts`, since route components take no
|
|
75
|
+
props. Each screen is a file under `routes/`, named after its path; a
|
|
76
|
+
screen with children keeps its file as the layout and gets a folder of the
|
|
77
|
+
same name for them.
|
|
78
|
+
|
|
79
|
+
This is a convention, not a mechanism: a path comes from the `path` of its
|
|
80
|
+
`<Route>`, and nothing reads the file system. Naming the file after the
|
|
81
|
+
path is what lets a screen be found by its link.
|
|
82
|
+
|
|
83
|
+
While the tree is small it is written whole in the entry. When a section
|
|
84
|
+
grows, it can own its subtree: a component that returns `<Route>` elements
|
|
85
|
+
is placed in the tree like a `<Route>` (a fragment returns several
|
|
86
|
+
siblings), so the entry keeps one line per section.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
// src/routes/settings.tsx
|
|
90
|
+
export function SettingsRoutes() {
|
|
91
|
+
return (
|
|
92
|
+
<Route path="/settings" component={Settings}>
|
|
93
|
+
<Route path="/" component={Overview} />
|
|
94
|
+
<Route path="/theme" component={Theme} />
|
|
95
|
+
</Route>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/index.tsx
|
|
100
|
+
<Route path="/" component={App}>
|
|
101
|
+
<Route path="/" component={Home} />
|
|
102
|
+
<SettingsRoutes />
|
|
103
|
+
<Route path="/$" component={NotFound} />
|
|
104
|
+
</Route>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`sol init` with the router selected starts a project in this shape.
|
|
108
|
+
|
|
53
109
|
## Params are validated
|
|
54
110
|
|
|
55
111
|
A path arrives as strings, and from outside the app they are untrusted. A
|
|
@@ -230,9 +286,9 @@ is dropped. A link that matches nothing lands on the catch-all route, or is
|
|
|
230
286
|
ignored with a warning.
|
|
231
287
|
|
|
232
288
|
`<Router>` reports the current path through `reportLocation` from
|
|
233
|
-
`
|
|
289
|
+
`sol:dev`, so `GET /__control__/link` and the `get_location` MCP tool read
|
|
234
290
|
where the app is, and `POST /__control__/link` or `open_link` opens a
|
|
235
|
-
screen directly. `
|
|
291
|
+
screen directly. `sol render --link /settings` renders that screen. A hot
|
|
236
292
|
reload starts the rebuilt app at the path it was on: the runtime hands the
|
|
237
293
|
last reported path to the new run as `env.launchLink`.
|
|
238
294
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidrt/router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.66",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"funding": "https://github.com/sponsors/wellawaretech",
|
|
6
6
|
"author": "Antoine van Wel",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"AGENTS.md"
|
|
16
16
|
],
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"@solidjs/signals": "2.0.0-rc.
|
|
19
|
-
"@solidrt/core": "0.0.
|
|
18
|
+
"@solidjs/signals": "2.0.0-rc.13",
|
|
19
|
+
"@solidrt/core": "0.0.66"
|
|
20
20
|
}
|
|
21
21
|
}
|
package/src/router.tsx
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// navigation, the back step, blocking, links in and the location out, the
|
|
3
3
|
// JSX tree (`<Route>`) and the components that render the matched routes.
|
|
4
4
|
// Everything here is built on what core offers every app (onBack, onLink,
|
|
5
|
-
// env.launchLink, reportLocation from
|
|
5
|
+
// env.launchLink, reportLocation from sol:dev); core knows nothing of routes.
|
|
6
6
|
import { createSignal, createMemo, createContext, createEffect, useContext, untrack, onCleanup, children, Show, For } from "@solidrt/core"
|
|
7
7
|
import { env, onBack, onLink } from "@solidrt/core"
|
|
8
|
-
import { reportLocation } from "
|
|
8
|
+
import { reportLocation } from "sol:dev"
|
|
9
9
|
import { createRootRoute, createRoute, formatPath, linkToPath, matchPath, place } from "./route"
|
|
10
10
|
import type { AnyRoute, Match, ParamsOf, RawParams, Route as RouteValue } from "./route"
|
|
11
11
|
import { back as stepBack, changed, currentPath, findTabs, initialState, push, replace, reset, resolve } from "./stack"
|