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