@shop-on/theme-react 0.4.0 → 0.5.0
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/template-renderer.js +46 -17
- package/package.json +3 -3
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { escapeAttrValue, scopeCustomCss } from "./custom-css.js";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { createContext, createElement, useContext, useEffect } from "react";
|
|
4
|
-
import { collectTypes, selectRenderableChildren, selectRenderableSections } from "@shop-on/theme-contract";
|
|
4
|
+
import { MAX_APP_BLOCK_CONTAINER_DEPTH, collectTypes, selectRenderableChildren, selectRenderableSections } from "@shop-on/theme-contract";
|
|
5
5
|
import { rootRouteId, useMatch } from "@tanstack/react-router";
|
|
6
6
|
//#region src/template-renderer.tsx
|
|
7
7
|
const EMPTY_BLOCK_PATH = [];
|
|
8
8
|
const SectionIdContext = createContext(void 0);
|
|
9
9
|
const BlockPathContext = createContext(EMPTY_BLOCK_PATH);
|
|
10
|
+
const BlockDepthContext = createContext(void 0);
|
|
10
11
|
const appScriptPromises = /* @__PURE__ */ new Map();
|
|
11
12
|
function loadAppScript(src) {
|
|
12
13
|
const cached = appScriptPromises.get(src);
|
|
13
14
|
if (cached) return cached;
|
|
14
15
|
const p = new Promise((resolve, reject) => {
|
|
15
16
|
if (typeof window === "undefined") return resolve();
|
|
16
|
-
const existing = document.querySelector(`script[data-app-bundle="${src}"]`);
|
|
17
|
+
const existing = document.querySelector(`script[data-app-bundle="${CSS.escape(src)}"]`);
|
|
17
18
|
if (existing) {
|
|
18
19
|
existing.addEventListener("load", () => resolve(), { once: true });
|
|
19
20
|
existing.addEventListener("error", () => reject(/* @__PURE__ */ new Error("app-script-load-failed")), { once: true });
|
|
@@ -46,21 +47,31 @@ function useShopHandle() {
|
|
|
46
47
|
select: (match) => shopHandleOf(match.loaderData)
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
|
-
function
|
|
50
|
-
const { tag, scriptUrl } = section;
|
|
51
|
-
const settings = section.settings ?? {};
|
|
50
|
+
function AppElement({ tag, scriptUrl, settings, kind, instanceId }) {
|
|
52
51
|
const shopHandle = useShopHandle();
|
|
53
52
|
useEffect(() => {
|
|
54
53
|
if (scriptUrl) loadAppScript(scriptUrl).catch(() => {});
|
|
55
54
|
}, [scriptUrl]);
|
|
56
|
-
if (!tag) return null;
|
|
57
55
|
return createElement(tag, {
|
|
58
|
-
"data-settings": JSON.stringify(settings),
|
|
59
|
-
|
|
56
|
+
"data-settings": JSON.stringify(settings ?? {}),
|
|
57
|
+
[`data-app-${kind}-id`]: instanceId,
|
|
60
58
|
"data-shop-handle": shopHandle,
|
|
61
59
|
suppressHydrationWarning: true
|
|
62
60
|
});
|
|
63
61
|
}
|
|
62
|
+
function DefaultAppSection({ section, sectionId }) {
|
|
63
|
+
if (!section.tag) return null;
|
|
64
|
+
return /* @__PURE__ */ jsx(AppElement, {
|
|
65
|
+
tag: section.tag,
|
|
66
|
+
scriptUrl: section.scriptUrl,
|
|
67
|
+
settings: section.settings,
|
|
68
|
+
kind: "section",
|
|
69
|
+
instanceId: sectionId
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function mountsAppBlock(block, depth) {
|
|
73
|
+
return !!block.id && depth !== void 0 && depth <= MAX_APP_BLOCK_CONTAINER_DEPTH && !block.static && !!block.tag && block.type.startsWith("app-");
|
|
74
|
+
}
|
|
64
75
|
/** `collectTypes` over every template, merged. */
|
|
65
76
|
function collectTemplateTypes(templates) {
|
|
66
77
|
const sections = /* @__PURE__ */ new Set();
|
|
@@ -109,6 +120,7 @@ function createTemplateRenderer(loaders, opts) {
|
|
|
109
120
|
async function preloadBlocks(args) {
|
|
110
121
|
const types = /* @__PURE__ */ new Set();
|
|
111
122
|
const visit = (b) => {
|
|
123
|
+
if (b.source === "app") return;
|
|
112
124
|
types.add(b.type);
|
|
113
125
|
if (b.blocks) for (const child of Object.values(b.blocks)) visit(child);
|
|
114
126
|
};
|
|
@@ -143,9 +155,12 @@ function createTemplateRenderer(loaders, opts) {
|
|
|
143
155
|
style: { display: "contents" },
|
|
144
156
|
children: /* @__PURE__ */ jsx(SectionIdContext.Provider, {
|
|
145
157
|
value: instanceId,
|
|
146
|
-
children: /* @__PURE__ */
|
|
158
|
+
children: /* @__PURE__ */ jsx(BlockPathContext.Provider, {
|
|
147
159
|
value: EMPTY_BLOCK_PATH,
|
|
148
|
-
children:
|
|
160
|
+
children: /* @__PURE__ */ jsxs(BlockDepthContext.Provider, {
|
|
161
|
+
value: 0,
|
|
162
|
+
children: [sectionCss ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: sectionCss } }) : null, renderSectionBody(section, instanceId, groupType, blocks, staticBlocks)]
|
|
163
|
+
})
|
|
149
164
|
})
|
|
150
165
|
})
|
|
151
166
|
}, instanceId);
|
|
@@ -182,14 +197,23 @@ function createTemplateRenderer(loaders, opts) {
|
|
|
182
197
|
children: renderSections(template.sections, template.order)
|
|
183
198
|
});
|
|
184
199
|
}
|
|
200
|
+
function renderThemeBlock(block) {
|
|
201
|
+
const BlockComponent = resolveBlock(block.type);
|
|
202
|
+
return /* @__PURE__ */ jsx(BlockComponent, {
|
|
203
|
+
...block.settings,
|
|
204
|
+
blockId: block.id,
|
|
205
|
+
blocks: selectRenderableChildren(block)
|
|
206
|
+
});
|
|
207
|
+
}
|
|
185
208
|
function BlockRenderer({ blocks, parentBlockId }) {
|
|
186
209
|
const sectionId = useContext(SectionIdContext);
|
|
187
210
|
const inheritedPath = useContext(BlockPathContext);
|
|
188
211
|
const containerPath = inheritedPath.length > 0 ? inheritedPath : parentBlockId ? [parentBlockId] : EMPTY_BLOCK_PATH;
|
|
212
|
+
const depth = useContext(BlockDepthContext);
|
|
189
213
|
return /* @__PURE__ */ jsx(Fragment, { children: blocks.map((block, i) => {
|
|
190
214
|
if (block.disabled) return null;
|
|
191
|
-
const
|
|
192
|
-
|
|
215
|
+
const isApp = block.source === "app";
|
|
216
|
+
if (isApp && !mountsAppBlock(block, depth)) return null;
|
|
193
217
|
const key = block.id ?? `${block.type}-${i}`;
|
|
194
218
|
const ownPath = block.id ? [...containerPath, block.id] : containerPath;
|
|
195
219
|
const blockCss = block.id && sectionId ? scopeCustomCss(`[data-editor-section-id="${escapeAttrValue(sectionId)}"] ${containerPath.map((seg) => `[data-editor-block-id="${escapeAttrValue(seg)}"] `).join("")}[data-editor-block-id="${escapeAttrValue(block.id)}"]`, block.custom_css) : null;
|
|
@@ -197,12 +221,17 @@ function createTemplateRenderer(loaders, opts) {
|
|
|
197
221
|
"data-editor-block-id": block.id || void 0,
|
|
198
222
|
className: `block-${block.type.replace(/^_/, "")}`,
|
|
199
223
|
style: { display: "contents" },
|
|
200
|
-
children: [blockCss ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: blockCss } }) : null, /* @__PURE__ */ jsx(
|
|
224
|
+
children: [blockCss ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: blockCss } }) : null, isApp ? /* @__PURE__ */ jsx(AppElement, {
|
|
225
|
+
tag: block.tag,
|
|
226
|
+
scriptUrl: block.scriptUrl,
|
|
227
|
+
settings: block.settings,
|
|
228
|
+
kind: "block",
|
|
229
|
+
instanceId: block.id
|
|
230
|
+
}) : /* @__PURE__ */ jsx(BlockPathContext.Provider, {
|
|
201
231
|
value: ownPath,
|
|
202
|
-
children: /* @__PURE__ */ jsx(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
blocks: children
|
|
232
|
+
children: /* @__PURE__ */ jsx(BlockDepthContext.Provider, {
|
|
233
|
+
value: depth === void 0 ? void 0 : depth + 1,
|
|
234
|
+
children: renderThemeBlock(block)
|
|
206
235
|
})
|
|
207
236
|
})]
|
|
208
237
|
}, key);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shop-on/theme-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"license": "SEE LICENSE IN dist/LICENSE.md",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"./package.json": "./package.json"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@shop-on/theme-contract": "0.
|
|
35
|
-
"@shop-on/theme-runtime": "0.
|
|
34
|
+
"@shop-on/theme-contract": "0.5.0",
|
|
35
|
+
"@shop-on/theme-runtime": "0.5.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@tanstack/react-router": "1.170.45",
|