@weftui/core 0.28.0 → 0.30.0
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 +8 -8
- package/dist/{index-Bsh2WLtx.d.ts → index-CX9uEejU.d.ts} +70 -51
- package/dist/index.d.ts +68 -119
- package/dist/index.js +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/explanation/boundaries-and-suspense.md +39 -20
- package/docs/explanation/combinator-api.md +14 -12
- package/docs/explanation/reactive-primitives.md +14 -14
- package/docs/explanation/rendering-model.md +20 -18
- package/docs/explanation/services-and-context.md +35 -21
- package/docs/how-to/add-routing.md +361 -60
- package/docs/how-to/author-components.md +42 -30
- package/docs/how-to/compose-behavior-and-markup.md +144 -0
- package/docs/how-to/handle-forms.md +6 -6
- package/docs/how-to/load-async-data.md +15 -13
- package/docs/how-to/load-data-with-rpc.md +34 -32
- package/docs/how-to/provide-services.md +20 -18
- package/docs/how-to/render-keyed-lists.md +14 -12
- package/docs/how-to/render-on-the-server.md +18 -14
- package/docs/how-to/show-navigation-progress.md +12 -10
- package/docs/how-to/split-routes-lazily.md +16 -14
- package/docs/how-to/style-reactively.md +13 -13
- package/docs/how-to/use-element-refs.md +10 -8
- package/docs/index.md +20 -18
- package/docs/reference/core.md +46 -42
- package/docs/reference/dom.md +274 -58
- package/docs/reference/router.md +69 -47
- package/docs/tutorial/01-your-first-app.md +7 -9
- package/docs/tutorial/02-reactivity.md +8 -6
- package/docs/tutorial/03-services-and-async.md +10 -6
- package/docs/tutorial/04-errors-and-server.md +14 -5
- package/package.json +2 -2
package/docs/reference/core.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "@weftui/core"
|
|
3
3
|
order: 1
|
|
4
4
|
section: reference
|
|
5
|
-
description: Full API surface for @weftui/core
|
|
5
|
+
description: "Full API surface for @weftui/core: element builders, components, sources, streams, and boundaries."
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# @weftui/core API Reference
|
|
@@ -52,7 +52,7 @@ Use when a component needs to return multiple sibling elements.
|
|
|
52
52
|
|
|
53
53
|
### `Component`
|
|
54
54
|
|
|
55
|
-
Namespace exposing two factories for reusable components with caller-propagating reactive prop types: `Component.gen` (generator body) and `Component.make` (plain-function body). Both return a callable that is generic over the caller's specific `props`/`children
|
|
55
|
+
Namespace exposing two factories for reusable components with caller-propagating reactive prop types: `Component.gen` (generator body) and `Component.make` (plain-function body). Both return a callable that is generic over the caller's specific `props`/`children`. Reactive prop values and reactive children therefore contribute their `E`/`R` at the call site.
|
|
56
56
|
|
|
57
57
|
```typescript
|
|
58
58
|
import { Component } from "@weftui/core";
|
|
@@ -69,7 +69,7 @@ Component.make<BaseProps, C>(
|
|
|
69
69
|
): /* same call signature as above */;
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
**`Children
|
|
72
|
+
**`Children`**: the optional `children` argument may be either form:
|
|
73
73
|
|
|
74
74
|
```typescript
|
|
75
75
|
type Component.Children<Input = never> =
|
|
@@ -79,7 +79,7 @@ type Component.Children<Input = never> =
|
|
|
79
79
|
|
|
80
80
|
For function-children, `ChildrenE`/`ChildrenR` are extracted from the function's `ReturnType`, not from the function itself. The component's body invokes the function with whatever input it chooses.
|
|
81
81
|
|
|
82
|
-
**Example
|
|
82
|
+
**Example: `Component.gen`**
|
|
83
83
|
|
|
84
84
|
```typescript
|
|
85
85
|
interface TextFieldProps {
|
|
@@ -96,7 +96,7 @@ const TextField = Component.gen(function* (props: TextFieldProps) {
|
|
|
96
96
|
});
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
**Example
|
|
99
|
+
**Example: `Component.make` with function-children**
|
|
100
100
|
|
|
101
101
|
```typescript
|
|
102
102
|
const Labeled = Component.make(
|
|
@@ -108,17 +108,17 @@ Labeled({ label: "Name" }, (label) => [h.label(label), h.input()]);
|
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
> For rendering a reactive collection, reach for the built-in [`List.each`](#listeach)
|
|
111
|
-
> rather than mapping items by hand
|
|
111
|
+
> rather than mapping items by hand. It reconciles by key across emissions instead of
|
|
112
112
|
> rebuilding the region.
|
|
113
113
|
|
|
114
114
|
### `Boundary` namespace
|
|
115
115
|
|
|
116
|
-
Variants for intercepting rendering-path errors in a subtree, plus `Boundary.suspend` for async fallbacks and `Boundary.rpc` for rpc-backed server data. Each returns a descriptor that the renderer processes via the same `{ type, props }` branch. The catch variants share the same call shape
|
|
116
|
+
Variants for intercepting rendering-path errors in a subtree, plus `Boundary.suspend` for async fallbacks and `Boundary.rpc` for rpc-backed server data. Each returns a descriptor that the renderer processes via the same `{ type, props }` branch. The catch variants share the same call shape: props first, children array second.
|
|
117
117
|
|
|
118
118
|
**What is caught:**
|
|
119
119
|
|
|
120
|
-
- Construction-time failures
|
|
121
|
-
- Post-mount stream failures
|
|
120
|
+
- Construction-time failures: the Effect phase of building child nodes
|
|
121
|
+
- Post-mount stream failures: streams driving children or prop values that fail after mount
|
|
122
122
|
|
|
123
123
|
**What is NOT caught:** event handler errors (they run in detached fibers outside the render path).
|
|
124
124
|
|
|
@@ -144,7 +144,9 @@ Boundary.suspend(
|
|
|
144
144
|
|
|
145
145
|
#### `Boundary.rpc`
|
|
146
146
|
|
|
147
|
-
A universal server/client render boundary backed by one `Rpc` from the app's merged `RpcGroup` ([`effect/unstable/rpc`](https://github.com/Effect-TS/effect)). The rpc **`_tag`** is the boundary's stable identity and its **payload schema** the typed input
|
|
147
|
+
A universal server/client render boundary backed by one `Rpc` from the app's merged `RpcGroup` ([`effect/unstable/rpc`](https://github.com/Effect-TS/effect)). The rpc **`_tag`** is the boundary's stable identity and its **payload schema** the typed input. The handler lives in the server-only rpc Layer (`group.toLayer(...)`), which the client never imports: tree-shaking does the client/server split structurally.
|
|
148
|
+
|
|
149
|
+
Unlike the catch variants it takes a `render` function, not a children array. That `render` receives a reactive [`Resource`](#resourcea), not a bare value.
|
|
148
150
|
|
|
149
151
|
```typescript
|
|
150
152
|
Boundary.rpc<R extends Rpc.Any, C extends Node<any, any>>(
|
|
@@ -157,27 +159,27 @@ Boundary.rpc<R extends Rpc.Any, C extends Node<any, any>>(
|
|
|
157
159
|
|
|
158
160
|
The boundary resolves the rpc through the ambient [`AppRpcClientTag`](#apprpcclienttag) seam, provided by `@weftui/router` (`RouterServer` on the server, `RouterLive` on the client). It has four lifecycles:
|
|
159
161
|
|
|
160
|
-
- **SSR:** the server resolves the rpc in-process (over the handler Layer), `successSchema`-encodes the result inline as `<script type="application/json">` at the region cursor
|
|
161
|
-
- **Hydrate:** `hydrate` reads the inline payload positionally, `successSchema`-decodes it, seeds the `Resource`, and adopts the DOM
|
|
162
|
-
- **Refetch:** `resource.refetch` calls the rpc again over the network (`POST /_eui/rpc`) and patches the subtree in place
|
|
162
|
+
- **SSR:** the server resolves the rpc in-process (over the handler Layer), `successSchema`-encodes the result inline as `<script type="application/json">` at the region cursor. It then renders `render(seededResource)` to HTML in place.
|
|
163
|
+
- **Hydrate:** `hydrate` reads the inline payload positionally, `successSchema`-decodes it, seeds the `Resource`, and adopts the DOM. It **never re-calls the rpc** (replay, not refetch).
|
|
164
|
+
- **Refetch:** `resource.refetch` calls the rpc again over the network (`POST /_eui/rpc`) and patches the subtree in place. **Stale-on-error**: a failed refetch leaves the previous value intact.
|
|
163
165
|
- **Client-first mount:** SPA-navigating into a boundary with **no** SSR payload renders `options.fallback`, forks the rpc call, and swaps in `render(resource)` once it resolves.
|
|
164
166
|
|
|
165
|
-
**Channel algebra:** the output `E` is `render`'s error union plus the rpc's typed `Rpc.Error<R>` (`never` for an rpc with no `error` schema). The output `R` is **exactly** `render`'s `R`, untouched
|
|
167
|
+
**Channel algebra:** the output `E` is `render`'s error union plus the rpc's typed `Rpc.Error<R>` (`never` for an rpc with no `error` schema). The output `R` is **exactly** `render`'s `R`, untouched. There is no `provide`/`RServer` to discharge (the handler lives in the rpc Layer) and **no `Exclude`** is applied. A server-only tag accidentally referenced in `render` therefore stays in `R`, where `hydrate`'s `AssertNoServerOnly` rejects it. Brand such services with [`ServerTag`](#servertag).
|
|
166
168
|
|
|
167
|
-
**Typed-failure replay:** a resolved rpc **error** on the SSR pass is `errorSchema`-encoded and relocated to the nearest enclosing failure `Boundary
|
|
169
|
+
**Typed-failure replay:** a resolved rpc **error** on the SSR pass is `errorSchema`-encoded and relocated to the nearest enclosing failure `Boundary`. It is then replayed on the client: decoded and re-raised, reproducing the same fallback DOM (never retried). A transport **defect**, or an rpc with no `error` schema, is not replayed; it propagates.
|
|
168
170
|
|
|
169
171
|
> **Not yet covered:** streamed success (`Rpc.make(..., { stream: true })`) and mutations are on the roadmap, not this pass.
|
|
170
172
|
|
|
171
173
|
##### `Resource<A>`
|
|
172
174
|
|
|
173
|
-
The reactive handle `render` receives (`A = Rpc.Success<R>`). After hydrate the region is live: `value` is seeded with the SSR payload
|
|
175
|
+
The reactive handle `render` receives (`A = Rpc.Success<R>`). After hydrate the region is live: `value` is seeded with the SSR payload. The client can `refetch` the same data on demand, patching the rendered subtree in place.
|
|
174
176
|
|
|
175
|
-
| Field | Type | Meaning
|
|
176
|
-
| --------- | -------------------------------------------- |
|
|
177
|
-
| `value` | `Subscribable.Subscribable<A>` | Current data. Seeded with the SSR `data` (await-first, emits immediately, so SSR HTML and adopted DOM are byte-identical
|
|
178
|
-
| `refetch` | `Effect.Effect<void>` | Re-resolves the rpc over the network with a fresh `payload()` and sets `value`. Client only
|
|
179
|
-
| `pending` | `Subscribable.Subscribable<boolean>` | `true` while a refetch is in flight (`false` on the server / before any refetch).
|
|
180
|
-
| `error` | `Subscribable.Subscribable<Option<unknown>>` | `Some` with the last refetch error, else `None`. A failed refetch is stale-on-error
|
|
177
|
+
| Field | Type | Meaning |
|
|
178
|
+
| --------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
179
|
+
| `value` | `Subscribable.Subscribable<A>` | Current data. Seeded with the SSR `data` (await-first, emits immediately, so SSR HTML and adopted DOM are byte-identical, no fallback flash). A successful refetch pushes the new value. |
|
|
180
|
+
| `refetch` | `Effect.Effect<void>` | Re-resolves the rpc over the network with a fresh `payload()` and sets `value`. Client only, a no-op on the server. |
|
|
181
|
+
| `pending` | `Subscribable.Subscribable<boolean>` | `true` while a refetch is in flight (`false` on the server / before any refetch). |
|
|
182
|
+
| `error` | `Subscribable.Subscribable<Option<unknown>>` | `Some` with the last refetch error, else `None`. A failed refetch is stale-on-error: it does **not** unmount or raise into a failure `Boundary`. |
|
|
181
183
|
|
|
182
184
|
##### `RpcOptions`
|
|
183
185
|
|
|
@@ -206,7 +208,9 @@ class AppRpcClientTag extends Context.Service<AppRpcClientTag, AppRpcClient>()(
|
|
|
206
208
|
) {}
|
|
207
209
|
```
|
|
208
210
|
|
|
209
|
-
The ambient, package-neutral seam the renderer resolves a `Boundary.rpc` through
|
|
211
|
+
The ambient, package-neutral seam the renderer resolves a `Boundary.rpc` through: a **flat, untyped** caller `(tag, payload) => Effect<success>`. It lets `@weftui/dom` resolve a boundary without importing `effect/unstable/rpc` or `@weftui/router`. `@weftui/router` provides it: a **network** `RpcClient` (POST `/_eui/rpc`) in the browser, an **in-process** client over the handler Layer on the server.
|
|
212
|
+
|
|
213
|
+
`call` returns the already-decoded success; the renderer owns `successSchema`/`errorSchema` decoding of the inline SSR payload only. Both `AppRpcClientTag` and the `AppRpcClient` type are re-exported from `@weftui/core`. Absent in a router-less mount, where a `Boundary.rpc` resolves to a descriptive "needs router/rpc" error (not a defect).
|
|
210
214
|
|
|
211
215
|
See the [rpc data boundaries guide](https://weftui.dev/docs/how-to/load-data-with-rpc) and [examples/router-ssr](https://github.com/stefvw93/weft/tree/main/examples/router-ssr).
|
|
212
216
|
|
|
@@ -267,7 +271,9 @@ Boundary.catchTags<C, Handlers>(
|
|
|
267
271
|
|
|
268
272
|
#### `Boundary.catchFilter`
|
|
269
273
|
|
|
270
|
-
Conditionally catches using a `Filter`, run on each typed failure
|
|
274
|
+
Conditionally catches using a `Filter`, run on each typed failure. A `Result.succeed` (pass) recovers via `fallback`, receiving the possibly-narrowed pass value. A `Result.fail` re-raises the error; its `Fail` channel `X` is preserved in the output `E`, since the boundary may not handle any given error.
|
|
275
|
+
|
|
276
|
+
Takes the `Filter` and `fallback` as **positional** arguments (no wrapping props object). Mirrors Effect 4's `Effect.catchFilter` (renamed from `catchSome`, which took an `Option`-returning function in v3).
|
|
271
277
|
|
|
272
278
|
```typescript
|
|
273
279
|
Boundary.catchFilter<C, EB, X, FE, FR>(
|
|
@@ -288,8 +294,6 @@ Boundary.catchFilter(
|
|
|
288
294
|
);
|
|
289
295
|
```
|
|
290
296
|
|
|
291
|
-
The children's `E` is narrowed to the filter's `Fail` channel `X` in the output, because the boundary may or may not handle any given error.
|
|
292
|
-
|
|
293
297
|
#### `Boundary.catchIf`
|
|
294
298
|
|
|
295
299
|
A predicate gates the fallback. `false` re-raises.
|
|
@@ -308,7 +312,7 @@ Boundary.catchIf<C, FE, FR>(
|
|
|
308
312
|
|
|
309
313
|
When a boundary's `match` returns `null` (unmatched error), the error propagates to the nearest **parent** `Boundary` via `BoundaryContext`. If there is no parent boundary, the error fails the enclosing mount.
|
|
310
314
|
|
|
311
|
-
Inner boundaries shadow outer ones for their subtree
|
|
315
|
+
Inner boundaries shadow outer ones for their subtree: the innermost boundary is always tried first.
|
|
312
316
|
|
|
313
317
|
```typescript
|
|
314
318
|
// Inner catches FooError; BarError propagates to outer
|
|
@@ -323,7 +327,7 @@ Boundary.catch({ fallback: (e) => h.div(`Outer: ${e.message}`) }, [
|
|
|
323
327
|
|
|
324
328
|
## ServerTag
|
|
325
329
|
|
|
326
|
-
A `Context.Service` key whose identifier is branded server-only. Use it exactly like `Context.Service` for services that must only ever be provided on the server
|
|
330
|
+
A `Context.Service` key whose identifier is branded server-only. Use it exactly like `Context.Service` for services that must only ever be provided on the server (e.g. a database handle read inside an rpc handler Layer). The brand also guards [`Boundary.rpc`](#boundaryrpc): a server-only tag accidentally referenced in `render` stays in the requirement channel, where `hydrate`'s `AssertNoServerOnly` rejects it at compile time.
|
|
327
331
|
|
|
328
332
|
```typescript
|
|
329
333
|
import { ServerTag } from "@weftui/core";
|
|
@@ -336,8 +340,8 @@ class Database extends ServerTag("Database")<
|
|
|
336
340
|
```
|
|
337
341
|
|
|
338
342
|
- The server-only brand rides along in the requirement channel `R` of any effect that uses the tag.
|
|
339
|
-
- An rpc handler Layer (`group.toLayer(...)`) discharges it on the server, where it is provided
|
|
340
|
-
- If a branded tag ever reaches client code
|
|
343
|
+
- An rpc handler Layer (`group.toLayer(...)`) discharges it on the server, where it is provided. It never enters a [`Boundary.rpc`](#boundaryrpc)'s output `R`, since `render` only reads the decoded result.
|
|
344
|
+
- If a branded tag ever reaches client code (referenced in `render` and surviving into `hydrate`'s requirement channel), `AssertNoServerOnly` resolves `R` to a compile-error sentinel (`ServerOnlyLeak`). The failure surfaces at the `hydrate` call site, not silently at runtime.
|
|
341
345
|
|
|
342
346
|
`ServerOnly`, `ServerOnlyLeak`, and `AssertNoServerOnly<R>` are exported alongside `ServerTag` for advanced typing; most code only needs `ServerTag` itself.
|
|
343
347
|
|
|
@@ -347,16 +351,16 @@ class Database extends ServerTag("Database")<
|
|
|
347
351
|
|
|
348
352
|
### `List` namespace
|
|
349
353
|
|
|
350
|
-
The keyed-list combinator. It is the opt-in alternative to wholesale child rebuilds: items are rendered **once per key** and reconciled across emissions
|
|
354
|
+
The keyed-list combinator. It is the opt-in alternative to wholesale child rebuilds: items are rendered **once per key** and reconciled across emissions. Reordering, inserting, or removing items therefore reuses and moves existing DOM rather than rebuilding the region.
|
|
351
355
|
|
|
352
356
|
> **Note:** This exported `List` namespace is the built-in, key-reconciling way to
|
|
353
|
-
> render collections
|
|
357
|
+
> render collections. Prefer it over hand-rolling a component that maps items into
|
|
354
358
|
> elements.
|
|
355
359
|
|
|
356
360
|
```typescript
|
|
357
|
-
import { h, List } from "@weftui/core";
|
|
361
|
+
import { h, List, Subscribable } from "@weftui/core";
|
|
358
362
|
|
|
359
|
-
h.ul([List.each({ of:
|
|
363
|
+
h.ul([List.each({ of: Subscribable.changes(rows), by: (row) => row.id }, (row) => h.li(row.name))]);
|
|
360
364
|
```
|
|
361
365
|
|
|
362
366
|
#### `List.each`
|
|
@@ -372,7 +376,7 @@ List.each<S extends Source.Source<Iterable<any>, any, any>, CE, CR, K>(
|
|
|
372
376
|
|
|
373
377
|
`render` runs **once per key**; a persisted key keeps its DOM nodes and its running subscription fibers across re-emits (it is never re-invoked). The returned node's `E`/`R` are the union of the source channels and the channels of the node `render` returns.
|
|
374
378
|
|
|
375
|
-
> **⚠️ Render-once / index-key footgun:** because `render` runs exactly once per key, reconciliation never refreshes a kept row's content
|
|
379
|
+
> **⚠️ Render-once / index-key footgun:** because `render` runs exactly once per key, reconciliation never refreshes a kept row's content. Refresh a row by threading a `Stream` **inside** it, not by re-running `render`. Keying by index (`by: (_, i) => i`) reuses rows positionally and will show stale content after a reorder. Prefer a stable identity key (`by: (item) => item.id`).
|
|
376
380
|
|
|
377
381
|
**`List.Options<S, K>`**
|
|
378
382
|
|
|
@@ -383,8 +387,8 @@ interface List.Options<S, K> {
|
|
|
383
387
|
}
|
|
384
388
|
```
|
|
385
389
|
|
|
386
|
-
- **`of
|
|
387
|
-
- **`by
|
|
390
|
+
- **`of`**: the list source. Each emission is materialized to an array to fix order, then reconciled by key.
|
|
391
|
+
- **`by`**: projects each item to its reconciliation key. Omitted ⇒ the item itself is the key (structural for `Data`, by reference otherwise).
|
|
388
392
|
|
|
389
393
|
#### `List.Error<N>` and `List.Context<N>`
|
|
390
394
|
|
|
@@ -435,7 +439,7 @@ Normalization rules:
|
|
|
435
439
|
- **`Effect`** → memoized via `Effect.cached`; `changes` emits the resolved value once
|
|
436
440
|
- **`Stream`** → forks a scoped pump fiber that drains into a `SubscriptionRef`; `get` awaits the first emission
|
|
437
441
|
|
|
438
|
-
The pump fiber is tied to the enclosing scope via `Effect.forkScoped
|
|
442
|
+
The pump fiber is tied to the enclosing scope via `Effect.forkScoped`. It terminates when the scope closes.
|
|
439
443
|
|
|
440
444
|
### `NoPropValue`
|
|
441
445
|
|
|
@@ -458,7 +462,7 @@ type PropsE<P> = { [K in keyof P]: P[K] extends Stream.Stream<any, infer E, any>
|
|
|
458
462
|
type PropsR<P> = { [K in keyof P]: P[K] extends Stream.Stream<any, any, infer R> ? R : ... }[keyof P]
|
|
459
463
|
```
|
|
460
464
|
|
|
461
|
-
These are used internally by `h` and `Component` to accumulate channels from props.
|
|
465
|
+
These are used internally by `h` and `Component` to accumulate channels from props. Reference them directly only when building utilities over the combinator API.
|
|
462
466
|
|
|
463
467
|
---
|
|
464
468
|
|
|
@@ -466,7 +470,7 @@ These are used internally by `h` and `Component` to accumulate channels from pro
|
|
|
466
470
|
|
|
467
471
|
### `FRAGMENT`
|
|
468
472
|
|
|
469
|
-
Internal brand used to mark fragment nodes. Not intended for direct use
|
|
473
|
+
Internal brand used to mark fragment nodes. Not intended for direct use; use `h.fragment` instead.
|
|
470
474
|
|
|
471
475
|
---
|
|
472
476
|
|
|
@@ -502,6 +506,6 @@ isSubscribable(value: unknown): value is Subscribable<unknown, unknown, unknown>
|
|
|
502
506
|
|
|
503
507
|
## See also
|
|
504
508
|
|
|
505
|
-
- [The Combinator API](https://weftui.dev/docs/explanation/combinator-api) · [Reactive Primitives](https://weftui.dev/docs/explanation/reactive-primitives) · [Boundaries and Suspense](https://weftui.dev/docs/explanation/boundaries-and-suspense)
|
|
506
|
-
- [Author Components](https://weftui.dev/docs/how-to/author-components) · [Render Keyed Lists](https://weftui.dev/docs/how-to/render-keyed-lists)
|
|
509
|
+
- [The Combinator API](https://weftui.dev/docs/explanation/combinator-api) · [Reactive Primitives](https://weftui.dev/docs/explanation/reactive-primitives) · [Boundaries and Suspense](https://weftui.dev/docs/explanation/boundaries-and-suspense): the concepts behind this surface
|
|
510
|
+
- [Author Components](https://weftui.dev/docs/how-to/author-components) · [Render Keyed Lists](https://weftui.dev/docs/how-to/render-keyed-lists): task guides that use it
|
|
507
511
|
- [`@weftui/dom` reference](https://weftui.dev/docs/reference/dom) · [`@weftui/router` reference](https://weftui.dev/docs/reference/router)
|