@llui/vike 0.4.10 → 0.5.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/dist/page-slot.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getRenderContext, createLifetime } from '@llui/dom/internal';
1
+ import { __currentBuildInfo } from '@llui/dom';
2
2
  let pendingSlot = null;
3
3
  /**
4
4
  * Declare where a persistent layout renders its nested content — either
@@ -11,12 +11,12 @@ let pendingSlot = null;
11
11
  * within the layout's own parent element; a synthesized end sentinel
12
12
  * (`<!-- llui-mount-end -->`) brackets the owned region.
13
13
  *
14
- * The slot is a real scope-tree node: the scope it creates is a child
15
- * of the current render scope, so contexts provided by the layout (via
16
- * `provide()`) above the slot are reachable from inside the nested
17
- * page. That's how patterns like a layout-owned toast dispatcher work —
18
- * the page does `useContext(ToastContext)` and walks up through the
19
- * slot into the layout's providers.
14
+ * Contexts provided by the layout (via `provide()`) ABOVE the slot are
15
+ * reachable from inside the nested page: `pageSlot()` snapshots the
16
+ * in-scope context values and the adapter replays them into the nested
17
+ * layer's build. That's how patterns like a layout-owned toast
18
+ * dispatcher work — the page does `useContext(ToastContext)` and reads
19
+ * the value the layout provided above the slot.
20
20
  *
21
21
  * Do NOT name the file `+Layout.ts` — Vike reserves the `+` prefix for
22
22
  * its own framework config conventions. Use `Layout.ts`, `app-layout.ts`,
@@ -29,9 +29,9 @@ let pendingSlot = null;
29
29
  *
30
30
  * export const AppLayout = component<LayoutState, LayoutMsg>({
31
31
  * name: 'AppLayout',
32
- * init: () => [{ ... }, []],
32
+ * init: () => ({ ... }),
33
33
  * update: layoutUpdate,
34
- * view: (h) => [
34
+ * view: ({ send }) => [
35
35
  * div({ class: 'app-shell' }, [
36
36
  * header([...]),
37
37
  * main([pageSlot()]), // ← here the page goes (no wrapper div)
@@ -40,6 +40,9 @@ let pendingSlot = null;
40
40
  * })
41
41
  * ```
42
42
  *
43
+ * Returns the anchor comment as a single `Node` — drop it straight into
44
+ * a children array (`main([pageSlot()])`); no spread needed.
45
+ *
43
46
  * Call exactly once per layout. Calling more than once in a single
44
47
  * view throws.
45
48
  */
@@ -50,11 +53,14 @@ export function pageSlot() {
50
53
  'regions that swap on navigation, build them as sibling nested layouts in ' +
51
54
  'the Vike routing tree and use context to share state between them.');
52
55
  }
53
- const ctx = getRenderContext('pageSlot');
54
- const slotLifetime = createLifetime(ctx.rootLifetime);
55
- const anchor = ctx.dom.createComment('llui-page-slot');
56
- pendingSlot = { slotLifetime, anchor };
57
- return [anchor];
56
+ const info = __currentBuildInfo();
57
+ if (!info) {
58
+ throw new Error('[llui/vike] pageSlot() was called outside a signal build. It must run inside ' +
59
+ 'a layout component view rendered by the @llui/vike adapter.');
60
+ }
61
+ const anchor = info.doc.createComment('llui-page-slot');
62
+ pendingSlot = { anchor, contexts: info.contexts };
63
+ return anchor;
58
64
  }
59
65
  /**
60
66
  * @internal — vike adapter only. Read and clear the slot registered by
@@ -1 +1 @@
1
- {"version":3,"file":"page-slot.js","sourceRoot":"","sources":["../src/page-slot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAmBrE,IAAI,WAAW,GAAuB,IAAI,CAAA;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,UAAU,QAAQ;IACtB,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,uEAAuE;YACrE,6EAA6E;YAC7E,2EAA2E;YAC3E,oEAAoE,CACvE,CAAA;IACH,CAAC;IACD,MAAM,GAAG,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;IACxC,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IACrD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,gBAAgB,CAAY,CAAA;IACjE,WAAW,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,CAAA;IACtC,OAAO,CAAC,MAAM,CAAC,CAAA;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,WAAW,GAAG,IAAI,CAAA;IAClB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,WAAW,GAAG,IAAI,CAAA;AACpB,CAAC","sourcesContent":["import type { Lifetime } from '@llui/dom'\nimport { getRenderContext, createLifetime } from '@llui/dom/internal'\n\n// @llui/dom/internal is the adapter-layer surface: low-level primitives\n// (render-context access, scope creation, disposer registration) that\n// framework adapters like @llui/vike need to build structural primitives\n// on top of. Not part of the public app-author API.\n\n/**\n * Transient handoff between a layout layer's render pass and the vike\n * adapter that's mounting the chain. `pageSlot()` populates this during\n * the layout's view() call; `consumePendingSlot()` reads and clears it\n * immediately after the mount returns. One slot per mount pass — calling\n * `pageSlot()` twice in the same layout is a bug the primitive reports.\n */\ninterface PendingSlot {\n slotLifetime: Lifetime\n anchor: Comment\n}\n\nlet pendingSlot: PendingSlot | null = null\n\n/**\n * Declare where a persistent layout renders its nested content — either\n * a nested layout or the route's page component. The vike adapter's\n * client and server render paths walk the layout chain, and each layer's\n * `pageSlot()` call records the position where the next layer mounts.\n *\n * Emits a single `<!-- llui-page-slot -->` comment as an insertion\n * anchor. The nested layer's DOM lives as siblings of this comment\n * within the layout's own parent element; a synthesized end sentinel\n * (`<!-- llui-mount-end -->`) brackets the owned region.\n *\n * The slot is a real scope-tree node: the scope it creates is a child\n * of the current render scope, so contexts provided by the layout (via\n * `provide()`) above the slot are reachable from inside the nested\n * page. That's how patterns like a layout-owned toast dispatcher work —\n * the page does `useContext(ToastContext)` and walks up through the\n * slot into the layout's providers.\n *\n * Do NOT name the file `+Layout.ts` — Vike reserves the `+` prefix for\n * its own framework config conventions. Use `Layout.ts`, `app-layout.ts`,\n * or anywhere outside `/pages` that Vike won't scan.\n *\n * ```ts\n * // pages/Layout.ts ← not +Layout.ts\n * import { component, div, main, header } from '@llui/dom'\n * import { pageSlot } from '@llui/vike/client'\n *\n * export const AppLayout = component<LayoutState, LayoutMsg>({\n * name: 'AppLayout',\n * init: () => [{ ... }, []],\n * update: layoutUpdate,\n * view: (h) => [\n * div({ class: 'app-shell' }, [\n * header([...]),\n * main([pageSlot()]), // ← here the page goes (no wrapper div)\n * ]),\n * ],\n * })\n * ```\n *\n * Call exactly once per layout. Calling more than once in a single\n * view throws.\n */\nexport function pageSlot(): Node[] {\n if (pendingSlot !== null) {\n throw new Error(\n '[llui/vike] pageSlot() was called more than once in the same layout. ' +\n 'A layout has exactly one nested-content slot — if you need two independent ' +\n 'regions that swap on navigation, build them as sibling nested layouts in ' +\n 'the Vike routing tree and use context to share state between them.',\n )\n }\n const ctx = getRenderContext('pageSlot')\n const slotLifetime = createLifetime(ctx.rootLifetime)\n const anchor = ctx.dom.createComment('llui-page-slot') as Comment\n pendingSlot = { slotLifetime, anchor }\n return [anchor]\n}\n\n/**\n * @internal — vike adapter only. Read and clear the slot registered by\n * the most recent `pageSlot()` call. Returns null if the layer being\n * mounted didn't call `pageSlot()` (meaning it's the innermost layer\n * and owns no nested content).\n */\nexport function _consumePendingSlot(): PendingSlot | null {\n const slot = pendingSlot\n pendingSlot = null\n return slot\n}\n\n/**\n * @internal — vike adapter only. Reset the pending slot without reading\n * it. Used defensively in error paths to avoid leaking a pending slot\n * registration into a subsequent mount attempt.\n */\nexport function _resetPendingSlot(): void {\n pendingSlot = null\n}\n"]}
1
+ {"version":3,"file":"page-slot.js","sourceRoot":"","sources":["../src/page-slot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AA6B9C,IAAI,WAAW,GAAuB,IAAI,CAAA;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,UAAU,QAAQ;IACtB,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,uEAAuE;YACrE,6EAA6E;YAC7E,2EAA2E;YAC3E,oEAAoE,CACvE,CAAA;IACH,CAAC;IACD,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAA;IACjC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,+EAA+E;YAC7E,6DAA6D,CAChE,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,gBAAgB,CAAY,CAAA;IAClE,WAAW,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,WAAW,GAAG,IAAI,CAAA;IAClB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,WAAW,GAAG,IAAI,CAAA;AACpB,CAAC","sourcesContent":["import { __currentBuildInfo } from '@llui/dom'\n\n// `@llui/dom`'s `__currentBuildInfo()` is the adapter-layer hook a\n// framework adapter like `@llui/vike` uses to participate in the signal build:\n// it exposes the in-progress build's `doc` (to create anchor nodes that belong\n// to the same document) plus a SNAPSHOT of the context values in scope at the\n// call site (so contexts provided ABOVE the slot reach the nested page's\n// separate build/mount pass). Not part of the public app-author API.\n\n/**\n * Transient handoff between a layout layer's render pass and the vike\n * adapter that's mounting the chain. `pageSlot()` populates this during\n * the layout's view() call; `_consumePendingSlot()` reads and clears it\n * immediately after the mount returns. One slot per mount pass — calling\n * `pageSlot()` twice in the same layout is a bug the primitive reports.\n */\ninterface PendingSlot {\n /** the slot's insertion anchor (a `<!-- llui-page-slot -->` comment) */\n anchor: Comment\n /**\n * Snapshot of the context values in scope at the `pageSlot()` call site.\n * The adapter replays these into the NESTED layer's build (via the signal\n * `contexts` mount/render option) so a layout-provided context — e.g. a\n * toast dispatcher provided ABOVE the slot — is reachable from inside the\n * nested page, even though the page builds in a separate pass.\n */\n contexts: ReadonlyMap<symbol, unknown>\n}\n\nlet pendingSlot: PendingSlot | null = null\n\n/**\n * Declare where a persistent layout renders its nested content — either\n * a nested layout or the route's page component. The vike adapter's\n * client and server render paths walk the layout chain, and each layer's\n * `pageSlot()` call records the position where the next layer mounts.\n *\n * Emits a single `<!-- llui-page-slot -->` comment as an insertion\n * anchor. The nested layer's DOM lives as siblings of this comment\n * within the layout's own parent element; a synthesized end sentinel\n * (`<!-- llui-mount-end -->`) brackets the owned region.\n *\n * Contexts provided by the layout (via `provide()`) ABOVE the slot are\n * reachable from inside the nested page: `pageSlot()` snapshots the\n * in-scope context values and the adapter replays them into the nested\n * layer's build. That's how patterns like a layout-owned toast\n * dispatcher work the page does `useContext(ToastContext)` and reads\n * the value the layout provided above the slot.\n *\n * Do NOT name the file `+Layout.ts` — Vike reserves the `+` prefix for\n * its own framework config conventions. Use `Layout.ts`, `app-layout.ts`,\n * or anywhere outside `/pages` that Vike won't scan.\n *\n * ```ts\n * // pages/Layout.ts ← not +Layout.ts\n * import { component, div, main, header } from '@llui/dom'\n * import { pageSlot } from '@llui/vike/client'\n *\n * export const AppLayout = component<LayoutState, LayoutMsg>({\n * name: 'AppLayout',\n * init: () => ({ ... }),\n * update: layoutUpdate,\n * view: ({ send }) => [\n * div({ class: 'app-shell' }, [\n * header([...]),\n * main([pageSlot()]), // ← here the page goes (no wrapper div)\n * ]),\n * ],\n * })\n * ```\n *\n * Returns the anchor comment as a single `Node` — drop it straight into\n * a children array (`main([pageSlot()])`); no spread needed.\n *\n * Call exactly once per layout. Calling more than once in a single\n * view throws.\n */\nexport function pageSlot(): Node {\n if (pendingSlot !== null) {\n throw new Error(\n '[llui/vike] pageSlot() was called more than once in the same layout. ' +\n 'A layout has exactly one nested-content slot — if you need two independent ' +\n 'regions that swap on navigation, build them as sibling nested layouts in ' +\n 'the Vike routing tree and use context to share state between them.',\n )\n }\n const info = __currentBuildInfo()\n if (!info) {\n throw new Error(\n '[llui/vike] pageSlot() was called outside a signal build. It must run inside ' +\n 'a layout component view rendered by the @llui/vike adapter.',\n )\n }\n const anchor = info.doc.createComment('llui-page-slot') as Comment\n pendingSlot = { anchor, contexts: info.contexts }\n return anchor\n}\n\n/**\n * @internal — vike adapter only. Read and clear the slot registered by\n * the most recent `pageSlot()` call. Returns null if the layer being\n * mounted didn't call `pageSlot()` (meaning it's the innermost layer\n * and owns no nested content).\n */\nexport function _consumePendingSlot(): PendingSlot | null {\n const slot = pendingSlot\n pendingSlot = null\n return slot\n}\n\n/**\n * @internal — vike adapter only. Reset the pending slot without reading\n * it. Used defensively in error paths to avoid leaking a pending slot\n * registration into a subsequent mount attempt.\n */\nexport function _resetPendingSlot(): void {\n pendingSlot = null\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llui/vike",
3
- "version": "0.4.10",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -21,7 +21,7 @@
21
21
  "dist"
22
22
  ],
23
23
  "peerDependencies": {
24
- "@llui/dom": "^0.4.10",
24
+ "@llui/dom": "^0.5.0",
25
25
  "jsdom": "*"
26
26
  },
27
27
  "peerDependenciesMeta": {
@@ -30,7 +30,7 @@
30
30
  }
31
31
  },
32
32
  "devDependencies": {
33
- "@llui/dom": "0.4.10"
33
+ "@llui/dom": "0.5.0"
34
34
  },
35
35
  "description": "LLui Vike SSR adapter — onRenderHtml, onRenderClient hooks",
36
36
  "keywords": [