@homepages/template-kit 0.8.0 → 0.8.1-dev-20260718020735
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/CHANGELOG.md +10 -0
- package/dist/island-runtime.js +1 -1
- package/dist/package.js +1 -1
- package/guide/islands.md +23 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @homepages/template-kit
|
|
2
2
|
|
|
3
|
+
## 0.8.1-dev-20260718020735
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1c4c7dd: Island hydration is now nesting-safe: `hydrateIslands` skips any island marker
|
|
8
|
+
nested inside another marker, so an island can render another island without the
|
|
9
|
+
child being hydrated twice (once by its parent root, once independently). Enables
|
|
10
|
+
interactive islands (accordion, card-slider, carousel) to wrap existing leaf
|
|
11
|
+
islands (expandable-text) on published pages.
|
|
12
|
+
|
|
3
13
|
## 0.8.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/dist/island-runtime.js
CHANGED
|
@@ -17,7 +17,7 @@ function createEditorPropsBridge(react) {
|
|
|
17
17
|
}
|
|
18
18
|
async function hydrateIslands(options) {
|
|
19
19
|
const root = options.root ?? document;
|
|
20
|
-
const markers = Array.from(root.querySelectorAll(`[${ATTR_ISLAND_KEY}]`)).filter((element) => !roots.has(element));
|
|
20
|
+
const markers = Array.from(root.querySelectorAll(`[${ATTR_ISLAND_KEY}]`)).filter((element) => !roots.has(element) && element.parentElement?.closest(`[${"data-tr-island"}]`) == null);
|
|
21
21
|
if (markers.length === 0) return [];
|
|
22
22
|
const payloads = /* @__PURE__ */ new Map();
|
|
23
23
|
const duplicateIds = /* @__PURE__ */ new Set();
|
package/dist/package.js
CHANGED
package/guide/islands.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
purpose: How interactivity works in a template — client components ("islands"), their props contract, and their editor options.
|
|
3
3
|
status: living
|
|
4
4
|
related: [INDEX.md, eslint.md, dev.md]
|
|
5
|
-
updated: 2026-07-
|
|
5
|
+
updated: 2026-07-18
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Islands: interactivity in a template
|
|
@@ -141,6 +141,24 @@ hydrates:
|
|
|
141
141
|
The marker is layout-invisible (`display:contents`), so an island can sit directly
|
|
142
142
|
inside a grid or flex container without adding a box.
|
|
143
143
|
|
|
144
|
+
## Nesting one island inside another
|
|
145
|
+
|
|
146
|
+
An island can render another island — for example, an accordion island whose expanded
|
|
147
|
+
content is itself an existing expandable-text island. Because the build wraps every
|
|
148
|
+
`"use client"` module in a marker, the nested island's marker ends up inside the parent
|
|
149
|
+
island's server-rendered output.
|
|
150
|
+
|
|
151
|
+
A nested marker is not hydrated as its own root. It is left to the marker that contains
|
|
152
|
+
it, which already renders — and hydrates — it as part of its own React tree. The nested
|
|
153
|
+
component still runs and stays interactive, but it loses its own root and its own editor
|
|
154
|
+
treatment:
|
|
155
|
+
|
|
156
|
+
- Its `editor.live`/`shieldMode`/`liveSurface`/`props` declaration has no independent
|
|
157
|
+
effect in the canvas — the parent island's declaration governs the whole subtree, since
|
|
158
|
+
there is no separate root for the editor to select or shield.
|
|
159
|
+
- Its props `<script>` still renders in the DOM (harmless) but goes unread; props reach
|
|
160
|
+
the nested component through the parent's own render instead.
|
|
161
|
+
|
|
144
162
|
## Hosting islands yourself
|
|
145
163
|
|
|
146
164
|
`@homepages/template-kit/island-runtime` is the loader. It is not something a template
|
|
@@ -153,9 +171,10 @@ await hydrateIslands({ load: (key) => ISLANDS[key]() }); // ISLANDS: the build'
|
|
|
153
171
|
unmountIslands(sectionEl); // before replacing sectionEl's HTML
|
|
154
172
|
```
|
|
155
173
|
|
|
156
|
-
Each island is an independent React root: one island's state, re-renders, and
|
|
157
|
-
never touch another's.
|
|
158
|
-
|
|
174
|
+
Each top-level island is an independent React root: one island's state, re-renders, and
|
|
175
|
+
errors never touch another's. An island nested inside another (see above) hydrates as
|
|
176
|
+
part of its parent's root instead. Hydration is idempotent, so calling `hydrateIslands`
|
|
177
|
+
again after injecting new markup is safe.
|
|
159
178
|
|
|
160
179
|
## Talking to HomePages from an island
|
|
161
180
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homepages/template-kit",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1-dev-20260718020735",
|
|
4
4
|
"description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the template-kit CLI.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|