@uniweb/runtime 0.8.15 → 0.8.17
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/app/assets/{index-CsqlosR8.js → index-S3vw9Fm0.js} +7 -7
- package/dist/app/assets/index-S3vw9Fm0.js.map +1 -0
- package/dist/app/index.html +1 -1
- package/dist/app/manifest.json +2 -2
- package/dist/shims/react-jsx-runtime.js +7 -0
- package/dist/shims/react.js +48 -0
- package/dist/shims/uniweb-core.js +22 -0
- package/dist/ssr.js +15 -2
- package/dist/ssr.js.map +1 -1
- package/dist/worker-runtime-entry.js +8 -0
- package/dist/worker-runtime.js +28970 -0
- package/package.json +6 -4
- package/src/components/Layout.jsx +8 -3
- package/src/setup.js +7 -3
- package/src/ssr-renderer.js +16 -2
- package/src/view-transitions.js +47 -0
- package/dist/app/assets/index-CsqlosR8.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/runtime",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.17",
|
|
4
4
|
"description": "Minimal runtime for loading Uniweb foundations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -35,14 +35,15 @@
|
|
|
35
35
|
"node": ">=20.19"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@uniweb/
|
|
39
|
-
"@uniweb/
|
|
38
|
+
"@uniweb/theming": "0.1.3",
|
|
39
|
+
"@uniweb/core": "0.7.12"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@vitejs/plugin-react": "^4.5.2",
|
|
43
|
+
"esbuild": "^0.21.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.27.0",
|
|
43
44
|
"vite": "^7.3.1",
|
|
44
45
|
"vitest": "^4.1.7",
|
|
45
|
-
"@uniweb/build": "0.14.
|
|
46
|
+
"@uniweb/build": "0.14.11"
|
|
46
47
|
},
|
|
47
48
|
"peerDependencies": {
|
|
48
49
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
"build:ssr": "vite build --config vite.config.ssr.js",
|
|
54
55
|
"build:app": "vite build --config vite.config.app.js",
|
|
55
56
|
"build": "npm run build:ssr && npm run build:app",
|
|
57
|
+
"build:worker": "node build-worker.js",
|
|
56
58
|
"test": "vitest run",
|
|
57
59
|
"test:watch": "vitest"
|
|
58
60
|
}
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
import Blocks from './Blocks.jsx'
|
|
35
|
+
import { resolveLayoutTransitions } from '../view-transitions.js'
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Default layout - renders header, body, footer in sequence
|
|
@@ -91,9 +92,13 @@ export default function Layout({ page, website }) {
|
|
|
91
92
|
initializeAllBlocks(...allBlockGroups)
|
|
92
93
|
|
|
93
94
|
// Pre-render each area as React elements.
|
|
94
|
-
// When the foundation enables view transitions, wrap areas in thin divs
|
|
95
|
-
//
|
|
96
|
-
|
|
95
|
+
// When the foundation enables view transitions, wrap areas in thin divs with
|
|
96
|
+
// view-transition-name so the browser can animate them independently. Names
|
|
97
|
+
// default to one per area + body (see resolveLayoutTransitions); the layout's
|
|
98
|
+
// `transitions` meta overrides or opts out.
|
|
99
|
+
const transitions = website.viewTransitions
|
|
100
|
+
? resolveLayoutTransitions(Object.keys(areas), layoutMeta?.transitions)
|
|
101
|
+
: null
|
|
97
102
|
|
|
98
103
|
const bodyElement = bodyBlocks ? (
|
|
99
104
|
transitions?.body
|
package/src/setup.js
CHANGED
|
@@ -217,9 +217,13 @@ function createIconResolver(iconConfig = {}) {
|
|
|
217
217
|
// ─── Runtime default fetcher ────────────────────────────────────────────────
|
|
218
218
|
|
|
219
219
|
function buildDefaultFetcher(content) {
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
|
|
220
|
+
// Base for resolving local absolute paths (e.g. /data/*.json). Prefer the base
|
|
221
|
+
// the PAYLOAD carries (`content.config.base`) — a backend-hosted SPA is served
|
|
222
|
+
// under a subpath the payload declares (e.g. /gateway/site/<uuid>/) that the
|
|
223
|
+
// gateway-delivered runtime bundle can't know via Vite's build-time BASE_URL.
|
|
224
|
+
// This is the SAME base routing uses; without it local fetches hit the origin
|
|
225
|
+
// root and 404. Falls back to Vite's BASE_URL for a statically built site.
|
|
226
|
+
const basePath = content?.config?.base || import.meta.env?.BASE_URL || ''
|
|
223
227
|
// Per-site transport config from `site.yml fetcher:`. The default fetcher
|
|
224
228
|
// recognizes `baseUrl` and `envelope`; foundations with their own fetchers
|
|
225
229
|
// may read additional keys from the same block via ctx.website.config.fetcher.
|
package/src/ssr-renderer.js
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
sliceContentForLocale,
|
|
26
26
|
hydrateDataStore,
|
|
27
27
|
} from './wire-foundation.js'
|
|
28
|
+
import { resolveLayoutTransitions } from './view-transitions.js'
|
|
28
29
|
|
|
29
30
|
// Re-export L2 helpers so the public `@uniweb/runtime/ssr` surface
|
|
30
31
|
// carries everything an SSR consumer needs from one entry point.
|
|
@@ -343,10 +344,23 @@ export function renderLayout(page, website) {
|
|
|
343
344
|
const bodyBlocks = page.getBodyBlocks()
|
|
344
345
|
const areas = page.getLayoutAreas()
|
|
345
346
|
|
|
346
|
-
|
|
347
|
+
// Mirror Layout.jsx: wrap body + each area in a thin div carrying its
|
|
348
|
+
// view-transition-name, so the prerendered HTML matches what the SPA hydrates
|
|
349
|
+
// and the browser can animate regions independently on client navigation.
|
|
350
|
+
const transitions = website.viewTransitions
|
|
351
|
+
? resolveLayoutTransitions(Object.keys(areas), layoutMeta?.transitions)
|
|
352
|
+
: null
|
|
353
|
+
const wrapTransition = (name, element) => {
|
|
354
|
+
const vtName = transitions?.[name]
|
|
355
|
+
return vtName
|
|
356
|
+
? React.createElement('div', { style: { viewTransitionName: vtName } }, element)
|
|
357
|
+
: element
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const bodyElement = bodyBlocks ? wrapTransition('body', renderBlocks(bodyBlocks)) : null
|
|
347
361
|
const areaElements = {}
|
|
348
362
|
for (const [name, blocks] of Object.entries(areas)) {
|
|
349
|
-
areaElements[name] = renderBlocks(blocks)
|
|
363
|
+
areaElements[name] = wrapTransition(name, renderBlocks(blocks))
|
|
350
364
|
}
|
|
351
365
|
|
|
352
366
|
if (RemoteLayout) {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View-transition name resolution for layout areas.
|
|
3
|
+
*
|
|
4
|
+
* When a foundation enables view transitions (the default), the runtime gives
|
|
5
|
+
* each layout region a `view-transition-name` so the browser animates them
|
|
6
|
+
* independently — persistent chrome (header, sidebar, footer) morphs in place
|
|
7
|
+
* while the body crossfades. Without per-region names the browser falls back to
|
|
8
|
+
* a single full-page crossfade, which makes the whole layout (chrome included)
|
|
9
|
+
* flicker on every navigation.
|
|
10
|
+
*
|
|
11
|
+
* This module is pure (no React/DOM) so both the SPA renderer
|
|
12
|
+
* (`components/Layout.jsx`) and the SSR renderer (`ssr-renderer.js`) derive the
|
|
13
|
+
* exact same names — keeping the prerendered HTML and the hydrated SPA aligned.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Namespace so generated names can't collide with `view-transition-name`s a
|
|
17
|
+
// foundation sets inside its own component CSS. The prefix also guarantees a
|
|
18
|
+
// valid CSS <custom-ident> (starts with a letter).
|
|
19
|
+
const NS = 'uw-'
|
|
20
|
+
|
|
21
|
+
const toIdent = (name) => NS + String(name).replace(/[^a-zA-Z0-9_-]/g, '-')
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Build the effective view-transition-name map for a layout.
|
|
25
|
+
*
|
|
26
|
+
* Default: every rendered area plus the implicit `body` gets a stable,
|
|
27
|
+
* namespaced name (`uw-<area>`, `uw-body`). Same-named areas across layouts
|
|
28
|
+
* therefore share a name and morph between layouts automatically.
|
|
29
|
+
*
|
|
30
|
+
* The layout's `meta.js` `transitions` value overrides this:
|
|
31
|
+
* - an object overrides per region (`{ left: 'sidebar' }` to group across
|
|
32
|
+
* layouts, or `{ left: null }` to opt one region out);
|
|
33
|
+
* - `false` opts the whole layout out (back to the full-page crossfade).
|
|
34
|
+
*
|
|
35
|
+
* @param {string[]} areaNames - Names of the areas rendered for this page (excludes `body`).
|
|
36
|
+
* @param {Object|false|null|undefined} explicit - `layoutMeta.transitions`.
|
|
37
|
+
* @returns {Object|null} region → view-transition-name; `null` when opted out.
|
|
38
|
+
* A region whose value is null/empty in the returned map gets no name.
|
|
39
|
+
*/
|
|
40
|
+
export function resolveLayoutTransitions(areaNames, explicit) {
|
|
41
|
+
if (explicit === false) return null
|
|
42
|
+
|
|
43
|
+
const transitions = { body: toIdent('body') }
|
|
44
|
+
for (const name of areaNames) transitions[name] = toIdent(name)
|
|
45
|
+
|
|
46
|
+
return explicit ? { ...transitions, ...explicit } : transitions
|
|
47
|
+
}
|