@ripple-ts/vite-plugin 0.3.81 → 0.3.83

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 CHANGED
@@ -1,5 +1,35 @@
1
1
  # @ripple-ts/vite-plugin
2
2
 
3
+ ## 0.3.83
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ [[`3d93339`](https://github.com/Ripple-TS/ripple/commit/3d93339e851818b547c43c29c8965700c069b037),
9
+ [`5646eb4`](https://github.com/Ripple-TS/ripple/commit/5646eb4e4c101b34100acf30ea57ad4065a47720),
10
+ [`8747e8f`](https://github.com/Ripple-TS/ripple/commit/8747e8f306628443d3c4d73bce0d79e986f5966e),
11
+ [`8747e8f`](https://github.com/Ripple-TS/ripple/commit/8747e8f306628443d3c4d73bce0d79e986f5966e)]:
12
+ - @tsrx/ripple@0.1.31
13
+ - @ripple-ts/adapter@0.3.83
14
+
15
+ ## 0.3.82
16
+
17
+ ### Patch Changes
18
+
19
+ - [`67f3794`](https://github.com/Ripple-TS/ripple/commit/67f3794d2f1ffd55dd23a47327d925d9a76a4171)
20
+ Thanks [@leonidaz](https://github.com/leonidaz)! - Compose `RenderRoute` layouts
21
+ during client hydration. The generated client entry hydrated the bare page
22
+ component, so a route's `layout` only existed in the server-rendered HTML: the
23
+ layout component never ran in the browser, its CSS was missing from the client
24
+ graph, and once the SSR style block was removed after hydration the layout's
25
+ styles disappeared (visible as a flash of unstyled content). The client entry
26
+ now loads the layout module and wraps the page the same way the server does, and
27
+ layout entries are included in the client build's static route imports so their
28
+ CSS is bundled.
29
+ - Updated dependencies []:
30
+ - @tsrx/ripple@0.1.30
31
+ - @ripple-ts/adapter@0.3.82
32
+
3
33
  ## 0.3.81
4
34
 
5
35
  ### Patch Changes
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Vite plugin for Ripple",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.3.81",
6
+ "version": "0.3.83",
7
7
  "type": "module",
8
8
  "module": "src/index.js",
9
9
  "main": "src/index.js",
@@ -32,14 +32,14 @@
32
32
  "url": "https://github.com/Ripple-TS/ripple/issues"
33
33
  },
34
34
  "dependencies": {
35
- "@ripple-ts/adapter": "0.3.81",
36
- "@tsrx/ripple": "0.1.29"
35
+ "@tsrx/ripple": "0.1.31",
36
+ "@ripple-ts/adapter": "0.3.83"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^24.3.0",
40
40
  "type-fest": "^5.6.0",
41
41
  "vite": "^8.0.12",
42
- "ripple": "0.3.81"
42
+ "ripple": "0.3.83"
43
43
  },
44
44
  "publishConfig": {
45
45
  "access": "public"
package/src/index.js CHANGED
@@ -529,8 +529,7 @@ export function ripple(inlineOptions = {}) {
529
529
 
530
530
  renderRouteEntries = loadedRippleConfig.router.routes
531
531
  .filter((/** @type {Route} */ r) => r.type === 'render')
532
- .map((/** @type {RenderRoute} */ r) => r.entry)
533
- .map(get_route_entry_path)
532
+ .flatMap((/** @type {RenderRoute} */ r) => [get_route_entry_path(r.entry), r.layout])
534
533
  .filter((entry) => typeof entry === 'string');
535
534
 
536
535
  // Deduplicate entries (multiple routes can share the same component)
@@ -106,33 +106,44 @@ async function resolveRouteComponent(data) {
106
106
  if (!entryPath) return null;
107
107
 
108
108
  const loadModule = routeModules[entryPath] ?? (() => import(/* @vite-ignore */ entryPath));
109
- return getComponentExport(await loadModule(), exportName);
109
+ const Component = getComponentExport(await loadModule(), exportName);
110
+ if (!Component) return null;
111
+
112
+ // Load the route layout so hydration sees the same component tree as the
113
+ // server render and the layout's CSS is part of the client graph.
114
+ const layoutPath = typeof route?.layout === 'string' ? route.layout : undefined;
115
+ if (layoutPath) {
116
+ const loadLayout = routeModules[layoutPath] ?? (() => import(/* @vite-ignore */ layoutPath));
117
+ const Layout = getComponentExport(await loadLayout());
118
+ if (Layout) return { Component, Layout };
119
+ }
120
+
121
+ return { Component };
110
122
  }
111
123
 
112
124
  (async () => {
113
125
  try {
114
126
  const data = JSON.parse(document.getElementById('__ripple_data').textContent);
115
127
  const target = document.getElementById('root');
116
- const Component = await resolveRouteComponent(data);
128
+ const resolved = await resolveRouteComponent(data);
117
129
 
118
- if (!Component || !target) {
130
+ if (!resolved || !target) {
119
131
  console.error('[ripple] Unable to hydrate route: missing component export or #root target.');
120
132
  return;
121
133
  }
122
134
 
135
+ // With a layout, hydrate the layout and pass the page as its children
136
+ // prop — the same tree the server rendered.
137
+ const { Component, Layout } = resolved;
138
+ const pageProps = { params: data.params };
139
+ const root = Layout ?? Component;
140
+ const props = Layout ? { ...pageProps, children: () => Component(pageProps) } : pageProps;
141
+
123
142
  try {
124
- hydrate(Component, {
125
- target,
126
- props: { params: data.params },
127
- rootBoundary,
128
- });
143
+ hydrate(root, { target, props, rootBoundary });
129
144
  } catch (error) {
130
145
  console.warn('[ripple] Hydration failed, falling back to mount.', error);
131
- mount(Component, {
132
- target,
133
- props: { params: data.params },
134
- rootBoundary,
135
- });
146
+ mount(root, { target, props, rootBoundary });
136
147
  }
137
148
  } catch (error) {
138
149
  console.error('[ripple] Failed to bootstrap client hydration.', error);
@@ -17,7 +17,7 @@ describe('project codegen', () => {
17
17
  expect(source).toContain('function getRouteEntryExportName(entry)');
18
18
  expect(source).toContain('return Array.isArray(entry) ? entry[0] : undefined;');
19
19
  expect(source).toContain('const rootBoundary = rippleConfig.rootBoundary;');
20
- expect(source).toContain('rootBoundary,');
20
+ expect(source).toContain('hydrate(root, { target, props, rootBoundary });');
21
21
  });
22
22
 
23
23
  it('generates server components from named entry tuples', () => {