@llui/vike 0.0.15 → 0.0.16
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 +162 -7
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/on-render-client.d.ts +97 -51
- package/dist/on-render-client.d.ts.map +1 -1
- package/dist/on-render-client.js +235 -52
- package/dist/on-render-client.js.map +1 -1
- package/dist/on-render-html.d.ts +45 -15
- package/dist/on-render-html.d.ts.map +1 -1
- package/dist/on-render-html.js +119 -20
- package/dist/on-render-html.js.map +1 -1
- package/dist/page-slot.d.ts +63 -0
- package/dist/page-slot.d.ts.map +1 -0
- package/dist/page-slot.js +77 -0
- package/dist/page-slot.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -57,6 +57,160 @@ export const onRenderClient = createOnRenderClient({
|
|
|
57
57
|
})
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
### Persistent Layouts
|
|
61
|
+
|
|
62
|
+
Declare app chrome (header, sidebar, dialogs, session state) as a `Layout` component that stays mounted across client navigation. The route-scoped `Page` swaps in and out at the layout's `pageSlot()` position while the surrounding layout subtree — and every DOM node, focus trap, portal, and effect subscription inside it — is untouched.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// pages/+Layout.ts
|
|
66
|
+
import { component, div, header, main } from '@llui/dom'
|
|
67
|
+
import { pageSlot } from '@llui/vike/client'
|
|
68
|
+
|
|
69
|
+
export const AppLayout = component<LayoutState, LayoutMsg>({
|
|
70
|
+
name: 'AppLayout',
|
|
71
|
+
init: () => [{ session: null }, []],
|
|
72
|
+
update: layoutUpdate,
|
|
73
|
+
view: ({ send }) => [
|
|
74
|
+
div({ class: 'app-shell' }, [
|
|
75
|
+
header([
|
|
76
|
+
/* persistent chrome */
|
|
77
|
+
]),
|
|
78
|
+
main([pageSlot()]), // ← where the route's Page renders
|
|
79
|
+
]),
|
|
80
|
+
],
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// pages/+onRenderClient.ts
|
|
86
|
+
import { createOnRenderClient } from '@llui/vike/client'
|
|
87
|
+
import { AppLayout } from './+Layout'
|
|
88
|
+
|
|
89
|
+
export const onRenderClient = createOnRenderClient({
|
|
90
|
+
Layout: AppLayout,
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// pages/+onRenderHtml.ts — server renders layout + page as one tree
|
|
96
|
+
import { createOnRenderHtml } from '@llui/vike/server'
|
|
97
|
+
import { AppLayout } from './+Layout'
|
|
98
|
+
|
|
99
|
+
export const onRenderHtml = createOnRenderHtml({
|
|
100
|
+
Layout: AppLayout,
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Call `pageSlot()` exactly once in each layout's view, at the position where nested content should render. It's an ordinary structural primitive — composes naturally inside `show()`, `branch()`, `provide()`, and any other view tree.
|
|
105
|
+
|
|
106
|
+
#### Nested layouts
|
|
107
|
+
|
|
108
|
+
Pass an array to stack layouts outer-to-inner. Each layout except the innermost calls its own `pageSlot()`. The innermost layer is always the route's `Page`.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
createOnRenderClient({
|
|
112
|
+
Layout: [AppLayout, DashboardLayout],
|
|
113
|
+
})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For per-route chains — e.g. `/dashboard/*` routes use `[AppLayout, DashboardLayout]` while `/settings` uses `[AppLayout]` — pass a resolver function instead:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
createOnRenderClient({
|
|
120
|
+
Layout: (pageContext) =>
|
|
121
|
+
pageContext.urlPathname.startsWith('/dashboard') ? [AppLayout, DashboardLayout] : [AppLayout],
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The chain diff on each nav walks old and new chains in parallel and finds the first mismatch. Every layer before that mismatch stays mounted; every layer at or after it is torn down innermost-first and re-mounted outermost-first. Navigating from `/dashboard/reports` to `/dashboard/overview` only disposes the `Page` — `AppLayout` and `DashboardLayout` stay alive. Navigating to `/settings` disposes `DashboardLayout` and the `Page`, keeping only `AppLayout`.
|
|
126
|
+
|
|
127
|
+
#### Layout ↔ Page communication
|
|
128
|
+
|
|
129
|
+
Layouts and pages are independent component instances with their own state, update, and `send`. They share state and expose cross-cutting operations via **context**, not via direct messaging.
|
|
130
|
+
|
|
131
|
+
The scope-tree integration makes this natural: `pageSlot()` creates its slot as a child of the layout's render scope, and the page's `rootScope` is parented inside that slot. `useContext` from within the page walks up through the slot and finds any providers the layout installed above it.
|
|
132
|
+
|
|
133
|
+
Common pattern — a layout-owned toast system:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// pages/+Layout.ts
|
|
137
|
+
import { component, div, main, provide, createContext } from '@llui/dom'
|
|
138
|
+
import { pageSlot } from '@llui/vike/client'
|
|
139
|
+
|
|
140
|
+
interface ToastDispatchers {
|
|
141
|
+
show: (msg: string) => void
|
|
142
|
+
dismiss: (id: string) => void
|
|
143
|
+
}
|
|
144
|
+
export const ToastContext = createContext<ToastDispatchers>(undefined, 'Toast')
|
|
145
|
+
|
|
146
|
+
export const AppLayout = component<LayoutState, LayoutMsg>({
|
|
147
|
+
name: 'AppLayout',
|
|
148
|
+
init: () => [{ toasts: [] }, []],
|
|
149
|
+
update: layoutUpdate,
|
|
150
|
+
view: ({ send }) => [
|
|
151
|
+
div({ class: 'app-shell' }, [
|
|
152
|
+
ToastStack(), // reads from layout state
|
|
153
|
+
...provide(
|
|
154
|
+
ToastContext,
|
|
155
|
+
() => ({
|
|
156
|
+
show: (msg) => send({ type: 'toast/show', msg }),
|
|
157
|
+
dismiss: (id) => send({ type: 'toast/dismiss', id }),
|
|
158
|
+
}),
|
|
159
|
+
() => [main([pageSlot()])],
|
|
160
|
+
),
|
|
161
|
+
]),
|
|
162
|
+
],
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
// Any page below the layout can now use the toast dispatcher.
|
|
168
|
+
// pages/studio/+Page.ts
|
|
169
|
+
import { component, button, text, useContext } from '@llui/dom'
|
|
170
|
+
import { ToastContext } from '../+Layout'
|
|
171
|
+
|
|
172
|
+
export const StudioPage = component<StudioState, StudioMsg>({
|
|
173
|
+
name: 'StudioPage',
|
|
174
|
+
init: () => [{ saved: false }, []],
|
|
175
|
+
update: (s, m) => {
|
|
176
|
+
if (m.type === 'saveSucceeded') {
|
|
177
|
+
// ...
|
|
178
|
+
}
|
|
179
|
+
return [s, []]
|
|
180
|
+
},
|
|
181
|
+
view: ({ send }) => {
|
|
182
|
+
const toast = useContext(ToastContext)
|
|
183
|
+
return [button({ onClick: () => toast({} as LayoutState).show('Saved') }, [text('Save')])]
|
|
184
|
+
},
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Toast state machines, global progress indicators, breadcrumb/title bars, modal-takeover chrome toggles, and session-expired banners all fall out of this pattern naturally — the layout owns the state, provides a dispatcher via context, and any page can trigger layout operations without touching the layout's internals.
|
|
189
|
+
|
|
190
|
+
For the rarer case where a layout needs to **probe a page** (e.g. "is your form dirty? can we navigate away?"), use **addressed effects** — the page registers an address on mount, the layout dispatches a targeted effect to it.
|
|
191
|
+
|
|
192
|
+
#### Layout data
|
|
193
|
+
|
|
194
|
+
Layouts can have their own server-fetched data alongside per-page `+data.ts` by populating `pageContext.lluiLayoutData` as an array matching the layout chain (outermost first). Each layout's `init(layoutData)` receives its slice.
|
|
195
|
+
|
|
196
|
+
Wire this from Vike's config mechanism however you like — the adapter just reads `pageContext.lluiLayoutData` when present.
|
|
197
|
+
|
|
198
|
+
#### Hydration envelope
|
|
199
|
+
|
|
200
|
+
With a `Layout` configured, `window.__LLUI_STATE__` is chain-aware:
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
window.__LLUI_STATE__ = {
|
|
204
|
+
layouts: [
|
|
205
|
+
{ name: 'AppLayout', state: { session: 'alice' } },
|
|
206
|
+
{ name: 'DashboardLayout', state: { active: 'reports' } },
|
|
207
|
+
],
|
|
208
|
+
page: { name: 'ReportsPage', state: { view: 'summary' } },
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The client matches each layer by component `name` when hydrating — server/client chain mismatches throw with a clear error instead of silently binding the wrong state to the wrong instance. Pages written against the pre-layout flat envelope shape continue to hydrate correctly when no `Layout` is configured.
|
|
213
|
+
|
|
60
214
|
### Page Transitions
|
|
61
215
|
|
|
62
216
|
`createOnRenderClient` accepts `onLeave` and `onEnter` hooks that fire around the dispose-and-remount cycle on client navigation. `onLeave` is awaited — return a promise to defer the swap until a leave animation finishes:
|
|
@@ -110,12 +264,13 @@ Hydrates the server-rendered HTML on the client. Attaches event listeners and re
|
|
|
110
264
|
|
|
111
265
|
## API
|
|
112
266
|
|
|
113
|
-
| Export | Sub-path | Description
|
|
114
|
-
| ---------------------- | ------------------- |
|
|
115
|
-
| `onRenderHtml` | `@llui/vike/server` | Default server hook — minimal HTML template
|
|
116
|
-
| `createOnRenderHtml` | `@llui/vike/server` | Factory for custom document templates
|
|
117
|
-
| `onRenderClient` | `@llui/vike/client` | Default client hook — hydrate or mount
|
|
118
|
-
| `createOnRenderClient` | `@llui/vike/client` | Factory for custom container +
|
|
119
|
-
| `
|
|
267
|
+
| Export | Sub-path | Description |
|
|
268
|
+
| ---------------------- | ------------------- | --------------------------------------------------------------- |
|
|
269
|
+
| `onRenderHtml` | `@llui/vike/server` | Default server hook — minimal HTML template |
|
|
270
|
+
| `createOnRenderHtml` | `@llui/vike/server` | Factory for custom document templates + persistent layouts |
|
|
271
|
+
| `onRenderClient` | `@llui/vike/client` | Default client hook — hydrate or mount |
|
|
272
|
+
| `createOnRenderClient` | `@llui/vike/client` | Factory for custom container + layouts + transition hooks |
|
|
273
|
+
| `pageSlot` | `@llui/vike/client` | Structural primitive — declares where a layout renders its page |
|
|
274
|
+
| `fromTransition` | `@llui/vike/client` | Adapter: `TransitionOptions` → `{ onLeave, onEnter }` hook pair |
|
|
120
275
|
|
|
121
276
|
The barrel export (`@llui/vike`) re-exports everything, but prefer sub-path imports to avoid bundling jsdom into the client.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { onRenderHtml, createOnRenderHtml } from './on-render-html.js';
|
|
2
|
-
export type { PageContext, DocumentContext, RenderHtmlResult } from './on-render-html.js';
|
|
2
|
+
export type { PageContext, DocumentContext, RenderHtmlResult, RenderHtmlOptions, } from './on-render-html.js';
|
|
3
3
|
export { onRenderClient, createOnRenderClient, fromTransition } from './on-render-client.js';
|
|
4
4
|
export type { ClientPageContext, RenderClientOptions } from './on-render-client.js';
|
|
5
|
+
export { pageSlot } from './page-slot.js';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACtE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACtE,YAAY,EACV,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC5F,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAEnF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAQtE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG5F,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA","sourcesContent":["export { onRenderHtml, createOnRenderHtml } from './on-render-html.js'\nexport type {\n PageContext,\n DocumentContext,\n RenderHtmlResult,\n RenderHtmlOptions,\n} from './on-render-html.js'\n\nexport { onRenderClient, createOnRenderClient, fromTransition } from './on-render-client.js'\nexport type { ClientPageContext, RenderClientOptions } from './on-render-client.js'\n\nexport { pageSlot } from './page-slot.js'\n"]}
|
|
@@ -1,124 +1,170 @@
|
|
|
1
1
|
import type { ComponentDef, TransitionOptions } from '@llui/dom';
|
|
2
|
+
export { pageSlot } from './page-slot.js';
|
|
2
3
|
declare global {
|
|
3
4
|
interface Window {
|
|
4
5
|
__LLUI_STATE__?: unknown;
|
|
5
6
|
}
|
|
6
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Page context shape as seen by `@llui/vike`'s client-side hooks. The
|
|
10
|
+
* `Page` and `data` fields come from whichever `+Page.ts` and `+data.ts`
|
|
11
|
+
* Vike resolved for the current route.
|
|
12
|
+
*
|
|
13
|
+
* `lluiLayoutData` is optional and carries per-layer data for the layout
|
|
14
|
+
* chain configured via `createOnRenderClient({ Layout })`. It's indexed
|
|
15
|
+
* outermost-to-innermost, one entry per layout layer. Absent entries
|
|
16
|
+
* mean the corresponding layout's `init()` receives `undefined`. Users
|
|
17
|
+
* wire this from their Vike `+data.ts` files by merging layout-owned
|
|
18
|
+
* data under the `lluiLayoutData` key.
|
|
19
|
+
*/
|
|
7
20
|
export interface ClientPageContext {
|
|
8
21
|
Page: ComponentDef<unknown, unknown, unknown, unknown>;
|
|
9
22
|
data?: unknown;
|
|
23
|
+
lluiLayoutData?: readonly unknown[];
|
|
10
24
|
isHydration?: boolean;
|
|
11
25
|
}
|
|
26
|
+
type AnyComponentDef = ComponentDef<unknown, unknown, unknown, unknown>;
|
|
27
|
+
type LayoutChain = ReadonlyArray<AnyComponentDef>;
|
|
12
28
|
/**
|
|
13
|
-
* Page-lifecycle hooks that fire around the dispose →
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
29
|
+
* Page-lifecycle hooks that fire around the dispose → mount cycle on
|
|
30
|
+
* client navigation. With persistent layouts in play the cycle only
|
|
31
|
+
* tears down the *divergent* suffix of the layout chain — any layers
|
|
32
|
+
* shared between the old and new routes stay mounted.
|
|
17
33
|
*
|
|
18
|
-
*
|
|
34
|
+
* Navigation sequence for an already-mounted app:
|
|
19
35
|
*
|
|
20
36
|
* ```
|
|
21
37
|
* client nav triggered
|
|
22
38
|
* │
|
|
23
39
|
* ▼
|
|
24
|
-
*
|
|
25
|
-
* │
|
|
40
|
+
* compare old chain to new chain → find first mismatch index K
|
|
41
|
+
* │
|
|
26
42
|
* ▼
|
|
27
|
-
*
|
|
28
|
-
* │
|
|
29
|
-
* │
|
|
43
|
+
* onLeave(leaveTarget) ← awaited; leaveTarget is the slot element
|
|
44
|
+
* │ at depth K-1 (or the root container if K=0)
|
|
45
|
+
* │ whose contents are about to be replaced
|
|
30
46
|
* ▼
|
|
31
|
-
*
|
|
32
|
-
* │
|
|
47
|
+
* dispose chainHandles[K..end] innermost first
|
|
48
|
+
* │
|
|
33
49
|
* ▼
|
|
34
|
-
*
|
|
35
|
-
* │
|
|
50
|
+
* leaveTarget.textContent = ''
|
|
51
|
+
* │
|
|
52
|
+
* ▼
|
|
53
|
+
* mount newChain[K..end] into leaveTarget, outermost first
|
|
54
|
+
* │
|
|
36
55
|
* ▼
|
|
37
|
-
* onEnter(
|
|
56
|
+
* onEnter(leaveTarget) ← fire-and-forget; fresh DOM in place
|
|
38
57
|
* │
|
|
39
58
|
* ▼
|
|
40
|
-
* onMount()
|
|
59
|
+
* onMount()
|
|
41
60
|
* ```
|
|
42
61
|
*
|
|
43
|
-
* On the initial render
|
|
62
|
+
* On the initial hydration render, `onLeave` and `onEnter` are NOT
|
|
44
63
|
* called — there's no outgoing page to leave and no animation to enter.
|
|
45
|
-
*
|
|
64
|
+
* Use `onMount` for code that should run on every render including the
|
|
65
|
+
* initial one.
|
|
46
66
|
*/
|
|
47
67
|
export interface RenderClientOptions {
|
|
48
|
-
/** CSS selector for the mount container. Default: '#app' */
|
|
68
|
+
/** CSS selector for the mount container. Default: `'#app'`. */
|
|
49
69
|
container?: string;
|
|
50
70
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
71
|
+
* Persistent layout chain. One of:
|
|
72
|
+
*
|
|
73
|
+
* - A single `ComponentDef` — becomes a one-layout chain.
|
|
74
|
+
* - An array of `ComponentDef`s — outermost layout first, innermost
|
|
75
|
+
* layout last. Every layer except the innermost must call
|
|
76
|
+
* `pageSlot()` in its view to declare where nested content renders.
|
|
77
|
+
* - A function that returns a chain from the current `pageContext` —
|
|
78
|
+
* lets different routes use different chains, e.g. by reading
|
|
79
|
+
* Vike's `pageContext.urlPathname` or `pageContext.config.Layout`.
|
|
55
80
|
*
|
|
81
|
+
* Layers that are shared between the previous and next navigation
|
|
82
|
+
* stay mounted. Only the divergent suffix is disposed and re-mounted.
|
|
83
|
+
* Dialogs, focus traps, and effect subscriptions rooted in a surviving
|
|
84
|
+
* layer are unaffected by the nav.
|
|
85
|
+
*/
|
|
86
|
+
Layout?: AnyComponentDef | LayoutChain | ((pageContext: ClientPageContext) => LayoutChain);
|
|
87
|
+
/**
|
|
88
|
+
* Called on the slot element whose contents are about to be replaced,
|
|
89
|
+
* BEFORE the divergent suffix is disposed and re-mounted. The slot's
|
|
90
|
+
* current DOM is still attached when this runs — the only moment a
|
|
91
|
+
* leave animation can read/write it. Return a promise to defer the
|
|
92
|
+
* swap until the animation completes.
|
|
93
|
+
*
|
|
94
|
+
* For a plain no-layout setup, the slot element is the root container.
|
|
56
95
|
* Not called on the initial hydration render.
|
|
57
96
|
*/
|
|
58
97
|
onLeave?: (el: HTMLElement) => void | Promise<void>;
|
|
59
98
|
/**
|
|
60
|
-
* Called after the new
|
|
61
|
-
*
|
|
62
|
-
*
|
|
99
|
+
* Called after the new divergent suffix is mounted, on the same slot
|
|
100
|
+
* element that was passed to `onLeave`. Use this to kick off an enter
|
|
101
|
+
* animation. Fire-and-forget — promise returns are ignored.
|
|
63
102
|
*
|
|
64
103
|
* Not called on the initial hydration render.
|
|
65
104
|
*/
|
|
66
105
|
onEnter?: (el: HTMLElement) => void;
|
|
67
106
|
/**
|
|
68
107
|
* Called after mount or hydration completes. Fires on every render
|
|
69
|
-
* including the initial hydration. Use
|
|
70
|
-
*
|
|
71
|
-
* management, etc.).
|
|
108
|
+
* including the initial hydration. Use for per-render side effects
|
|
109
|
+
* that don't fit the animation hooks.
|
|
72
110
|
*/
|
|
73
111
|
onMount?: () => void;
|
|
74
112
|
}
|
|
75
113
|
/**
|
|
76
114
|
* Adapt a `TransitionOptions` object (e.g. the output of
|
|
77
|
-
* `routeTransition()` from `@llui/transitions`, or
|
|
78
|
-
*
|
|
79
|
-
*
|
|
115
|
+
* `routeTransition()` from `@llui/transitions`, or a preset like `fade`
|
|
116
|
+
* / `slide`) into the `onLeave` / `onEnter` pair expected by
|
|
117
|
+
* `createOnRenderClient`.
|
|
80
118
|
*
|
|
81
|
-
* ```
|
|
119
|
+
* ```ts
|
|
82
120
|
* import { createOnRenderClient, fromTransition } from '@llui/vike/client'
|
|
83
121
|
* import { routeTransition } from '@llui/transitions'
|
|
84
122
|
*
|
|
85
123
|
* export const onRenderClient = createOnRenderClient({
|
|
124
|
+
* Layout: AppLayout,
|
|
86
125
|
* ...fromTransition(routeTransition({ duration: 200 })),
|
|
87
126
|
* })
|
|
88
127
|
* ```
|
|
89
128
|
*
|
|
90
|
-
* The transition operates on the
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* when the new page mounts; use `enter` to reset them explicitly or
|
|
95
|
-
* pick presets that self-clean.
|
|
129
|
+
* The transition operates on the slot element — in a no-layout setup,
|
|
130
|
+
* the root container; in a layout setup, the innermost surviving
|
|
131
|
+
* layer's `pageSlot()` element. Opacity / transform fades apply to the
|
|
132
|
+
* outgoing page content, then the new page fades in.
|
|
96
133
|
*/
|
|
97
134
|
export declare function fromTransition(t: TransitionOptions): Pick<RenderClientOptions, 'onLeave' | 'onEnter'>;
|
|
98
135
|
/**
|
|
99
|
-
* @internal — test helper. Disposes
|
|
100
|
-
* the module
|
|
101
|
-
* Not part of the public API; subject to change without notice.
|
|
136
|
+
* @internal — test helper. Disposes every layer in the current chain
|
|
137
|
+
* and clears the module state so subsequent calls behave as a first
|
|
138
|
+
* mount. Not part of the public API; subject to change without notice.
|
|
139
|
+
*/
|
|
140
|
+
export declare function _resetChainForTest(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Back-compat alias for the pre-layout test helper name.
|
|
143
|
+
* @internal
|
|
144
|
+
* @deprecated — use `_resetChainForTest` instead.
|
|
102
145
|
*/
|
|
103
146
|
export declare function _resetCurrentHandleForTest(): void;
|
|
104
147
|
/**
|
|
105
|
-
* Default onRenderClient hook — no animation hooks. Hydrates
|
|
106
|
-
*
|
|
148
|
+
* Default onRenderClient hook — no layout, no animation hooks. Hydrates
|
|
149
|
+
* on first load, mounts fresh on subsequent navs. Use `createOnRenderClient`
|
|
107
150
|
* for the customizable factory form.
|
|
108
151
|
*/
|
|
109
152
|
export declare function onRenderClient(pageContext: ClientPageContext): Promise<void>;
|
|
110
153
|
/**
|
|
111
|
-
* Factory to create a customized onRenderClient hook.
|
|
154
|
+
* Factory to create a customized onRenderClient hook. See `RenderClientOptions`
|
|
155
|
+
* for the full option surface — this is the entry point for persistent
|
|
156
|
+
* layouts, route transitions, and lifecycle hooks.
|
|
112
157
|
*
|
|
113
|
-
* ```
|
|
158
|
+
* ```ts
|
|
114
159
|
* // pages/+onRenderClient.ts
|
|
115
|
-
* import { createOnRenderClient } from '@llui/vike/client'
|
|
160
|
+
* import { createOnRenderClient, fromTransition } from '@llui/vike/client'
|
|
161
|
+
* import { routeTransition } from '@llui/transitions'
|
|
162
|
+
* import { AppLayout } from './+Layout'
|
|
116
163
|
*
|
|
117
164
|
* export const onRenderClient = createOnRenderClient({
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* onMount: () => console.log('Page ready'),
|
|
165
|
+
* Layout: AppLayout,
|
|
166
|
+
* ...fromTransition(routeTransition({ duration: 200 })),
|
|
167
|
+
* onMount: () => console.log('page rendered'),
|
|
122
168
|
* })
|
|
123
169
|
* ```
|
|
124
170
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-render-client.d.ts","sourceRoot":"","sources":["../src/on-render-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAa,iBAAiB,
|
|
1
|
+
{"version":3,"file":"on-render-client.d.ts","sourceRoot":"","sources":["../src/on-render-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAa,iBAAiB,EAAS,MAAM,WAAW,CAAA;AAKlF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,cAAc,CAAC,EAAE,OAAO,CAAA;KACzB;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACtD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,cAAc,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;IACnC,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,KAAK,eAAe,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACvE,KAAK,WAAW,GAAG,aAAa,CAAC,eAAe,CAAC,CAAA;AAoBjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,EAAE,eAAe,GAAG,WAAW,GAAG,CAAC,CAAC,WAAW,EAAE,iBAAiB,KAAK,WAAW,CAAC,CAAA;IAE1F;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEnD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IAEnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,iBAAiB,GACnB,IAAI,CAAC,mBAAmB,EAAE,SAAS,GAAG,SAAS,CAAC,CAgBlD;AAoBD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAOzC;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,mBAAmB,GAC3B,CAAC,WAAW,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAEnD"}
|