@moku-labs/web 2.0.0 → 2.1.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 +45 -0
- package/dist/browser.d.mts +207 -10
- package/dist/browser.mjs +439 -26
- package/dist/index.cjs +439 -25
- package/dist/index.d.cts +207 -10
- package/dist/index.d.mts +207 -10
- package/dist/index.mjs +439 -26
- package/dist/{render-yXHc9BWI.mjs → render-CkdqOmsm.mjs} +7 -1
- package/dist/{render-DHUcHCYs.cjs → render-rf8FAg_Z.cjs} +7 -1
- package/dist/testing.d.mts +36 -1
- package/dist/testing.mjs +18 -3
- package/package.json +3 -3
package/dist/testing.d.mts
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
|
+
//#region src/plugins/router/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Scroll behaviour for a navigation TO a route — a closed, typed vocabulary the SPA
|
|
4
|
+
* kernel interprets (a first-class `.scroll()` method, not a `.meta()` key):
|
|
5
|
+
* - `"top"` — reset to the top of the page on the swap (the default for forward navs);
|
|
6
|
+
* - `"preserve"` — keep the current scroll position (e.g. opening an overlay/issue route
|
|
7
|
+
* over a board that must stay still). A route's `.scroll()` OVERRIDES `spa.scrollRestoration`.
|
|
8
|
+
*/
|
|
9
|
+
type ScrollMode = "top" | "preserve";
|
|
10
|
+
//#endregion
|
|
1
11
|
//#region src/plugins/spa/types.d.ts
|
|
12
|
+
/** Per-navigation options for the programmatic navigators (`ctx.navigate` / `app.spa.navigate`). */
|
|
13
|
+
interface NavigateOptions {
|
|
14
|
+
/** Override the scroll behaviour for this single navigation (else the route/app default). */
|
|
15
|
+
scroll?: ScrollMode;
|
|
16
|
+
}
|
|
2
17
|
/**
|
|
3
18
|
* What a island's `render` may return:
|
|
4
19
|
* - a Preact `VNode` — committed into the host through the lazy Preact gate (`commitVNode`);
|
|
5
20
|
* - a `Node` — replaces the host's children;
|
|
6
21
|
* - a `string` — set as the host's `innerHTML`;
|
|
22
|
+
* - `null` — render NOTHING but stay mountable: the host's Preact tree is unmounted via
|
|
23
|
+
* `render(null, host)` (NOT `innerHTML = ""`), so a later non-empty render re-commits
|
|
24
|
+
* cleanly. This is the correct "empty" for a persistent render-island (e.g. a closed
|
|
25
|
+
* overlay panel) — returning `""` instead corrupts Preact's retained vdom and the panel
|
|
26
|
+
* never re-opens;
|
|
7
27
|
* - `void`/`undefined` — the render mutated the DOM itself (DOM-only islands → no Preact loaded).
|
|
8
28
|
*/
|
|
9
|
-
type RenderResult = AnyVNode | Node | string | void;
|
|
29
|
+
type RenderResult = AnyVNode | Node | string | null | void;
|
|
10
30
|
/**
|
|
11
31
|
* A Preact `VNode` of ANY props shape. A render returns `h(Component, props)`, i.e. a
|
|
12
32
|
* `VNode<SomeProps>`; the props generic is invariant under `exactOptionalPropertyTypes`,
|
|
@@ -92,6 +112,21 @@ interface IslandContext<S = undefined> {
|
|
|
92
112
|
readonly locale: string;
|
|
93
113
|
/** Build a link to a named route by pattern substitution (same output as `app.router.toUrl`). */
|
|
94
114
|
readonly url: (name: string, params?: Record<string, string>) => string;
|
|
115
|
+
/**
|
|
116
|
+
* Programmatically navigate the SPA to an internal path (same swap pipeline as a
|
|
117
|
+
* link click; no-op without a DOM). Build `path` from the route map's `urls`/`ctx.url`,
|
|
118
|
+
* never a literal. Pass `{ scroll: "preserve" }` to keep the current scroll for this nav.
|
|
119
|
+
*
|
|
120
|
+
* An ALWAYS-PRESENT member (like `set`/`flush`/`cleanup`) so every island can navigate
|
|
121
|
+
* without an `app` handle — no synthesized anchor click.
|
|
122
|
+
*
|
|
123
|
+
* @param path - The internal destination path (e.g. `ctx.url("board", { id })`).
|
|
124
|
+
* @param options - Optional per-navigation overrides (e.g. `{ scroll: "preserve" }`).
|
|
125
|
+
* @returns void
|
|
126
|
+
* @example
|
|
127
|
+
* ctx.navigate(ctx.url("issue", { id, issueId }));
|
|
128
|
+
*/
|
|
129
|
+
readonly navigate: (path: string, options?: NavigateOptions) => void;
|
|
95
130
|
/** The live per-instance state (the object returned by `spec.state`). `undefined` for legacy hooks-only islands. */
|
|
96
131
|
readonly state: S;
|
|
97
132
|
/**
|
package/dist/testing.mjs
CHANGED
|
@@ -62,13 +62,15 @@ let commitVNodeFunction;
|
|
|
62
62
|
* await loadRenderChunk();
|
|
63
63
|
*/
|
|
64
64
|
async function loadRenderChunk() {
|
|
65
|
-
renderChunk ??= import("./render-
|
|
65
|
+
renderChunk ??= import("./render-CkdqOmsm.mjs");
|
|
66
66
|
commitVNodeFunction = (await renderChunk).commitVNode;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Commit a {@link RenderResult} into a host: `string` → `innerHTML`, `Node` →
|
|
70
|
-
* `replaceChildren`, `
|
|
71
|
-
*
|
|
70
|
+
* `replaceChildren`, `null` → Preact unmount via the lazy gate (`render(null, host)` —
|
|
71
|
+
* stays re-mountable, the correct "empty" for a persistent render-island), `void`/`undefined`
|
|
72
|
+
* → no-op (the render mutated the DOM itself), and a Preact `VNode` → committed through the
|
|
73
|
+
* lazy gate (loading it on demand if needed).
|
|
72
74
|
*
|
|
73
75
|
* @param host - The island host element to render into.
|
|
74
76
|
* @param result - The value returned by the island's `render`.
|
|
@@ -195,6 +197,18 @@ function buildContext(state, instance) {
|
|
|
195
197
|
return instance.route.url;
|
|
196
198
|
},
|
|
197
199
|
/**
|
|
200
|
+
* Programmatically navigate the SPA (delegates to the kernel's navigator through
|
|
201
|
+
* `state.navigate` — the same decoupled seam as `island`). No-op before the kernel binds.
|
|
202
|
+
*
|
|
203
|
+
* @param path - The internal destination path.
|
|
204
|
+
* @param options - Optional per-navigation overrides (e.g. `{ scroll: "preserve" }`).
|
|
205
|
+
* @example
|
|
206
|
+
* ctx.navigate(ctx.url("issue", { id, issueId }));
|
|
207
|
+
*/
|
|
208
|
+
navigate(path, options) {
|
|
209
|
+
state.navigate?.(path, options);
|
|
210
|
+
},
|
|
211
|
+
/**
|
|
198
212
|
* The live per-instance state (`undefined` for legacy hooks-only islands).
|
|
199
213
|
*
|
|
200
214
|
* @returns The current state.
|
|
@@ -552,6 +566,7 @@ function createState(_ctx) {
|
|
|
552
566
|
currentUrl: "",
|
|
553
567
|
destroyRouter: null,
|
|
554
568
|
started: false,
|
|
569
|
+
navigate: null,
|
|
555
570
|
kernel: null
|
|
556
571
|
};
|
|
557
572
|
}
|
package/package.json
CHANGED
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"bun": ">=1.3.14"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@moku-labs/common": "0.2.
|
|
68
|
-
"@moku-labs/core": "
|
|
67
|
+
"@moku-labs/common": "0.2.1",
|
|
68
|
+
"@moku-labs/core": "1.5.0",
|
|
69
69
|
"@resvg/resvg-js": "2.6.2",
|
|
70
70
|
"@shikijs/rehype": "3.22.0",
|
|
71
71
|
"feed": "5.2.0",
|
|
@@ -132,5 +132,5 @@
|
|
|
132
132
|
"test:build-e2e": "bun test src/plugins/build/__tests__/e2e/",
|
|
133
133
|
"test:coverage": "vitest run --project unit --project integration --coverage"
|
|
134
134
|
},
|
|
135
|
-
"version": "2.
|
|
135
|
+
"version": "2.1.0"
|
|
136
136
|
}
|