@cmssy/next 10.10.0 → 11.0.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/server.cjs CHANGED
@@ -255,18 +255,19 @@ async function CmssyLayoutSlot({
255
255
  blocks,
256
256
  position,
257
257
  path,
258
+ locale: explicitLocale,
259
+ editMode,
258
260
  page = "/",
259
261
  editable: Editable,
260
262
  appContext
261
263
  }) {
262
- const editMode = await isCmssyEditMode();
263
264
  const [groups, siteLocales] = await Promise.all([
264
265
  internal.fetchLayouts(config, page, {
265
266
  previewSecret: editMode ? config.draftSecret : void 0
266
267
  }),
267
268
  locale.resolveSiteLocales(config)
268
269
  ]);
269
- const locale$1 = path ? locale.splitLocaleFromPath(path, siteLocales).locale : await localeFromHeader(siteLocales.defaultLocale);
270
+ const locale$1 = explicitLocale ?? locale.splitLocaleFromPath(path ?? [], siteLocales).locale;
270
271
  if (!editMode) {
271
272
  return /* @__PURE__ */ jsxRuntime.jsx(
272
273
  react.CmssyServerLayout,
@@ -309,10 +310,6 @@ async function CmssyLayoutSlot({
309
310
  }
310
311
  );
311
312
  }
312
- async function localeFromHeader(defaultLocale) {
313
- const { headers: headers3 } = await import('next/headers');
314
- return (await headers3()).get(locale.CMSSY_LOCALE_HEADER) || defaultLocale;
315
- }
316
313
 
317
314
  exports.CmssyLayoutSlot = CmssyLayoutSlot;
318
315
  exports.createCmssyEditPage = createCmssyEditPage;
package/dist/server.d.cts CHANGED
@@ -12,7 +12,7 @@ declare function createDraftRoute(config: CmssyDraftRouteConfig): (request: Requ
12
12
 
13
13
  declare function isCmssyEditMode(): Promise<boolean>;
14
14
 
15
- interface CmssyLayoutSlotProps {
15
+ interface CmssyLayoutSlotBaseProps {
16
16
  config: CmssyConfig;
17
17
  blocks: BlockDefinition[];
18
18
  /**
@@ -22,16 +22,15 @@ interface CmssyLayoutSlotProps {
22
22
  */
23
23
  position: LayoutPosition;
24
24
  /**
25
- * The catch-all segments of the route rendering this slot, **as routed**.
26
- * The language prefix in them IS the language, and reading it here keeps the
27
- * route statically renderable.
25
+ * Whether to render through the edit bridge. A parameter rather than a
26
+ * lookup: every way of asking the request - `headers()`, `draftMode()` - is a
27
+ * dynamic API, and one read makes the whole route uncacheable. The route
28
+ * segment already knows the answer, so it passes it.
28
29
  *
29
- * Omit it only where there are no params to read - a root layout - and the
30
- * language falls back to the header the middleware set, which means calling
31
- * `headers()` and giving up static rendering for the whole route. The version
32
- * of this component removed in 10.0 had no choice about that; this one does.
30
+ * Required on purpose. A slot that guessed `false` in an edit route would
31
+ * wrap draft content in published chrome, and nothing would report it.
33
32
  */
34
- path?: string[];
33
+ editMode: boolean;
35
34
  /** The page whose layout to render. Defaults to the site-wide header/footer. */
36
35
  page?: string;
37
36
  /**
@@ -58,6 +57,24 @@ interface CmssyLayoutSlotProps {
58
57
  /** Forwarded untouched to every block as `context.app`. */
59
58
  appContext?: Record<string, unknown>;
60
59
  }
60
+ /**
61
+ * Where the language comes from - one of two, never neither.
62
+ *
63
+ * `path` is the catch-all segments **as routed**: the language prefix in them
64
+ * IS the language, and reading it costs the route nothing. A caller with no
65
+ * params (a root layout) has to resolve the language itself and pass `locale`;
66
+ * there is deliberately no fallback to the request header, because a static
67
+ * route never sees the header the proxy set and would render the wrong
68
+ * language while looking like it worked.
69
+ */
70
+ type CmssyLayoutSlotLocaleSource = {
71
+ path: string[];
72
+ locale?: never;
73
+ } | {
74
+ locale: string;
75
+ path?: never;
76
+ };
77
+ type CmssyLayoutSlotProps = CmssyLayoutSlotBaseProps & CmssyLayoutSlotLocaleSource;
61
78
  /**
62
79
  * The site-wide header and footer, which are layout **blocks** rather than
63
80
  * markup the app owns. Rendered the way each mode needs them:
@@ -72,6 +89,6 @@ interface CmssyLayoutSlotProps {
72
89
  * app that wrote this by hand between 10.0 and 10.9 got at least one of the
73
90
  * three wrong, which is why it is back.
74
91
  */
75
- declare function CmssyLayoutSlot({ config, blocks, position, path, page, editable: Editable, appContext, }: CmssyLayoutSlotProps): Promise<react_jsx_runtime.JSX.Element>;
92
+ declare function CmssyLayoutSlot({ config, blocks, position, path, locale: explicitLocale, editMode, page, editable: Editable, appContext, }: CmssyLayoutSlotProps): Promise<react_jsx_runtime.JSX.Element>;
76
93
 
77
94
  export { type CmssyDraftRouteConfig, CmssyLayoutSlot, type CmssyLayoutSlotProps, createDraftRoute, isCmssyEditMode };
package/dist/server.d.ts CHANGED
@@ -12,7 +12,7 @@ declare function createDraftRoute(config: CmssyDraftRouteConfig): (request: Requ
12
12
 
13
13
  declare function isCmssyEditMode(): Promise<boolean>;
14
14
 
15
- interface CmssyLayoutSlotProps {
15
+ interface CmssyLayoutSlotBaseProps {
16
16
  config: CmssyConfig;
17
17
  blocks: BlockDefinition[];
18
18
  /**
@@ -22,16 +22,15 @@ interface CmssyLayoutSlotProps {
22
22
  */
23
23
  position: LayoutPosition;
24
24
  /**
25
- * The catch-all segments of the route rendering this slot, **as routed**.
26
- * The language prefix in them IS the language, and reading it here keeps the
27
- * route statically renderable.
25
+ * Whether to render through the edit bridge. A parameter rather than a
26
+ * lookup: every way of asking the request - `headers()`, `draftMode()` - is a
27
+ * dynamic API, and one read makes the whole route uncacheable. The route
28
+ * segment already knows the answer, so it passes it.
28
29
  *
29
- * Omit it only where there are no params to read - a root layout - and the
30
- * language falls back to the header the middleware set, which means calling
31
- * `headers()` and giving up static rendering for the whole route. The version
32
- * of this component removed in 10.0 had no choice about that; this one does.
30
+ * Required on purpose. A slot that guessed `false` in an edit route would
31
+ * wrap draft content in published chrome, and nothing would report it.
33
32
  */
34
- path?: string[];
33
+ editMode: boolean;
35
34
  /** The page whose layout to render. Defaults to the site-wide header/footer. */
36
35
  page?: string;
37
36
  /**
@@ -58,6 +57,24 @@ interface CmssyLayoutSlotProps {
58
57
  /** Forwarded untouched to every block as `context.app`. */
59
58
  appContext?: Record<string, unknown>;
60
59
  }
60
+ /**
61
+ * Where the language comes from - one of two, never neither.
62
+ *
63
+ * `path` is the catch-all segments **as routed**: the language prefix in them
64
+ * IS the language, and reading it costs the route nothing. A caller with no
65
+ * params (a root layout) has to resolve the language itself and pass `locale`;
66
+ * there is deliberately no fallback to the request header, because a static
67
+ * route never sees the header the proxy set and would render the wrong
68
+ * language while looking like it worked.
69
+ */
70
+ type CmssyLayoutSlotLocaleSource = {
71
+ path: string[];
72
+ locale?: never;
73
+ } | {
74
+ locale: string;
75
+ path?: never;
76
+ };
77
+ type CmssyLayoutSlotProps = CmssyLayoutSlotBaseProps & CmssyLayoutSlotLocaleSource;
61
78
  /**
62
79
  * The site-wide header and footer, which are layout **blocks** rather than
63
80
  * markup the app owns. Rendered the way each mode needs them:
@@ -72,6 +89,6 @@ interface CmssyLayoutSlotProps {
72
89
  * app that wrote this by hand between 10.0 and 10.9 got at least one of the
73
90
  * three wrong, which is why it is back.
74
91
  */
75
- declare function CmssyLayoutSlot({ config, blocks, position, path, page, editable: Editable, appContext, }: CmssyLayoutSlotProps): Promise<react_jsx_runtime.JSX.Element>;
92
+ declare function CmssyLayoutSlot({ config, blocks, position, path, locale: explicitLocale, editMode, page, editable: Editable, appContext, }: CmssyLayoutSlotProps): Promise<react_jsx_runtime.JSX.Element>;
76
93
 
77
94
  export { type CmssyDraftRouteConfig, CmssyLayoutSlot, type CmssyLayoutSlotProps, createDraftRoute, isCmssyEditMode };
package/dist/server.js CHANGED
@@ -7,7 +7,7 @@ import { resolveEditorBlockData } from '@cmssy/react/internal-server';
7
7
  import { isDevelopment, resolveSiteLocales, splitLocaleFromPath, fetchPage, resolveForms, toCspOrigin, cmssySecretsMatch, fetchLayouts } from '@cmssy/core/internal';
8
8
  import { CMSSY_SECRET_QUERY_PARAM, resolveEditorOrigin, CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM } from '@cmssy/core';
9
9
  import { jsx } from 'react/jsx-runtime';
10
- import { resolveSiteLocales as resolveSiteLocales$1, splitLocaleFromPath as splitLocaleFromPath$1, CMSSY_LOCALE_HEADER } from '@cmssy/core/internal/locale';
10
+ import { resolveSiteLocales as resolveSiteLocales$1, splitLocaleFromPath as splitLocaleFromPath$1 } from '@cmssy/core/internal/locale';
11
11
 
12
12
  // src/server.ts
13
13
  function hasEditFlag(value) {
@@ -253,18 +253,19 @@ async function CmssyLayoutSlot({
253
253
  blocks,
254
254
  position,
255
255
  path,
256
+ locale: explicitLocale,
257
+ editMode,
256
258
  page = "/",
257
259
  editable: Editable,
258
260
  appContext
259
261
  }) {
260
- const editMode = await isCmssyEditMode();
261
262
  const [groups, siteLocales] = await Promise.all([
262
263
  fetchLayouts(config, page, {
263
264
  previewSecret: editMode ? config.draftSecret : void 0
264
265
  }),
265
266
  resolveSiteLocales$1(config)
266
267
  ]);
267
- const locale = path ? splitLocaleFromPath$1(path, siteLocales).locale : await localeFromHeader(siteLocales.defaultLocale);
268
+ const locale = explicitLocale ?? splitLocaleFromPath$1(path ?? [], siteLocales).locale;
268
269
  if (!editMode) {
269
270
  return /* @__PURE__ */ jsx(
270
271
  CmssyServerLayout,
@@ -307,9 +308,5 @@ async function CmssyLayoutSlot({
307
308
  }
308
309
  );
309
310
  }
310
- async function localeFromHeader(defaultLocale) {
311
- const { headers: headers3 } = await import('next/headers');
312
- return (await headers3()).get(CMSSY_LOCALE_HEADER) || defaultLocale;
313
- }
314
311
 
315
312
  export { CmssyLayoutSlot, createCmssyEditPage, createCmssyPage, createDraftRoute, isCmssyEditMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/next",
3
- "version": "10.10.0",
3
+ "version": "11.0.0",
4
4
  "description": "Next.js App Router bindings for cmssy headless sites (createCmssyPage + draft preview)",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -51,7 +51,7 @@
51
51
  "dist"
52
52
  ],
53
53
  "peerDependencies": {
54
- "@cmssy/react": "^10.0.0",
54
+ "@cmssy/react": "^11.0.0",
55
55
  "next": ">=15",
56
56
  "react": "^18.2.0 || ^19.0.0",
57
57
  "react-dom": "^18.2.0 || ^19.0.0"
@@ -65,12 +65,12 @@
65
65
  "tsup": "^8.3.0",
66
66
  "typescript": "^5.6.0",
67
67
  "vitest": "^2.1.0",
68
- "@cmssy/react": "10.10.0"
68
+ "@cmssy/react": "11.0.0"
69
69
  },
70
70
  "dependencies": {
71
71
  "@cmssy/types": "0.32.0",
72
72
  "server-only": "^0.0.1",
73
- "@cmssy/core": "10.10.0"
73
+ "@cmssy/core": "11.0.0"
74
74
  },
75
75
  "scripts": {
76
76
  "build": "tsup",