@nestjs-ssr/react 0.3.4 → 0.3.5

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.
@@ -25,6 +25,13 @@ export function getRootLayout(): React.ComponentType<any> | null {
25
25
  * Layouts are passed from the RenderInterceptor based on decorators.
26
26
  * Each layout is wrapped with data-layout and data-outlet attributes
27
27
  * for client-side navigation segment swapping.
28
+ *
29
+ * The layouts array is ordered [RootLayout, ControllerLayout, MethodLayout] (outer to inner).
30
+ * We iterate in REVERSE order because wrapping happens inside-out:
31
+ * - Start with Page
32
+ * - Wrap with innermost layout first (MethodLayout)
33
+ * - Then wrap with ControllerLayout
34
+ * - Finally wrap with RootLayout (outermost)
28
35
  */
29
36
  function composeWithLayouts(
30
37
  ViewComponent: React.ComponentType<any>,
@@ -35,11 +42,12 @@ function composeWithLayouts(
35
42
  // Start with the page component
36
43
  let result = <ViewComponent {...props} />;
37
44
 
38
- // Wrap with each layout in the chain (outermost to innermost in array)
39
- // We iterate normally because layouts are already in correct order from interceptor
45
+ // Wrap with each layout in REVERSE order (innermost to outermost)
46
+ // This produces the correct nesting: RootLayout > ControllerLayout > Page
40
47
  // Pass context to layouts so they can access path, params, etc. for navigation
41
48
  // Each layout gets data-layout attribute and children are wrapped in data-outlet
42
- for (const { layout: Layout, props: layoutProps } of layouts) {
49
+ for (let i = layouts.length - 1; i >= 0; i--) {
50
+ const { layout: Layout, props: layoutProps } = layouts[i];
43
51
  const layoutName = Layout.displayName || Layout.name || 'Layout';
44
52
  result = (
45
53
  <div data-layout={layoutName}>
@@ -80,19 +88,28 @@ export function renderComponent(
80
88
  }
81
89
 
82
90
  /**
83
- * Render just the page component for segment navigation.
84
- * No layout wrappers - the layout already exists on the client.
91
+ * Render a segment for client-side navigation.
92
+ * Includes any layouts below the swap target (e.g., nested layouts).
93
+ * The swap target's outlet will receive this rendered content.
85
94
  */
86
95
  export function renderSegment(
87
96
  ViewComponent: React.ComponentType<any>,
88
97
  data: any,
89
98
  ) {
90
- const { data: pageData, __context: context } = data;
99
+ const { data: pageData, __context: context, __layouts: layouts } = data;
100
+
101
+ // Compose with filtered layouts (layouts below the swap target)
102
+ const composedElement = composeWithLayouts(
103
+ ViewComponent,
104
+ pageData,
105
+ layouts,
106
+ context,
107
+ );
91
108
 
92
- // Render just the page component, no layout wrappers
109
+ // Wrap with PageContextProvider to make context available via hooks
93
110
  const element = (
94
111
  <PageContextProvider context={context}>
95
- <ViewComponent {...pageData} />
112
+ {composedElement}
96
113
  </PageContextProvider>
97
114
  );
98
115