@nextsparkjs/core 0.1.0-beta.132 → 0.1.0-beta.134
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/components/public/pageBuilder/PageRenderer.d.ts +6 -1
- package/dist/components/public/pageBuilder/PageRenderer.d.ts.map +1 -1
- package/dist/components/public/pageBuilder/PageRenderer.js +3 -10
- package/dist/lib/blocks/loader.d.ts +9 -0
- package/dist/lib/blocks/loader.d.ts.map +1 -1
- package/dist/lib/blocks/loader.js +9 -1
- package/dist/styles/classes.json +1 -1
- package/package.json +2 -2
- package/scripts/build/registry/generators/block-registry.mjs +20 -0
- package/scripts/build/registry/generators/plugin-registry.mjs +1 -1
- package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.ts +2 -0
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
* PageRenderer Component
|
|
3
3
|
*
|
|
4
4
|
* Renders pages from the Page Builder by iterating over blocks
|
|
5
|
-
* and
|
|
5
|
+
* and loading block components from the SSR registry.
|
|
6
|
+
*
|
|
7
|
+
* Block components are loaded via next/dynamic (ssr: true) for per-block
|
|
8
|
+
* code splitting. Each block gets its own JS chunk — only blocks used on
|
|
9
|
+
* the page have their JS loaded by the browser. SSR renders full HTML
|
|
10
|
+
* so content is visible without client JS (SEO-safe).
|
|
6
11
|
*
|
|
7
12
|
* @module core/components/public/pageBuilder
|
|
8
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageRenderer.d.ts","sourceRoot":"","sources":["../../../../src/components/public/pageBuilder/PageRenderer.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"PageRenderer.d.ts","sourceRoot":"","sources":["../../../../src/components/public/pageBuilder/PageRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAsC1D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAA;QACV,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,aAAa,EAAE,CAAA;QACvB,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,iBAAiB,2CA+BvD"}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Suspense } from "react";
|
|
3
|
-
import {
|
|
4
|
-
function BlockSkeleton() {
|
|
5
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full py-12 px-4 animate-pulse", children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto", children: [
|
|
6
|
-
/* @__PURE__ */ jsx("div", { className: "h-8 bg-muted rounded w-3/4 mb-4" }),
|
|
7
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-full mb-2" }),
|
|
8
|
-
/* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-5/6" })
|
|
9
|
-
] }) });
|
|
10
|
-
}
|
|
3
|
+
import { getBlockComponentSSR, normalizeBlockProps } from "../../../lib/blocks/loader.js";
|
|
11
4
|
function BlockError({ blockSlug }) {
|
|
12
5
|
return /* @__PURE__ */ jsx("div", { className: "w-full py-12 px-4 bg-destructive/10 border border-destructive/20 rounded", children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto text-center", children: [
|
|
13
6
|
/* @__PURE__ */ jsxs("p", { className: "text-destructive", children: [
|
|
@@ -18,13 +11,13 @@ function BlockError({ blockSlug }) {
|
|
|
18
11
|
] }) });
|
|
19
12
|
}
|
|
20
13
|
function BlockRenderer({ block }) {
|
|
21
|
-
const BlockComponent =
|
|
14
|
+
const BlockComponent = getBlockComponentSSR(block.blockSlug);
|
|
22
15
|
if (!BlockComponent) {
|
|
23
16
|
console.warn(`Block component not found for slug: ${block.blockSlug}`);
|
|
24
17
|
return /* @__PURE__ */ jsx(BlockError, { blockSlug: block.blockSlug });
|
|
25
18
|
}
|
|
26
19
|
const normalizedProps = normalizeBlockProps(block.props);
|
|
27
|
-
return /* @__PURE__ */ jsx(Suspense, {
|
|
20
|
+
return /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(BlockComponent, { ...normalizedProps }) });
|
|
28
21
|
}
|
|
29
22
|
function PageRenderer({ page }) {
|
|
30
23
|
const blocks = Array.isArray(page.blocks) ? page.blocks : [];
|
|
@@ -22,6 +22,15 @@ export declare function getBlockComponents(): Record<string, BlockComponent>;
|
|
|
22
22
|
* @returns The block component or undefined if not found
|
|
23
23
|
*/
|
|
24
24
|
export declare function getBlockComponent(slug: string): BlockComponent | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Get all SSR block components (direct imports, no React.lazy)
|
|
27
|
+
* Use for public page rendering where no-JS SSR is required
|
|
28
|
+
*/
|
|
29
|
+
export declare function getBlockComponentsSSR(): Record<string, BlockComponent>;
|
|
30
|
+
/**
|
|
31
|
+
* Get a specific SSR block component by slug (direct import, no React.lazy)
|
|
32
|
+
*/
|
|
33
|
+
export declare function getBlockComponentSSR(slug: string): BlockComponent | undefined;
|
|
25
34
|
/**
|
|
26
35
|
* Check if a block exists in the registry
|
|
27
36
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/lib/blocks/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAIrC,KAAK,cAAc,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;AAExC;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgD3F"}
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/lib/blocks/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAIrC,KAAK,cAAc,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;AAExC;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAE1E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgD3F"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { BLOCK_COMPONENTS } from "@nextsparkjs/registries/block-registry";
|
|
1
|
+
import { BLOCK_COMPONENTS, BLOCK_COMPONENTS_SSR } from "@nextsparkjs/registries/block-registry";
|
|
2
2
|
function getBlockComponents() {
|
|
3
3
|
return BLOCK_COMPONENTS;
|
|
4
4
|
}
|
|
5
5
|
function getBlockComponent(slug) {
|
|
6
6
|
return BLOCK_COMPONENTS[slug];
|
|
7
7
|
}
|
|
8
|
+
function getBlockComponentsSSR() {
|
|
9
|
+
return BLOCK_COMPONENTS_SSR;
|
|
10
|
+
}
|
|
11
|
+
function getBlockComponentSSR(slug) {
|
|
12
|
+
return BLOCK_COMPONENTS_SSR[slug];
|
|
13
|
+
}
|
|
8
14
|
function hasBlock(slug) {
|
|
9
15
|
return slug in BLOCK_COMPONENTS;
|
|
10
16
|
}
|
|
@@ -48,7 +54,9 @@ function normalizeBlockProps(props) {
|
|
|
48
54
|
}
|
|
49
55
|
export {
|
|
50
56
|
getBlockComponent,
|
|
57
|
+
getBlockComponentSSR,
|
|
51
58
|
getBlockComponents,
|
|
59
|
+
getBlockComponentsSSR,
|
|
52
60
|
hasBlock,
|
|
53
61
|
normalizeBlockProps
|
|
54
62
|
};
|
package/dist/styles/classes.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextsparkjs/core",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.134",
|
|
4
4
|
"description": "NextSpark - The complete SaaS framework for Next.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "NextSpark <hello@nextspark.dev>",
|
|
@@ -462,7 +462,7 @@
|
|
|
462
462
|
"tailwind-merge": "^3.3.1",
|
|
463
463
|
"uuid": "^13.0.0",
|
|
464
464
|
"zod": "^4.1.5",
|
|
465
|
-
"@nextsparkjs/testing": "0.1.0-beta.
|
|
465
|
+
"@nextsparkjs/testing": "0.1.0-beta.134"
|
|
466
466
|
},
|
|
467
467
|
"scripts": {
|
|
468
468
|
"postinstall": "node scripts/postinstall.mjs || true",
|
|
@@ -47,6 +47,13 @@ export const BLOCK_CATEGORIES: string[] = []
|
|
|
47
47
|
|
|
48
48
|
export const BLOCK_COMPONENTS: Record<string, React.LazyExoticComponent<React.ComponentType<unknown>>> = {}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Direct-imported block components for SSR rendering
|
|
52
|
+
* No React.lazy, no Suspense — HTML is fully visible without JS
|
|
53
|
+
*/
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
export const BLOCK_COMPONENTS_SSR: Record<string, React.ComponentType<any>> = {}
|
|
56
|
+
|
|
50
57
|
export const BLOCK_METADATA = {
|
|
51
58
|
totalBlocks: 0,
|
|
52
59
|
categories: [],
|
|
@@ -120,6 +127,7 @@ export const BLOCK_METADATA = {
|
|
|
120
127
|
*/
|
|
121
128
|
|
|
122
129
|
import React from 'react'
|
|
130
|
+
import dynamic from 'next/dynamic'
|
|
123
131
|
import type { BlockConfig, BlockCategory } from '${convertCorePath('@/core/types', outputFilePath, config)}'
|
|
124
132
|
|
|
125
133
|
${fieldImports}
|
|
@@ -141,6 +149,18 @@ ${blocks.map(block => {
|
|
|
141
149
|
}).join(',\n')}
|
|
142
150
|
}
|
|
143
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Code-split block components for SSR rendering via next/dynamic.
|
|
154
|
+
* Each block is a separate JS chunk — only blocks used on the page are loaded.
|
|
155
|
+
* SSR is enabled (default) so HTML is fully visible without client JS.
|
|
156
|
+
*/
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
158
|
+
export const BLOCK_COMPONENTS_SSR: Record<string, React.ComponentType<any>> = {
|
|
159
|
+
${blocks.map(block => {
|
|
160
|
+
return ` '${block.slug}': dynamic(() => import('${block.paths.component}'), { ssr: true })`
|
|
161
|
+
}).join(',\n')}
|
|
162
|
+
}
|
|
163
|
+
|
|
144
164
|
/**
|
|
145
165
|
* Block registry metadata
|
|
146
166
|
*/
|
|
@@ -6,6 +6,8 @@ export const BLOCK_REGISTRY: Record<string, any> = {}
|
|
|
6
6
|
|
|
7
7
|
export const BLOCK_COMPONENTS: Record<string, any> = {}
|
|
8
8
|
|
|
9
|
+
export const BLOCK_COMPONENTS_SSR: Record<string, any> = {}
|
|
10
|
+
|
|
9
11
|
export const BLOCK_METADATA = {
|
|
10
12
|
generated: new Date().toISOString(),
|
|
11
13
|
totalBlocks: 0,
|