@cmssy/react 16.9.1 → 16.10.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/index.cjs +156 -0
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +155 -2
- package/dist/load-cmssy-route-BjUMTpOJ.d.cts +34 -0
- package/dist/load-cmssy-route-C9FPwUSB.d.ts +34 -0
- package/dist/spa.cjs +639 -0
- package/dist/spa.d.cts +33 -0
- package/dist/spa.d.ts +33 -0
- package/dist/spa.js +636 -0
- package/package.json +12 -2
package/dist/spa.cjs
ADDED
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var internal = require('@cmssy/core/internal');
|
|
6
|
+
var core = require('@cmssy/core');
|
|
7
|
+
var locale = require('@cmssy/core/internal/locale');
|
|
8
|
+
var blockErrorBoundary = require('@cmssy/react/block-error-boundary');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
|
|
11
|
+
function buildBlockMap(blocks) {
|
|
12
|
+
const map = /* @__PURE__ */ Object.create(null);
|
|
13
|
+
for (const block of blocks) map[block.type] = block.component;
|
|
14
|
+
return map;
|
|
15
|
+
}
|
|
16
|
+
function buildLoaderMap(blocks) {
|
|
17
|
+
const map = /* @__PURE__ */ Object.create(null);
|
|
18
|
+
for (const block of blocks) {
|
|
19
|
+
if (block.loader) map[block.type] = block.loader;
|
|
20
|
+
}
|
|
21
|
+
return map;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/components/block-error.ts
|
|
25
|
+
var BLOCK_ERROR_KEY = "__cmssyBlockError";
|
|
26
|
+
var SOURCES = [
|
|
27
|
+
"loader",
|
|
28
|
+
"render",
|
|
29
|
+
"unregistered"
|
|
30
|
+
];
|
|
31
|
+
function blockErrorMessage(err) {
|
|
32
|
+
return err instanceof Error ? err.message : String(err);
|
|
33
|
+
}
|
|
34
|
+
function unregisteredBlockError(type) {
|
|
35
|
+
return {
|
|
36
|
+
source: "unregistered",
|
|
37
|
+
message: `Block type "${type}" is not registered in this site's blocks array.`
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function markBlockError(error) {
|
|
41
|
+
return { [BLOCK_ERROR_KEY]: error };
|
|
42
|
+
}
|
|
43
|
+
function readBlockError(value) {
|
|
44
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
45
|
+
const marked = value[BLOCK_ERROR_KEY];
|
|
46
|
+
if (typeof marked !== "object" || marked === null) return void 0;
|
|
47
|
+
const { message, source } = marked;
|
|
48
|
+
if (typeof message !== "string") return void 0;
|
|
49
|
+
if (!SOURCES.includes(source)) return void 0;
|
|
50
|
+
return { message, source };
|
|
51
|
+
}
|
|
52
|
+
async function resolveFoldedBlocks(blocks, contents, loaderMap, locale, context, options) {
|
|
53
|
+
const schemas = options?.schemas;
|
|
54
|
+
if (schemas) {
|
|
55
|
+
if (options?.config) {
|
|
56
|
+
await internal.resolveRelationContent(
|
|
57
|
+
options.config,
|
|
58
|
+
blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
|
|
59
|
+
schemas,
|
|
60
|
+
locale,
|
|
61
|
+
options.workspaceId ? { workspaceId: options.workspaceId } : {}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
blocks.forEach((block, i) => {
|
|
65
|
+
const schema = schemas[block.type];
|
|
66
|
+
if (schema) internal.normalizeBlockContent(contents[i], schema);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return Promise.all(
|
|
70
|
+
blocks.map(async (block, i) => {
|
|
71
|
+
const content = contents[i];
|
|
72
|
+
const loader = loaderMap[block.type];
|
|
73
|
+
let data;
|
|
74
|
+
let error;
|
|
75
|
+
if (loader) {
|
|
76
|
+
try {
|
|
77
|
+
data = await loader({ content, context });
|
|
78
|
+
} catch (err) {
|
|
79
|
+
if (typeof console !== "undefined") {
|
|
80
|
+
console.error(
|
|
81
|
+
`[cmssy] loader for block "${block.type}" (${block.id}) failed`,
|
|
82
|
+
err
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
error = { message: blockErrorMessage(err), source: "loader" };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { content, data, error };
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context, enabledLocales, options) {
|
|
93
|
+
const contents = blocks.map(
|
|
94
|
+
(block) => internal.getBlockContentForLanguage(
|
|
95
|
+
block.content,
|
|
96
|
+
locale,
|
|
97
|
+
defaultLocale,
|
|
98
|
+
enabledLocales?.length ? enabledLocales : void 0
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
return resolveFoldedBlocks(
|
|
102
|
+
blocks,
|
|
103
|
+
contents,
|
|
104
|
+
loaderMap,
|
|
105
|
+
locale,
|
|
106
|
+
context,
|
|
107
|
+
options
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/components/resolve-block-data.ts
|
|
112
|
+
function collectBlockData(blocks, resolved, isPreview) {
|
|
113
|
+
const data = {};
|
|
114
|
+
const content = {};
|
|
115
|
+
blocks.forEach((block, index) => {
|
|
116
|
+
const entry = resolved[index];
|
|
117
|
+
if (!entry) return;
|
|
118
|
+
content[block.id] = entry.content;
|
|
119
|
+
if (entry.error && isPreview) {
|
|
120
|
+
data[block.id] = markBlockError(entry.error);
|
|
121
|
+
} else if (entry.data !== void 0) {
|
|
122
|
+
data[block.id] = entry.data;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
return { data, content };
|
|
126
|
+
}
|
|
127
|
+
async function resolveEditorBlockData({
|
|
128
|
+
page,
|
|
129
|
+
blocks,
|
|
130
|
+
locale,
|
|
131
|
+
defaultLocale,
|
|
132
|
+
enabledLocales,
|
|
133
|
+
forms,
|
|
134
|
+
isPreview = false,
|
|
135
|
+
config,
|
|
136
|
+
appContext
|
|
137
|
+
}) {
|
|
138
|
+
if (!page) return { data: {}, content: {} };
|
|
139
|
+
const loaderMap = buildLoaderMap(blocks);
|
|
140
|
+
const context = internal.buildBlockContext(
|
|
141
|
+
locale,
|
|
142
|
+
defaultLocale,
|
|
143
|
+
enabledLocales,
|
|
144
|
+
isPreview,
|
|
145
|
+
forms,
|
|
146
|
+
{ page, app: appContext }
|
|
147
|
+
);
|
|
148
|
+
const resolved = await resolveBlocks(
|
|
149
|
+
page.blocks,
|
|
150
|
+
loaderMap,
|
|
151
|
+
locale,
|
|
152
|
+
defaultLocale,
|
|
153
|
+
context,
|
|
154
|
+
enabledLocales,
|
|
155
|
+
{ schemas: core.blocksToSchemas(blocks), config }
|
|
156
|
+
);
|
|
157
|
+
return collectBlockData(page.blocks, resolved, isPreview);
|
|
158
|
+
}
|
|
159
|
+
async function resolveEditorLayoutBlockData({
|
|
160
|
+
groups,
|
|
161
|
+
blocks,
|
|
162
|
+
region,
|
|
163
|
+
page,
|
|
164
|
+
locale,
|
|
165
|
+
defaultLocale,
|
|
166
|
+
enabledLocales,
|
|
167
|
+
forms,
|
|
168
|
+
isPreview = false,
|
|
169
|
+
config,
|
|
170
|
+
appContext
|
|
171
|
+
}) {
|
|
172
|
+
const group = groups.find((g) => g.region === region);
|
|
173
|
+
const layoutBlocks = group ? group.blocks.filter((b) => b.isActive !== false).slice().sort((a, b) => a.order - b.order) : [];
|
|
174
|
+
if (layoutBlocks.length === 0) return { data: {}, content: {} };
|
|
175
|
+
const loaderMap = buildLoaderMap(blocks);
|
|
176
|
+
const context = internal.buildBlockContext(
|
|
177
|
+
locale,
|
|
178
|
+
defaultLocale,
|
|
179
|
+
enabledLocales,
|
|
180
|
+
isPreview,
|
|
181
|
+
forms,
|
|
182
|
+
{ page, app: appContext }
|
|
183
|
+
);
|
|
184
|
+
const resolved = await resolveBlocks(
|
|
185
|
+
layoutBlocks,
|
|
186
|
+
loaderMap,
|
|
187
|
+
locale,
|
|
188
|
+
defaultLocale,
|
|
189
|
+
context,
|
|
190
|
+
enabledLocales,
|
|
191
|
+
{ schemas: core.blocksToSchemas(blocks), config }
|
|
192
|
+
);
|
|
193
|
+
return collectBlockData(layoutBlocks, resolved, isPreview);
|
|
194
|
+
}
|
|
195
|
+
function layoutSlotPage(slug) {
|
|
196
|
+
return { slug, path: slug.split("/").filter(Boolean) };
|
|
197
|
+
}
|
|
198
|
+
async function resolveCmssyLayoutSlot(config, options) {
|
|
199
|
+
const {
|
|
200
|
+
region,
|
|
201
|
+
blocks,
|
|
202
|
+
editMode,
|
|
203
|
+
preview = false,
|
|
204
|
+
page: explicitPage,
|
|
205
|
+
forms,
|
|
206
|
+
appContext,
|
|
207
|
+
path,
|
|
208
|
+
locale: explicitLocale,
|
|
209
|
+
retry,
|
|
210
|
+
fetch: fetchImpl
|
|
211
|
+
} = options;
|
|
212
|
+
const requestOptions = {
|
|
213
|
+
retry: retry ?? "build",
|
|
214
|
+
...fetchImpl ? { fetch: fetchImpl } : {}
|
|
215
|
+
};
|
|
216
|
+
const siteLocales = await locale.resolveSiteLocales(config, requestOptions);
|
|
217
|
+
const fromPath = path ? locale.splitLocaleFromPath(path, siteLocales) : { locale: siteLocales.defaultLocale, path: [] };
|
|
218
|
+
const locale$1 = explicitLocale ?? fromPath.locale;
|
|
219
|
+
const slugSegments = fromPath.path ?? [];
|
|
220
|
+
const page = layoutSlotPage(explicitPage ?? "/" + slugSegments.join("/"));
|
|
221
|
+
const groups = await internal.fetchLayouts(config, page.slug, {
|
|
222
|
+
previewSecret: editMode || preview ? config.draftSecret : void 0,
|
|
223
|
+
...requestOptions
|
|
224
|
+
});
|
|
225
|
+
const base = {
|
|
226
|
+
groups,
|
|
227
|
+
settings: groups.find((g) => g.region === region)?.settings ?? null,
|
|
228
|
+
page,
|
|
229
|
+
locale: locale$1,
|
|
230
|
+
defaultLocale: siteLocales.defaultLocale,
|
|
231
|
+
enabledLocales: siteLocales.locales,
|
|
232
|
+
path: slugSegments
|
|
233
|
+
};
|
|
234
|
+
if (!editMode) return base;
|
|
235
|
+
const editorData = await resolveEditorLayoutBlockData({
|
|
236
|
+
groups,
|
|
237
|
+
blocks,
|
|
238
|
+
region,
|
|
239
|
+
page,
|
|
240
|
+
locale: locale$1,
|
|
241
|
+
defaultLocale: siteLocales.defaultLocale,
|
|
242
|
+
enabledLocales: siteLocales.locales,
|
|
243
|
+
forms,
|
|
244
|
+
isPreview: true,
|
|
245
|
+
config,
|
|
246
|
+
appContext
|
|
247
|
+
});
|
|
248
|
+
return {
|
|
249
|
+
...base,
|
|
250
|
+
data: editorData.data,
|
|
251
|
+
resolvedContent: editorData.content,
|
|
252
|
+
editorOrigin: core.resolveEditorOrigin(config.editorOrigin)
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/components/load-cmssy-route.ts
|
|
257
|
+
async function loadCmssyRoute(config, options) {
|
|
258
|
+
const {
|
|
259
|
+
blocks,
|
|
260
|
+
path,
|
|
261
|
+
locale,
|
|
262
|
+
forms,
|
|
263
|
+
appContext,
|
|
264
|
+
previewSecret,
|
|
265
|
+
isPreview = false,
|
|
266
|
+
retry,
|
|
267
|
+
fetch: fetchImpl
|
|
268
|
+
} = options;
|
|
269
|
+
const regions = options.regions ?? internal.layoutRegionIds(config.layout);
|
|
270
|
+
const firstRegion = regions[0] ?? "header";
|
|
271
|
+
const slot = await resolveCmssyLayoutSlot(config, {
|
|
272
|
+
region: firstRegion,
|
|
273
|
+
blocks,
|
|
274
|
+
editMode: false,
|
|
275
|
+
preview: isPreview,
|
|
276
|
+
forms,
|
|
277
|
+
appContext,
|
|
278
|
+
retry,
|
|
279
|
+
...fetchImpl ? { fetch: fetchImpl } : {},
|
|
280
|
+
path: path ?? [],
|
|
281
|
+
...locale === void 0 ? {} : { locale }
|
|
282
|
+
});
|
|
283
|
+
const secret = previewSecret ?? (isPreview ? config.draftSecret : void 0);
|
|
284
|
+
const page = await internal.fetchPage(config, slot.path, {
|
|
285
|
+
...secret ? { previewSecret: secret } : {},
|
|
286
|
+
...retry === void 0 ? {} : { retry },
|
|
287
|
+
...fetchImpl ? { fetch: fetchImpl } : {}
|
|
288
|
+
});
|
|
289
|
+
const shared = {
|
|
290
|
+
blocks,
|
|
291
|
+
locale: slot.locale,
|
|
292
|
+
defaultLocale: slot.defaultLocale,
|
|
293
|
+
enabledLocales: slot.enabledLocales,
|
|
294
|
+
forms,
|
|
295
|
+
isPreview,
|
|
296
|
+
config,
|
|
297
|
+
appContext
|
|
298
|
+
};
|
|
299
|
+
const [pageBlocks, ...layoutBlocks] = await Promise.all([
|
|
300
|
+
resolveEditorBlockData({ ...shared, page }),
|
|
301
|
+
...regions.map(
|
|
302
|
+
(region) => resolveEditorLayoutBlockData({
|
|
303
|
+
...shared,
|
|
304
|
+
groups: slot.groups,
|
|
305
|
+
page: slot.page,
|
|
306
|
+
region
|
|
307
|
+
})
|
|
308
|
+
)
|
|
309
|
+
]);
|
|
310
|
+
return {
|
|
311
|
+
page,
|
|
312
|
+
layouts: slot.groups,
|
|
313
|
+
pageContext: slot.page,
|
|
314
|
+
locale: slot.locale,
|
|
315
|
+
defaultLocale: slot.defaultLocale,
|
|
316
|
+
enabledLocales: slot.enabledLocales,
|
|
317
|
+
path: slot.path,
|
|
318
|
+
blockData: pageBlocks.data,
|
|
319
|
+
blockContent: pageBlocks.content,
|
|
320
|
+
layoutData: Object.fromEntries(
|
|
321
|
+
regions.map((region, index) => [region, layoutBlocks[index]])
|
|
322
|
+
),
|
|
323
|
+
regions
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
var SOURCE_LABELS = {
|
|
327
|
+
loader: "loader failed",
|
|
328
|
+
render: "render failed",
|
|
329
|
+
unregistered: "type not registered"
|
|
330
|
+
};
|
|
331
|
+
var cardStyle = {
|
|
332
|
+
boxSizing: "border-box",
|
|
333
|
+
margin: "8px 0",
|
|
334
|
+
padding: "12px 16px",
|
|
335
|
+
border: "1px dashed #ef4444",
|
|
336
|
+
borderRadius: "8px",
|
|
337
|
+
background: "rgba(239, 68, 68, 0.08)",
|
|
338
|
+
color: "#ef4444",
|
|
339
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace",
|
|
340
|
+
fontSize: "13px",
|
|
341
|
+
lineHeight: 1.5,
|
|
342
|
+
textAlign: "left"
|
|
343
|
+
};
|
|
344
|
+
var headingStyle = {
|
|
345
|
+
fontWeight: 700,
|
|
346
|
+
marginBottom: "4px"
|
|
347
|
+
};
|
|
348
|
+
var metaStyle = {
|
|
349
|
+
opacity: 0.8,
|
|
350
|
+
marginBottom: "4px"
|
|
351
|
+
};
|
|
352
|
+
var messageStyle = {
|
|
353
|
+
whiteSpace: "pre-wrap",
|
|
354
|
+
overflowWrap: "anywhere"
|
|
355
|
+
};
|
|
356
|
+
function BlockErrorCard({
|
|
357
|
+
blockType,
|
|
358
|
+
blockId,
|
|
359
|
+
error
|
|
360
|
+
}) {
|
|
361
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", "data-cmssy-block-error": error.source, style: cardStyle, children: [
|
|
362
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: headingStyle, children: [
|
|
363
|
+
'Block "',
|
|
364
|
+
blockType,
|
|
365
|
+
'" - ',
|
|
366
|
+
SOURCE_LABELS[error.source]
|
|
367
|
+
] }),
|
|
368
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: metaStyle, children: [
|
|
369
|
+
"id: ",
|
|
370
|
+
blockId
|
|
371
|
+
] }),
|
|
372
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: messageStyle, children: error.message })
|
|
373
|
+
] });
|
|
374
|
+
}
|
|
375
|
+
function foldBlockContent(block, locale, defaultLocale, patchedContent, resolvedContent) {
|
|
376
|
+
const base = resolvedContent ? { ...resolvedContent } : internal.getBlockContentForLanguage(block.content, locale, defaultLocale);
|
|
377
|
+
return patchedContent ? { ...base, ...patchedContent } : base;
|
|
378
|
+
}
|
|
379
|
+
var WARN_CAP = 256;
|
|
380
|
+
var warned = /* @__PURE__ */ new Set();
|
|
381
|
+
function UnknownBlock({ type }) {
|
|
382
|
+
if (typeof window !== "undefined" && !warned.has(type)) {
|
|
383
|
+
if (warned.size >= WARN_CAP) warned.clear();
|
|
384
|
+
warned.add(type);
|
|
385
|
+
console.error(`[cmssy] no component registered for block type "${type}"`);
|
|
386
|
+
}
|
|
387
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-cmssy-unknown-block": type });
|
|
388
|
+
}
|
|
389
|
+
function CmssyBlock({
|
|
390
|
+
block,
|
|
391
|
+
locale,
|
|
392
|
+
defaultLocale,
|
|
393
|
+
blockMap,
|
|
394
|
+
patchedContent,
|
|
395
|
+
patchedStyle,
|
|
396
|
+
patchedAdvanced,
|
|
397
|
+
resolvedContent,
|
|
398
|
+
schema,
|
|
399
|
+
editable,
|
|
400
|
+
editMode,
|
|
401
|
+
layoutRegion,
|
|
402
|
+
context,
|
|
403
|
+
data
|
|
404
|
+
}) {
|
|
405
|
+
const inEditMode = editMode ?? editable ?? false;
|
|
406
|
+
const Component = Object.hasOwn(blockMap, block.type) ? blockMap[block.type] : void 0;
|
|
407
|
+
const blockError = readBlockError(data);
|
|
408
|
+
const wrap = (children, hidden = false) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
409
|
+
"div",
|
|
410
|
+
{
|
|
411
|
+
"data-block-id": block.id,
|
|
412
|
+
"data-block-type": block.type,
|
|
413
|
+
"data-layout-region": layoutRegion,
|
|
414
|
+
draggable: editable || void 0,
|
|
415
|
+
style: hidden ? { display: "none" } : void 0,
|
|
416
|
+
children
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
if (!Component) {
|
|
420
|
+
return inEditMode ? wrap(
|
|
421
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
422
|
+
BlockErrorCard,
|
|
423
|
+
{
|
|
424
|
+
blockType: block.type,
|
|
425
|
+
blockId: block.id,
|
|
426
|
+
error: unregisteredBlockError(block.type)
|
|
427
|
+
}
|
|
428
|
+
)
|
|
429
|
+
) : wrap(/* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type }), true);
|
|
430
|
+
}
|
|
431
|
+
if (blockError) {
|
|
432
|
+
if (!inEditMode) return null;
|
|
433
|
+
return wrap(
|
|
434
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
435
|
+
BlockErrorCard,
|
|
436
|
+
{
|
|
437
|
+
blockType: block.type,
|
|
438
|
+
blockId: block.id,
|
|
439
|
+
error: blockError
|
|
440
|
+
}
|
|
441
|
+
)
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
const content = foldBlockContent(
|
|
445
|
+
block,
|
|
446
|
+
locale,
|
|
447
|
+
defaultLocale,
|
|
448
|
+
patchedContent,
|
|
449
|
+
resolvedContent
|
|
450
|
+
);
|
|
451
|
+
if (schema) internal.normalizeBlockContent(content, schema, resolvedContent);
|
|
452
|
+
const style = patchedStyle ? { ...internal.asBucket(block.style), ...patchedStyle } : internal.asBucket(block.style);
|
|
453
|
+
const advanced = patchedAdvanced ? { ...internal.asBucket(block.advanced), ...patchedAdvanced } : internal.asBucket(block.advanced);
|
|
454
|
+
return wrap(
|
|
455
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
456
|
+
blockErrorBoundary.BlockErrorBoundary,
|
|
457
|
+
{
|
|
458
|
+
blockType: block.type,
|
|
459
|
+
blockId: block.id,
|
|
460
|
+
editMode: inEditMode,
|
|
461
|
+
children: react.createElement(Component, {
|
|
462
|
+
content,
|
|
463
|
+
style,
|
|
464
|
+
advanced,
|
|
465
|
+
context,
|
|
466
|
+
data
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
)
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
function CmssyBlocks({
|
|
473
|
+
page,
|
|
474
|
+
blocks,
|
|
475
|
+
locale,
|
|
476
|
+
defaultLocale,
|
|
477
|
+
enabledLocales,
|
|
478
|
+
blockData,
|
|
479
|
+
blockContent,
|
|
480
|
+
pageContext,
|
|
481
|
+
forms,
|
|
482
|
+
auth,
|
|
483
|
+
workspace,
|
|
484
|
+
appContext,
|
|
485
|
+
isPreview = false,
|
|
486
|
+
editMode = false
|
|
487
|
+
}) {
|
|
488
|
+
if (!page) return null;
|
|
489
|
+
const blockMap = buildBlockMap(blocks);
|
|
490
|
+
const context = internal.buildBlockContext(
|
|
491
|
+
locale,
|
|
492
|
+
defaultLocale,
|
|
493
|
+
enabledLocales,
|
|
494
|
+
isPreview,
|
|
495
|
+
forms,
|
|
496
|
+
{ page: pageContext, auth, workspace, app: appContext }
|
|
497
|
+
);
|
|
498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (page.blocks ?? []).map((block) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
499
|
+
CmssyBlock,
|
|
500
|
+
{
|
|
501
|
+
block,
|
|
502
|
+
blockMap,
|
|
503
|
+
locale,
|
|
504
|
+
defaultLocale,
|
|
505
|
+
context,
|
|
506
|
+
editMode,
|
|
507
|
+
resolvedContent: blockContent?.[block.id],
|
|
508
|
+
data: blockData?.[block.id]
|
|
509
|
+
},
|
|
510
|
+
block.id
|
|
511
|
+
)) });
|
|
512
|
+
}
|
|
513
|
+
function CmssyLayoutRegion({
|
|
514
|
+
groups,
|
|
515
|
+
region,
|
|
516
|
+
blocks,
|
|
517
|
+
locale,
|
|
518
|
+
defaultLocale,
|
|
519
|
+
enabledLocales,
|
|
520
|
+
page,
|
|
521
|
+
blockData,
|
|
522
|
+
blockContent,
|
|
523
|
+
forms,
|
|
524
|
+
appContext,
|
|
525
|
+
isPreview = false,
|
|
526
|
+
editMode = false
|
|
527
|
+
}) {
|
|
528
|
+
const group = groups.find((candidate) => candidate.region === region);
|
|
529
|
+
const regionBlocks = group ? group.blocks.filter((block) => block.isActive !== false).slice().sort((a, b) => (a.order ?? 0) - (b.order ?? 0)) : [];
|
|
530
|
+
if (regionBlocks.length === 0) return null;
|
|
531
|
+
const blockMap = buildBlockMap(blocks);
|
|
532
|
+
const context = internal.buildBlockContext(
|
|
533
|
+
locale,
|
|
534
|
+
defaultLocale,
|
|
535
|
+
enabledLocales,
|
|
536
|
+
isPreview,
|
|
537
|
+
forms,
|
|
538
|
+
{ page, app: appContext }
|
|
539
|
+
);
|
|
540
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: regionBlocks.map((block) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
541
|
+
CmssyBlock,
|
|
542
|
+
{
|
|
543
|
+
block,
|
|
544
|
+
blockMap,
|
|
545
|
+
locale,
|
|
546
|
+
defaultLocale,
|
|
547
|
+
context,
|
|
548
|
+
layoutRegion: region,
|
|
549
|
+
editMode,
|
|
550
|
+
resolvedContent: blockContent?.[block.id],
|
|
551
|
+
data: blockData?.[block.id]
|
|
552
|
+
},
|
|
553
|
+
block.id
|
|
554
|
+
)) });
|
|
555
|
+
}
|
|
556
|
+
function toSegments(path) {
|
|
557
|
+
if (Array.isArray(path)) return path;
|
|
558
|
+
const value = path ?? (typeof window === "undefined" ? "/" : window.location.pathname);
|
|
559
|
+
return value.split("/").filter(Boolean);
|
|
560
|
+
}
|
|
561
|
+
function useCmssyRoute(config, options) {
|
|
562
|
+
const segments = react.useMemo(() => toSegments(options.path), [options.path]);
|
|
563
|
+
const [state, setState] = react.useState({ data: null, error: null, loading: true });
|
|
564
|
+
const [attempt, setAttempt] = react.useState(0);
|
|
565
|
+
const latest = react.useRef(0);
|
|
566
|
+
const optionsRef = react.useRef(options);
|
|
567
|
+
optionsRef.current = options;
|
|
568
|
+
react.useEffect(() => {
|
|
569
|
+
const request = ++latest.current;
|
|
570
|
+
setState((current) => ({ ...current, error: null, loading: true }));
|
|
571
|
+
loadCmssyRoute(config, { ...optionsRef.current, path: segments }).then((data) => {
|
|
572
|
+
if (request !== latest.current) return;
|
|
573
|
+
setState({ data, error: null, loading: false });
|
|
574
|
+
}).catch((cause) => {
|
|
575
|
+
if (request !== latest.current) return;
|
|
576
|
+
setState({
|
|
577
|
+
data: null,
|
|
578
|
+
error: cause instanceof Error ? cause : new Error(String(cause)),
|
|
579
|
+
loading: false
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
}, [
|
|
583
|
+
config,
|
|
584
|
+
segments.join("/"),
|
|
585
|
+
options.locale,
|
|
586
|
+
options.previewSecret,
|
|
587
|
+
options.isPreview,
|
|
588
|
+
options.regions?.join(","),
|
|
589
|
+
attempt
|
|
590
|
+
]);
|
|
591
|
+
const reload = react.useCallback(() => setAttempt((value) => value + 1), []);
|
|
592
|
+
return { ...state, reload };
|
|
593
|
+
}
|
|
594
|
+
function CmssyRoute({
|
|
595
|
+
config,
|
|
596
|
+
children,
|
|
597
|
+
fallback = null,
|
|
598
|
+
notFound = null,
|
|
599
|
+
renderError,
|
|
600
|
+
...options
|
|
601
|
+
}) {
|
|
602
|
+
const { data, error, loading } = useCmssyRoute(config, options);
|
|
603
|
+
if (error) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderError ? renderError(error) : null });
|
|
604
|
+
if (!data) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loading ? fallback : null });
|
|
605
|
+
const shared = {
|
|
606
|
+
blocks: options.blocks,
|
|
607
|
+
locale: data.locale,
|
|
608
|
+
defaultLocale: data.defaultLocale,
|
|
609
|
+
enabledLocales: data.enabledLocales,
|
|
610
|
+
forms: options.forms,
|
|
611
|
+
appContext: options.appContext,
|
|
612
|
+
isPreview: options.isPreview ?? false
|
|
613
|
+
};
|
|
614
|
+
const Blocks = () => data.page ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
615
|
+
CmssyBlocks,
|
|
616
|
+
{
|
|
617
|
+
...shared,
|
|
618
|
+
page: data.page,
|
|
619
|
+
pageContext: data.pageContext,
|
|
620
|
+
blockData: data.blockData,
|
|
621
|
+
blockContent: data.blockContent
|
|
622
|
+
}
|
|
623
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: notFound });
|
|
624
|
+
const Region = ({ id }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
625
|
+
CmssyLayoutRegion,
|
|
626
|
+
{
|
|
627
|
+
...shared,
|
|
628
|
+
groups: data.layouts,
|
|
629
|
+
region: id,
|
|
630
|
+
page: data.pageContext,
|
|
631
|
+
blockData: data.layoutData[id]?.data,
|
|
632
|
+
blockContent: data.layoutData[id]?.content
|
|
633
|
+
}
|
|
634
|
+
);
|
|
635
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children({ data, Blocks, Region }) });
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
exports.CmssyRoute = CmssyRoute;
|
|
639
|
+
exports.useCmssyRoute = useCmssyRoute;
|
package/dist/spa.d.cts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { L as LoadCmssyRouteOptions, C as CmssyRouteConfig, a as CmssyRouteData } from './load-cmssy-route-BjUMTpOJ.cjs';
|
|
4
|
+
import '@cmssy/core';
|
|
5
|
+
import './resolve-block-data-Bkracpae.cjs';
|
|
6
|
+
|
|
7
|
+
interface UseCmssyRouteOptions extends Omit<LoadCmssyRouteOptions, "path"> {
|
|
8
|
+
path?: string | string[];
|
|
9
|
+
}
|
|
10
|
+
interface CmssyRouteState {
|
|
11
|
+
data: CmssyRouteData | null;
|
|
12
|
+
error: Error | null;
|
|
13
|
+
loading: boolean;
|
|
14
|
+
reload: () => void;
|
|
15
|
+
}
|
|
16
|
+
declare function useCmssyRoute(config: CmssyRouteConfig, options: UseCmssyRouteOptions): CmssyRouteState;
|
|
17
|
+
interface CmssyRouteRenderProps {
|
|
18
|
+
data: CmssyRouteData;
|
|
19
|
+
Blocks: () => ReactNode;
|
|
20
|
+
Region: (props: {
|
|
21
|
+
id: string;
|
|
22
|
+
}) => ReactNode;
|
|
23
|
+
}
|
|
24
|
+
interface CmssyRouteProps extends UseCmssyRouteOptions {
|
|
25
|
+
config: CmssyRouteConfig;
|
|
26
|
+
children: (props: CmssyRouteRenderProps) => ReactNode;
|
|
27
|
+
fallback?: ReactNode;
|
|
28
|
+
notFound?: ReactNode;
|
|
29
|
+
renderError?: (error: Error) => ReactNode;
|
|
30
|
+
}
|
|
31
|
+
declare function CmssyRoute({ config, children, fallback, notFound, renderError, ...options }: CmssyRouteProps): react_jsx_runtime.JSX.Element;
|
|
32
|
+
|
|
33
|
+
export { CmssyRoute, type CmssyRouteProps, type CmssyRouteRenderProps, type CmssyRouteState, type UseCmssyRouteOptions, useCmssyRoute };
|
package/dist/spa.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { L as LoadCmssyRouteOptions, C as CmssyRouteConfig, a as CmssyRouteData } from './load-cmssy-route-C9FPwUSB.js';
|
|
4
|
+
import '@cmssy/core';
|
|
5
|
+
import './resolve-block-data-Bkracpae.js';
|
|
6
|
+
|
|
7
|
+
interface UseCmssyRouteOptions extends Omit<LoadCmssyRouteOptions, "path"> {
|
|
8
|
+
path?: string | string[];
|
|
9
|
+
}
|
|
10
|
+
interface CmssyRouteState {
|
|
11
|
+
data: CmssyRouteData | null;
|
|
12
|
+
error: Error | null;
|
|
13
|
+
loading: boolean;
|
|
14
|
+
reload: () => void;
|
|
15
|
+
}
|
|
16
|
+
declare function useCmssyRoute(config: CmssyRouteConfig, options: UseCmssyRouteOptions): CmssyRouteState;
|
|
17
|
+
interface CmssyRouteRenderProps {
|
|
18
|
+
data: CmssyRouteData;
|
|
19
|
+
Blocks: () => ReactNode;
|
|
20
|
+
Region: (props: {
|
|
21
|
+
id: string;
|
|
22
|
+
}) => ReactNode;
|
|
23
|
+
}
|
|
24
|
+
interface CmssyRouteProps extends UseCmssyRouteOptions {
|
|
25
|
+
config: CmssyRouteConfig;
|
|
26
|
+
children: (props: CmssyRouteRenderProps) => ReactNode;
|
|
27
|
+
fallback?: ReactNode;
|
|
28
|
+
notFound?: ReactNode;
|
|
29
|
+
renderError?: (error: Error) => ReactNode;
|
|
30
|
+
}
|
|
31
|
+
declare function CmssyRoute({ config, children, fallback, notFound, renderError, ...options }: CmssyRouteProps): react_jsx_runtime.JSX.Element;
|
|
32
|
+
|
|
33
|
+
export { CmssyRoute, type CmssyRouteProps, type CmssyRouteRenderProps, type CmssyRouteState, type UseCmssyRouteOptions, useCmssyRoute };
|