payload-live-preview 2.2.1 → 2.3.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.
Files changed (104) hide show
  1. package/README.md +21 -18
  2. package/dist/adapters/astro/PreviewBoundary.astro +17 -4
  3. package/dist/adapters/astro/RichText.astro +13 -2
  4. package/dist/adapters/astro/index.d.ts +7 -7
  5. package/dist/adapters/astro/index.js +1 -1
  6. package/dist/adapters/astro/index.js.map +1 -1
  7. package/dist/adapters/astro/middleware-entry.d.ts +3 -3
  8. package/dist/adapters/astro/middleware-entry.js +1 -1
  9. package/dist/adapters/astro/middleware-entry.js.map +1 -1
  10. package/dist/adapters/nextjs/index.d.ts +2 -2
  11. package/dist/adapters/nextjs/index.js +1 -1
  12. package/dist/adapters/nextjs/index.js.map +1 -1
  13. package/dist/adapters/nuxt/index.d.ts +4 -4
  14. package/dist/adapters/nuxt/index.js +1 -1
  15. package/dist/adapters/nuxt/index.js.map +1 -1
  16. package/dist/adapters/nuxt/module.d.ts +1 -1
  17. package/dist/adapters/react/index.d.ts +2 -2
  18. package/dist/adapters/react/index.js +1 -1
  19. package/dist/adapters/react/index.js.map +1 -1
  20. package/dist/adapters/sveltekit/index.d.ts +5 -5
  21. package/dist/adapters/sveltekit/index.js +1 -1
  22. package/dist/adapters/sveltekit/index.js.map +1 -1
  23. package/dist/adapters/vue/index.d.ts +2 -2
  24. package/dist/adapters/vue/index.js +1 -1
  25. package/dist/adapters/vue/index.js.map +1 -1
  26. package/dist/client.cjs +1 -1
  27. package/dist/client.cjs.map +1 -1
  28. package/dist/client.d.cts +15 -3
  29. package/dist/client.d.ts +15 -3
  30. package/dist/client.js +1 -1
  31. package/dist/client.js.map +1 -1
  32. package/dist/codegen-astro.js +1 -1
  33. package/dist/codegen-astro.js.map +1 -1
  34. package/dist/codegen-cli.js +1 -1
  35. package/dist/codegen-cli.js.map +1 -1
  36. package/dist/codegen.cjs +1 -1
  37. package/dist/codegen.cjs.map +1 -1
  38. package/dist/codegen.js +1 -1
  39. package/dist/codegen.js.map +1 -1
  40. package/dist/core.cjs +1 -1
  41. package/dist/core.cjs.map +1 -1
  42. package/dist/core.d.cts +141 -6
  43. package/dist/core.d.ts +141 -6
  44. package/dist/core.js +1 -1
  45. package/dist/core.js.map +1 -1
  46. package/dist/doctor-cli.d.ts +1 -1
  47. package/dist/doctor-cli.js +1 -1
  48. package/dist/doctor-cli.js.map +1 -1
  49. package/dist/doctor.d.ts +2 -2
  50. package/dist/doctor.js +1 -1
  51. package/dist/doctor.js.map +1 -1
  52. package/dist/{document-session-Bkd181PV.d.ts → document-session-BuYuO3ae.d.ts} +27 -2
  53. package/dist/{fragment-endpoint-DGGLIijM.d.ts → fragment-endpoint-CQE_7MKi.d.ts} +5 -3
  54. package/dist/fragment.cjs +1 -1
  55. package/dist/fragment.cjs.map +1 -1
  56. package/dist/fragment.d.cts +6 -2
  57. package/dist/fragment.d.ts +6 -2
  58. package/dist/fragment.js +1 -1
  59. package/dist/fragment.js.map +1 -1
  60. package/dist/index.cjs +1 -1
  61. package/dist/index.cjs.map +1 -1
  62. package/dist/index.d.cts +79 -16
  63. package/dist/index.d.ts +79 -16
  64. package/dist/index.js +1 -1
  65. package/dist/index.js.map +1 -1
  66. package/dist/lean.cjs +1 -1
  67. package/dist/lean.cjs.map +1 -1
  68. package/dist/lean.js +1 -1
  69. package/dist/lean.js.map +1 -1
  70. package/dist/lexical.cjs +1 -1
  71. package/dist/lexical.cjs.map +1 -1
  72. package/dist/lexical.d.cts +16 -4
  73. package/dist/lexical.d.ts +16 -4
  74. package/dist/lexical.js +1 -1
  75. package/dist/lexical.js.map +1 -1
  76. package/dist/{locals-zz2gi9dj.d.ts → locals-CyzDKfKU.d.ts} +7 -1
  77. package/dist/{middleware-CI-UTf6R.d.ts → middleware-Dnt6u4nF.d.ts} +2 -2
  78. package/dist/{options-CnYybG51.d.ts → options-DTzhFVJ4.d.ts} +13 -1
  79. package/dist/plugin.cjs +1 -1
  80. package/dist/plugin.cjs.map +1 -1
  81. package/dist/plugin.d.cts +15 -9
  82. package/dist/plugin.d.ts +15 -9
  83. package/dist/plugin.js +1 -1
  84. package/dist/plugin.js.map +1 -1
  85. package/dist/plugins.cjs +1 -1
  86. package/dist/plugins.cjs.map +1 -1
  87. package/dist/plugins.d.cts +8 -2
  88. package/dist/plugins.d.ts +8 -2
  89. package/dist/plugins.js +1 -1
  90. package/dist/plugins.js.map +1 -1
  91. package/dist/{probe-D-IHg9dF.d.ts → probe-afwdYebU.d.ts} +6 -2
  92. package/dist/server.cjs +1 -1
  93. package/dist/server.cjs.map +1 -1
  94. package/dist/server.d.cts +23 -3
  95. package/dist/server.d.ts +23 -3
  96. package/dist/server.js +1 -1
  97. package/dist/server.js.map +1 -1
  98. package/dist/structural.cjs +2 -2
  99. package/dist/structural.cjs.map +1 -1
  100. package/dist/structural.d.cts +2 -0
  101. package/dist/structural.d.ts +2 -0
  102. package/dist/structural.js +1 -1
  103. package/dist/structural.js.map +1 -1
  104. package/package.json +7 -4
package/README.md CHANGED
@@ -37,7 +37,7 @@ One runtime serves every framework. The Astro, Next.js, SvelteKit and Nuxt adapt
37
37
  | 3.x | supported | the real admin on every push (3.92.1, three engines); the 3.85, 3.88 and 3.89 wire corpora replayed in CI |
38
38
  | 4.x | pre-release, the direction of this package | the 4.0.0-beta.4 wire corpus replayed in CI; the real-admin suite against `payload@beta` every day, as an early warning; a 2.2 release candidate on a site running 4.0.0-beta.4 with Astro 7.4.2 |
39
39
 
40
- **Payload 4** is where this package is headed. Its pre-releases are followed as they appear, and support becomes official with the stable 4.0 release; until then the daily run against `payload@beta` warns early and does not gate a release. The Payload 4 pre-release captured so far passes the same protocol checks as the 3.x corpora. As of 4.0.0-beta.4, Payload 4 needs Node 24.22.1 or later, and its admin Next.js 16.4 or a later 16.x release. Payload 2.x support ends with the next major release of this package: 3.0 supports Payload 3.x and 4.x, and every 2.x release keeps supporting Payload 2 ([ADR 0007 ledger, entry 25](docs/architecture/0007-v2-defaults-and-renames-ledger.md#ledger), [Preparing for 3.0](docs/migration.md#preparing-for-30)). Payload 3.x stays supported. The manifest declares `payload` as an optional peer, `^2.0.0 || ^3.0.0 || ^4.0.0-0`: npm never installs it, and a project that has Payload outside that range gets npm's `ERESOLVE` error.
40
+ **Payload 4** is where this package is headed. Its pre-releases are followed as they appear, and support becomes official with the stable 4.0 release; until then the daily run against `payload@beta` warns early and does not gate a release. The Payload 4 pre-release captured so far passes the same protocol checks as the 3.x corpora. As of 4.0.0-beta.4, Payload 4 needs Node 24.22.1 or later, and its admin Next.js 16.4 or a later 16.x release. Payload 2.x support ends with the next major release of this package: 3.0 supports Payload 3.x and 4.x, and every 2.x release keeps supporting Payload 2 ([ADR 0007 ledger, entry 25](docs/architecture/0007-v2-defaults-and-renames-ledger.md#ledger), [Preparing for 3.0](docs/migration.md#preparing-for-30)). 3.0 also needs Node 22 or newer and drops no framework major (entries 28 and 29). Payload 3.x stays supported. The manifest declares `payload` as an optional peer, `^2.0.0 || ^3.0.0 || ^4.0.0-0`: npm never installs it, and a project that has Payload outside that range gets npm's `ERESOLVE` error.
41
41
 
42
42
  What differs between Payload 2, 3 and 4:
43
43
 
@@ -50,16 +50,18 @@ What differs between Payload 2, 3 and 4:
50
50
 
51
51
  <!-- compat-matrix:start -->
52
52
 
53
- | Framework | Supported | Tested in CI on every push (version, browsers) |
54
- | --------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
55
- | Astro | >=4.0.0 <8.0.0 | 7.4.2 (chromium, firefox, webkit); 6.x (chromium); 5.x (chromium); 4.x (chromium) |
56
- | Next.js | App Router, 15.5 and 16 | 16.4.3 (chromium, firefox, webkit); 15.x (chromium) |
57
- | SvelteKit | 2.x | 2.70.3 (chromium, firefox, webkit) |
58
- | Nuxt | 3.x (end of life since 31 July 2026: kept working, not officially supported) | 3.21.11 (chromium, firefox, webkit) |
53
+ | Framework | Supported | Tested in CI on every push (version, browsers) |
54
+ | --------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
55
+ | Astro | >=4.0.0 <8.0.0 | 7.4.2 (chromium, firefox, webkit); 6.x (chromium); 5.x (chromium); 4.x (chromium) |
56
+ | Next.js | App Router, 15.5 and 16 | 16.4.3 (chromium, firefox, webkit); 15.x (chromium) |
57
+ | SvelteKit | 2.x and 3.x | 3.1.1 (chromium, firefox, webkit); 2.70.3 (chromium, firefox, webkit) |
58
+ | Nuxt | 4.x; 3.x (end of life since 31 July 2026: kept working, not officially supported) | 4.6.3 (chromium, firefox, webkit); 3.21.11 (chromium, firefox, webkit) |
59
59
 
60
60
  Node >=20.19.0; the unit and integration suites run on Node 20, 22, 24, 26. Every version in the table is what the fixture lockfile or the matrix job installs, checked by `npm run compat:check`.
61
61
 
62
- Vite 5 through 8: that is what the supported framework majors install (Astro 7 → 8, Astro 6 → 7, Astro 5 → 6, Astro 4 → 5, SvelteKit 2 → 5/6/7/8, Nuxt 3 → 7), measured 2026-09-06. `npm run compat:check` keeps the devDependency and the fixture lockfiles inside that span; `npm run compat:refresh` re-reads it from the registry.
62
+ Of the 58 feature rows of `quality/compat-matrix.json`, 55 passed in the CI run the last Version PR recorded (commit `c9ffe5d`, 2026-11-01, `quality/compat-results.json`); the other 3 have no recorded result.
63
+
64
+ Vite 5 through 8: that is what the supported framework majors install (Astro 7 → 8, Astro 6 → 7, Astro 5 → 6, Astro 4 → 5, SvelteKit 3 → 8, SvelteKit 2 → 5/6/7/8, Nuxt 4 → 8, Nuxt 3 → 7), measured 2026-10-31. `npm run compat:check` keeps the devDependency and the fixture lockfiles inside that span; `npm run compat:refresh` re-reads it from the registry.
63
65
 
64
66
  The framework hooks and fragment renderers run twice on every push: at the floor of each peer range, as unit tests in jsdom that the `hook-matrix` job runs after installing the floors over the lockfile (React 18.0.0, Vue 3.3.0, Svelte 5.0.0), and at what the lockfile installs (React 19.3.1, Vue 3.5.44, Svelte 5.57.3), in the unit tests and the browser suites; the SvelteKit renderer is measured against a component compiled by `svelte/compiler` and rendered by the real `svelte/server`.
65
67
 
@@ -76,11 +78,9 @@ The framework hooks and fragment renderers run twice on every push: at the floor
76
78
 
77
79
  <!-- compat-matrix:end -->
78
80
 
79
- Nuxt 4 has no row because no CI job installs it. A copy of the Nuxt example in Nuxt 4.5.2's `app/` layout passed the production suite against the mock admin on 2026-10-02 (54 of 54 cases), and a Nuxt 4.5.2 site installed from the 2.1.0 release candidate built and served its pages on 2026-10-18; neither was a real-admin run.
80
-
81
- SvelteKit 3 has no row either: no CI job installs it. A copy of the SvelteKit example, moved to SvelteKit 3.1.0 with `npx sv migrate sveltekit-3`, built with adapter-node 6 and passed the 32 SvelteKit cases of the browser suite against the mock admin in Chromium, Firefox and WebKit on 2026-10-26; it was not a real-admin run. The example needed the migration's changes ([docs/sveltekit.md](docs/sveltekit.md)); the package needed none.
81
+ SvelteKit 3 and Nuxt 4 are supported. The `sveltekit3` job runs the SvelteKit example migrated to SvelteKit 3.1.1 with `npx sv migrate sveltekit-3`, and the `nuxt4` job runs the Nuxt example in Nuxt 4.6.3's `app/` layout. Both run on the development server against the mock admin in Chromium, Firefox and WebKit, and `real-payload-surfaces` drives both from the real admin in the same three engines. The production jobs still build the SvelteKit 2 and Nuxt 3 examples. The SvelteKit example needed the migration's changes ([docs/sveltekit.md](docs/sveltekit.md)); the package needed no change for either.
82
82
 
83
- **A client-rendered app takes a hook.** `useLivePreviewDocument()` from `payload-live-preview/react` or `payload-live-preview/vue` returns the merged document and re-renders your tree. Payload 3 updates use the method-override merge request; Payload 2 scalar updates settle locally and raw relationships use schema-based collection GETs. A newer update aborts any request in flight; an HTTP error is refused instead of becoming the document; each hook keeps its own state, requests and errors, and every hook on the page follows the document the admin sends, whichever one it started from ([docs/react.md](docs/react.md), [docs/vue.md](docs/vue.md)). The official [`@payloadcms/live-preview-react`](https://payloadcms.com/docs/live-preview/client) / `-vue` hooks ship in lockstep with Payload and remain the safe default if that matters more to you; running either alongside the DOM runtime on one page: [docs/interop.md](docs/interop.md).
83
+ **A client-rendered app takes a hook.** `useLivePreviewDocument()` from `payload-live-preview/react` or `payload-live-preview/vue` returns the merged document and re-renders your tree. Payload 3 updates use the method-override merge request; Payload 2 scalar updates settle locally and raw relationships use schema-based collection GETs. A newer update aborts any request in flight; an HTTP error is refused instead of becoming the document; each hook keeps its own state, requests and errors, and a hook given a `document` merges only that document's updates; without one it follows the document the admin sends, whichever one it started from ([docs/react.md](docs/react.md), [docs/vue.md](docs/vue.md)). The official [`@payloadcms/live-preview-react`](https://payloadcms.com/docs/live-preview/client) / `-vue` hooks ship in lockstep with Payload and remain the safe default if that matters more to you; running either alongside the DOM runtime on one page: [docs/interop.md](docs/interop.md).
84
84
 
85
85
  ## Install
86
86
 
@@ -125,8 +125,10 @@ the mappings. Existing breakpoints stay when the option is omitted; supplying
125
125
  it replaces the list. A competing root URL or a URL on a selected entity that
126
126
  already exists when this transform runs is a configuration error. Make this
127
127
  transform run after any plugin that may write a Live Preview URL in Payload's
128
- effective execution order, or compose both routing policies explicitly. The
129
- complete merge and conflict rules are in [docs/payload.md](docs/payload.md).
128
+ effective execution order (Payload 3 and 4 sort by the `order` option), or
129
+ compose both routing policies explicitly. A resolver or the `fallback` may be
130
+ `null` for a document without a preview on Payload 3 and 4. The complete merge
131
+ and conflict rules are in [docs/payload.md](docs/payload.md).
130
132
 
131
133
  In the Payload 3.92.1 admin, a collection document gets its native Live
132
134
  Preview after its first save. The create screen has no preview toggle and no
@@ -137,10 +139,11 @@ Firefox and WebKit.
137
139
 
138
140
  Payload 4 is still a pre-release ([Compatibility](#compatibility)). The plugin
139
141
  was measured once against 4.0.0-beta.4, outside CI; the compatibility list says
140
- what that run covered and what it left out.
142
+ what that run covered and what it left out. Its `order` option and `null`
143
+ resolvers were measured once against 4.0.0-beta.6, also outside CI
144
+ ([ADR 0017](docs/architecture/0017-structural-payload-config-plugin.md)).
141
145
 
142
- Use the lower-level callback when another plugin owns the surrounding config or
143
- when a document may have no preview route:
146
+ Use the lower-level callback when another plugin owns the surrounding config:
144
147
 
145
148
  ```ts
146
149
  import { buildLivePreviewUrl } from 'payload-live-preview/payload';
@@ -171,7 +174,7 @@ export default buildConfig({
171
174
  });
172
175
  ```
173
176
 
174
- The helper appends `?preview=true`, one of the query parameters (`preview`, `draft`, `livePreview`) the adapters read as preview intent. The parameter is client-controlled: it selects delivery and never authorizes draft access. A hand-written `url: ({ data, locale, collectionConfig, globalConfig }) => string` callback works the same way; the [official docs](https://payloadcms.com/docs/live-preview/overview) have the full contract. The helper's nullable overload lets a resolver return `null` for a document without a route, and `fallback: null` declines every unmapped one; Payload 3 then shows no iframe. Payload 2.32.3's published callback result is string-only, so use the non-null overload and a string fallback there. The config plugin deliberately stays inside that common contract.
177
+ The helper appends `?preview=true`, one of the query parameters (`preview`, `draft`, `livePreview`) the adapters read as preview intent. The parameter is client-controlled: it selects delivery and never authorizes draft access. A hand-written `url: ({ data, locale, collectionConfig, globalConfig }) => string` callback works the same way; the [official docs](https://payloadcms.com/docs/live-preview/overview) have the full contract. The helper's nullable overload lets a resolver return `null` for a document without a route, and `fallback: null` declines every unmapped one; Payload 3 then shows no iframe. Payload 2.32.3's published callback result is string-only, so use the non-null overload and a string fallback there, and keep the config plugin's resolvers to strings.
175
178
 
176
179
  The config plugin accepts no signing secret or token option. Where no session
177
180
  cookie crosses origins, the manual `signed-token` URL callback is a Payload 3
@@ -24,6 +24,9 @@
24
24
  * `data-payload-strategy="patch"` is written explicitly: the wrapper is a
25
25
  * patch target; markup a server renders instead lives in a
26
26
  * `data-payload-fragment` boundary (docs/hybrid.md).
27
+ *
28
+ * Where `authorizePreview` decides, a response it did not authorize keeps the
29
+ * wrapper and carries no `data-payload-*`, as the gated helpers do (ADR 0006).
27
30
  */
28
31
 
29
32
  interface Props {
@@ -50,14 +53,24 @@ function isEmpty(candidate: unknown): boolean {
50
53
 
51
54
  const Tag = as;
52
55
  const empty = isEmpty(value);
56
+ const locals = Astro.locals as {
57
+ livePreviewRequiresAuthorization?: boolean;
58
+ livePreviewAuthorization?: unknown;
59
+ };
60
+ const binding =
61
+ locals.livePreviewRequiresAuthorization === true && locals.livePreviewAuthorization === undefined
62
+ ? {}
63
+ : {
64
+ 'data-payload-field': field,
65
+ 'data-payload-type': type,
66
+ 'data-payload-boundary': '',
67
+ 'data-payload-strategy': 'patch',
68
+ };
53
69
  ---
54
70
 
55
71
  <Tag
56
72
  {...rest}
57
- data-payload-field={field}
58
- data-payload-type={type}
59
- data-payload-boundary=""
60
- data-payload-strategy="patch"
73
+ {...binding}
61
74
  hidden={empty ? true : undefined}
62
75
  >
63
76
  <slot />
@@ -70,6 +70,17 @@ const {
70
70
  requireDocument,
71
71
  } = Astro.props;
72
72
  const Tag = tag;
73
+ const locals = Astro.locals as {
74
+ livePreviewRequiresAuthorization?: boolean;
75
+ livePreviewAuthorization?: unknown;
76
+ };
77
+ // Where `authorizePreview` decides, a response it did not authorize carries no binding (ADR 0006).
78
+ const bound =
79
+ field !== undefined &&
80
+ !(
81
+ locals.livePreviewRequiresAuthorization === true &&
82
+ locals.livePreviewAuthorization === undefined
83
+ );
73
84
  const html = isLexicalContent(value)
74
85
  ? lexicalToHtml(value, {
75
86
  ...(sanitizerDocument === undefined ? {} : { document: sanitizerDocument }),
@@ -80,7 +91,7 @@ const html = isLexicalContent(value)
80
91
 
81
92
  <Tag
82
93
  class={className}
83
- data-payload-field={field}
84
- data-payload-richtext={field !== undefined ? '' : undefined}
94
+ data-payload-field={bound ? field : undefined}
95
+ data-payload-richtext={bound ? '' : undefined}
85
96
  set:html={html}
86
97
  />
@@ -1,10 +1,10 @@
1
- import { L as LivePreviewAstroOptions } from '../../middleware-CI-UTf6R.js';
2
- export { a as LivePreviewMiddleware, c as createLivePreviewMiddleware } from '../../middleware-CI-UTf6R.js';
3
- import { h as hasPreviewIntent } from '../../options-CnYybG51.js';
4
- export { P as PreviewAdapterOptions, a as PreviewRequestLike, b as PreviewRequestOptions, c as PreviewSignal } from '../../options-CnYybG51.js';
5
- import { F as FragmentEndpointOptions$1, a as FragmentRegistry$1, b as FragmentRegistryEntry$1, c as FragmentRenderer$1 } from '../../fragment-endpoint-DGGLIijM.js';
6
- export { d as FragmentRenderInput } from '../../fragment-endpoint-DGGLIijM.js';
7
- export { A as AUTHORIZATION_LOCALS_KEY, a as AUTHORIZATION_OUTCOME_LOCALS_KEY, L as LivePreviewLocals, N as NONCE_LOCALS_KEY } from '../../locals-zz2gi9dj.js';
1
+ import { L as LivePreviewAstroOptions } from '../../middleware-Dnt6u4nF.js';
2
+ export { a as LivePreviewMiddleware, c as createLivePreviewMiddleware } from '../../middleware-Dnt6u4nF.js';
3
+ import { h as hasPreviewIntent } from '../../options-DTzhFVJ4.js';
4
+ export { P as PreviewAdapterOptions, a as PreviewRequestLike, b as PreviewRequestOptions, c as PreviewSignal } from '../../options-DTzhFVJ4.js';
5
+ import { F as FragmentEndpointOptions$1, a as FragmentRegistry$1, b as FragmentRegistryEntry$1, c as FragmentRenderer$1 } from '../../fragment-endpoint-CQE_7MKi.js';
6
+ export { d as FragmentRenderInput } from '../../fragment-endpoint-CQE_7MKi.js';
7
+ export { A as AUTHORIZATION_LOCALS_KEY, a as AUTHORIZATION_OUTCOME_LOCALS_KEY, L as LivePreviewLocals, N as NONCE_LOCALS_KEY } from '../../locals-CyzDKfKU.js';
8
8
 
9
9
  /**
10
10
  * The Astro integration for `astro.config.mjs`: `livePreview({ ... })`.