payload-live-preview 2.0.0-beta.0 → 2.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.
Files changed (109) hide show
  1. package/README.md +60 -775
  2. package/dist/adapters/astro/PreviewBoundary.astro +2 -2
  3. package/dist/adapters/astro/index.d.ts +28 -154
  4. package/dist/adapters/astro/index.js +1 -1
  5. package/dist/adapters/astro/index.js.map +1 -1
  6. package/dist/adapters/astro/middleware-entry.d.ts +3 -2
  7. package/dist/adapters/astro/middleware-entry.js +1 -1
  8. package/dist/adapters/astro/middleware-entry.js.map +1 -1
  9. package/dist/adapters/nextjs/index.d.ts +247 -6
  10. package/dist/adapters/nextjs/index.js +1 -1
  11. package/dist/adapters/nextjs/index.js.map +1 -1
  12. package/dist/adapters/nuxt/index.d.ts +58 -3
  13. package/dist/adapters/nuxt/index.js +1 -1
  14. package/dist/adapters/nuxt/index.js.map +1 -1
  15. package/dist/adapters/nuxt/module.d.ts +82 -0
  16. package/dist/adapters/nuxt/module.js +2 -0
  17. package/dist/adapters/nuxt/module.js.map +1 -0
  18. package/dist/adapters/react/index.d.ts +110 -0
  19. package/dist/adapters/react/index.js +3 -0
  20. package/dist/adapters/react/index.js.map +1 -0
  21. package/dist/adapters/sveltekit/index.d.ts +65 -7
  22. package/dist/adapters/sveltekit/index.js +1 -1
  23. package/dist/adapters/sveltekit/index.js.map +1 -1
  24. package/dist/adapters/vue/index.d.ts +56 -0
  25. package/dist/adapters/vue/index.js +2 -0
  26. package/dist/adapters/vue/index.js.map +1 -0
  27. package/dist/annotate.d.ts +161 -0
  28. package/dist/annotate.js +2 -0
  29. package/dist/annotate.js.map +1 -0
  30. package/dist/client.cjs +1 -1
  31. package/dist/client.cjs.map +1 -1
  32. package/dist/client.d.cts +182 -9
  33. package/dist/client.d.ts +182 -9
  34. package/dist/client.js +1 -1
  35. package/dist/client.js.map +1 -1
  36. package/dist/codegen-astro.js +1 -1
  37. package/dist/codegen-astro.js.map +1 -1
  38. package/dist/codegen-cli.js +1 -1
  39. package/dist/codegen-cli.js.map +1 -1
  40. package/dist/codegen.cjs +1 -1
  41. package/dist/codegen.cjs.map +1 -1
  42. package/dist/codegen.d.cts +129 -4
  43. package/dist/codegen.d.ts +129 -4
  44. package/dist/codegen.js +1 -1
  45. package/dist/codegen.js.map +1 -1
  46. package/dist/core.cjs +1 -1
  47. package/dist/core.cjs.map +1 -1
  48. package/dist/core.d.cts +264 -73
  49. package/dist/core.d.ts +264 -73
  50. package/dist/core.js +1 -1
  51. package/dist/core.js.map +1 -1
  52. package/dist/doctor-cli.d.ts +1 -1
  53. package/dist/doctor-cli.js +1 -1
  54. package/dist/doctor-cli.js.map +1 -1
  55. package/dist/doctor.d.ts +7 -6
  56. package/dist/doctor.js +1 -1
  57. package/dist/doctor.js.map +1 -1
  58. package/dist/document-session-BfBfLVpg.d.ts +53 -0
  59. package/dist/fragment-endpoint-3Mlz7GDz.d.ts +189 -0
  60. package/dist/fragment.cjs +1 -1
  61. package/dist/fragment.cjs.map +1 -1
  62. package/dist/fragment.d.cts +64 -18
  63. package/dist/fragment.d.ts +64 -18
  64. package/dist/fragment.js +1 -1
  65. package/dist/fragment.js.map +1 -1
  66. package/dist/index.cjs +1 -1
  67. package/dist/index.cjs.map +1 -1
  68. package/dist/index.d.cts +422 -83
  69. package/dist/index.d.ts +422 -83
  70. package/dist/index.js +1 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/lean.cjs +2 -0
  73. package/dist/lean.cjs.map +1 -0
  74. package/dist/lean.d.cts +44 -0
  75. package/dist/lean.d.ts +44 -0
  76. package/dist/lean.js +2 -0
  77. package/dist/lean.js.map +1 -0
  78. package/dist/lexical.cjs +1 -1
  79. package/dist/lexical.cjs.map +1 -1
  80. package/dist/lexical.d.cts +19 -1
  81. package/dist/lexical.d.ts +19 -1
  82. package/dist/lexical.js +1 -1
  83. package/dist/lexical.js.map +1 -1
  84. package/dist/locals-DBXDMxOA.d.ts +45 -0
  85. package/dist/{middleware-CEPsY1P7.d.ts → middleware-Bx9I7PXW.d.ts} +14 -14
  86. package/dist/migrate.d.ts +4 -3
  87. package/dist/migrate.js +1 -1
  88. package/dist/migrate.js.map +1 -1
  89. package/dist/{options-CEzzfHJu.d.ts → options-BW1eqXvc.d.ts} +90 -2
  90. package/dist/plugins.cjs +1 -1
  91. package/dist/plugins.cjs.map +1 -1
  92. package/dist/plugins.d.cts +111 -6
  93. package/dist/plugins.d.ts +111 -6
  94. package/dist/plugins.js +1 -1
  95. package/dist/plugins.js.map +1 -1
  96. package/dist/{probe-CYtvj_Lm.d.ts → probe-CELeUciC.d.ts} +26 -4
  97. package/dist/server.cjs +1 -1
  98. package/dist/server.cjs.map +1 -1
  99. package/dist/server.d.cts +67 -13
  100. package/dist/server.d.ts +67 -13
  101. package/dist/server.js +1 -1
  102. package/dist/server.js.map +1 -1
  103. package/dist/structural.cjs +2 -2
  104. package/dist/structural.cjs.map +1 -1
  105. package/dist/structural.d.cts +47 -4
  106. package/dist/structural.d.ts +47 -4
  107. package/dist/structural.js +2 -2
  108. package/dist/structural.js.map +1 -1
  109. package/package.json +77 -9
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /** The package version, read from package.json so the entries and the inline runtime cannot drift. */
2
+ /** @internal */
2
3
  declare const VERSION: string;
3
4
 
4
5
  /** Connection status and the heartbeat that decides a disconnect. */
@@ -83,6 +84,23 @@ interface InspectionBindings {
83
84
  readonly ownerScoped: boolean;
84
85
  /** Distinct document owners currently on the page, sorted. */
85
86
  readonly owners: readonly string[];
87
+ /**
88
+ * Bindings the runtime found by value on the connection's first message
89
+ * (`autoBind: 'unique'`, ADR 0014), sorted by field, each with the value it
90
+ * matched on and the attribute it matched in — `undefined` for a text match.
91
+ * These are the elements that change without a `data-payload-field` in the
92
+ * template; every one of them carries `data-payload-guessed` in the DOM.
93
+ */
94
+ readonly guessed: readonly {
95
+ readonly field: string;
96
+ readonly matched: string;
97
+ readonly attribute: string | undefined;
98
+ }[];
99
+ /** `autoBind` as configured, and what the one search cost; `searchMs` is `undefined` until it ran. */
100
+ readonly autoBind: {
101
+ readonly mode: 'off' | 'unique';
102
+ readonly searchMs: number | undefined;
103
+ };
86
104
  }
87
105
  /** Scheduler work in progress. */
88
106
  interface InspectionScheduler {
@@ -122,14 +140,49 @@ interface LivePreviewInspection {
122
140
  readonly plugins: readonly PluginInspection[];
123
141
  /** Server-rendered fragment boundaries: whether a handler exists and what happened to renders. */
124
142
  readonly fragments: InspectionFragments;
125
- /** Route refreshes: whether a strategy exists, how many ran, failed, or were stopped by the loop guard. */
143
+ /** Route refreshes: whether a strategy exists, how many ran, failed, were paced, or were stopped by the loop guard. */
126
144
  readonly route: InspectionRoute;
145
+ /** Patches the runtime knew could not match the server's render, and what became of them. */
146
+ readonly fidelity: InspectionFidelity;
147
+ /**
148
+ * Whether the page declared a framework that hydrates it, and how far the
149
+ * wait for its first commit — React's, or Vue's mount — got (ADR 0015).
150
+ * `waiting` is why a preview on a Next or Nuxt page is not connected yet;
151
+ * `timed-out` is LP0607.
152
+ */
153
+ readonly hydration: {
154
+ readonly mode: 'off' | 'react' | 'vue';
155
+ readonly state: 'idle' | 'waiting' | 'committed' | 'timed-out';
156
+ };
157
+ }
158
+ /**
159
+ * The fidelity verdicts as `inspect()` reports them (LP0411). A positive
160
+ * `unfaithful` beside `escalated: 0` is a page that keeps a degraded patch —
161
+ * because `mode` says so, or because neither `fragments.handler` nor
162
+ * `route.handler` is there to escalate to.
163
+ */
164
+ interface InspectionFidelity {
165
+ /** `onUnfaithfulPatch` as resolved from both of its names. */
166
+ readonly mode: 'ignore' | 'warn' | 'escalate';
167
+ /** Bindings reported unfaithful since start — once per element, like LP0411, and under every mode. */
168
+ readonly unfaithful: number;
169
+ /** Of those, how many were handed to the fragment or route strategy. */
170
+ readonly escalated: number;
171
+ /** The field names behind `unfaithful`, sorted. Cumulative. */
172
+ readonly fields: readonly string[];
127
173
  }
128
174
  /** The route strategy as `inspect()` reports it. */
129
175
  interface InspectionRoute {
130
176
  readonly handler: boolean;
131
177
  readonly refreshes: number;
178
+ /** Refreshes that broke: the request, the answer, or the morph. */
132
179
  readonly failed: number;
180
+ /**
181
+ * Refreshes the strategy's own minimum interval held back (LP0805). Each is
182
+ * run once the window closes unless a newer revision takes its place, so this
183
+ * counts pacing and not loss — and it is deliberately not `failed`.
184
+ */
185
+ readonly refused: number;
133
186
  /** Second refresh requests for one revision, refused with LP0805. */
134
187
  readonly loopStopped: number;
135
188
  }
@@ -227,7 +280,9 @@ type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
227
280
  *
228
281
  * Browser-side reporting sites write the literal (`code: 'LP0603'`) rather than
229
282
  * reading it from this record: the frozen table would then ship in the inline
230
- * runtime for the sake of six characters. Server-side tools may import it.
283
+ * runtime for the sake of six characters — it did, 1 287 B in every page, for
284
+ * the one read Z6 left in the strategy runner, and `diagnostic-codes.test.ts`
285
+ * now holds the artifact free of it. Server-side tools may import it.
231
286
  */
232
287
  /**
233
288
  * Every diagnostic code the runtime can report, by name.
@@ -245,6 +300,8 @@ declare const DIAGNOSTIC_CODES: Readonly<{
245
300
  readonly ReferrerOnlyTrust: "LP0102";
246
301
  /** A plugin declares a runtime range this runtime does not satisfy; it was refused. */
247
302
  readonly PluginIncompatible: "LP0103";
303
+ /** The page carries the lean runtime and needs a feature that profile leaves out. */
304
+ readonly ProfileFeatureOmitted: "LP0104";
248
305
  /** An update named a field with no binding anchor on the page. */
249
306
  readonly OrphanField: "LP0201";
250
307
  /** Owner scoping is on and the update names no document it could belong to. */
@@ -265,10 +322,24 @@ declare const DIAGNOSTIC_CODES: Readonly<{
265
322
  readonly StructuralUnstableKeys: "LP0406";
266
323
  /** A binding asks for a delivery strategy this release does not have; it is left unchanged. */
267
324
  readonly UnsupportedStrategy: "LP0407";
325
+ /** `data-payload-format` names a format the vocabulary does not contain; the default formatting was used instead. */
326
+ readonly UnknownValueFormat: "LP0408";
327
+ /** The strict sanitizer removed an attribute the 1.x `'compat'` policy kept. */
328
+ readonly SanitizerDroppedAttribute: "LP0409";
329
+ /** A Lexical block has no renderer; the markup the server rendered for it is kept instead. */
330
+ readonly UnrenderedBlockKept: "LP0410";
331
+ /** A patch cannot reach what the server would have drawn; `onUnfaithfulPatch` decided what happens next. */
332
+ readonly UnfaithfulPatch: "LP0411";
333
+ /** The first write to a date, number or checkbox binding replaced a different reading of the same value. */
334
+ readonly ServerFormatReplaced: "LP0412";
335
+ /** A Lexical block has no renderer, and the write could not keep the markup the server rendered for it; it is gone. */
336
+ readonly UnrenderedBlockLost: "LP0413";
268
337
  /** A message was rejected before it reached the update pipeline. */
269
338
  readonly MessageRejected: "LP0501";
270
339
  /** A preview token was rejected. */
271
340
  readonly TokenRejected: "LP0502";
341
+ /** A trusted origin sent a message this protocol version does not recognise. */
342
+ readonly ProtocolShapeUnknown: "LP0503";
272
343
  /** A consumer event handler threw. */
273
344
  readonly HandlerThrew: "LP0601";
274
345
  /** A consumer transform threw; the original value was kept. */
@@ -279,11 +350,13 @@ declare const DIAGNOSTIC_CODES: Readonly<{
279
350
  readonly StartupFailed: "LP0605";
280
351
  /** Sending the ready handshake failed. */
281
352
  readonly ReadyFailed: "LP0606";
353
+ /** The page declared hydration, but no React commit or Vue mount came within the cap; the runtime started without waiting. */
354
+ readonly HydrationWaitTimedOut: "LP0607";
282
355
  /** The audit found no runtime in a response that carried preview intent. */
283
356
  readonly AuditRuntimeMissing: "LP0701";
284
357
  /** The preview response declares no `frame-ancestors`. */
285
358
  readonly AuditNoFrameAncestors: "LP0702";
286
- /** `X-Frame-Options` forbids framing, which no CSP can undo. */
359
+ /** `X-Frame-Options` forbids framing, which no CSP can undo; `SAMEORIGIN` forbids it from another origin only. */
287
360
  readonly AuditFrameOptionsBlocks: "LP0703";
288
361
  /** Binding attributes are served to anonymous visitors. */
289
362
  readonly AuditBindingsExposed: "LP0704";
@@ -303,10 +376,12 @@ declare const DIAGNOSTIC_CODES: Readonly<{
303
376
  readonly FragmentUnauthorized: "LP0803";
304
377
  /** A fragment response arrived for a revision that was already superseded and was discarded. */
305
378
  readonly FragmentSuperseded: "LP0804";
306
- /** A route refresh was requested again for the same revision; the loop guard stopped it. */
379
+ /** A route refresh was refused: the loop guard, or the strategy's minimum interval. */
307
380
  readonly RouteRefreshLoop: "LP0805";
308
381
  /** A boundary asks for the fragment strategy but no fragment handler is configured; it is patched. */
309
382
  readonly FragmentStrategyUnavailable: "LP0806";
383
+ /** A revision changed a field with no binding; `onUnfaithfulPatch` refreshed the route. */
384
+ readonly UnboundChangeRefresh: "LP0807";
310
385
  /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */
311
386
  readonly V2ReadinessGap: "LP0709";
312
387
  /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */
@@ -369,7 +444,21 @@ interface RouteContext {
369
444
  readonly signal: AbortSignal;
370
445
  readonly isCurrent: () => boolean;
371
446
  readonly log: (code: DiagnosticCode, detail: string) => void;
447
+ /**
448
+ * Ask to be run again in `delayMs`, once. A strategy that refuses a refresh
449
+ * because it is rate-limiting itself uses this: the window is a rate limit
450
+ * and not a filter, so what falls inside it still has to reach the preview.
451
+ * The runtime runs at most one such request, and only while the revision that
452
+ * asked is still the current one.
453
+ */
454
+ readonly retryAfter?: (delayMs: number) => void;
372
455
  }
456
+ /**
457
+ * What one refresh did. `refused` is the strategy's own brake and not a
458
+ * failure — it is counted separately, because a number that mixes a planned
459
+ * pause with a broken request cannot be read.
460
+ */
461
+ type RouteOutcome = 'refreshed' | 'failed' | 'refused' | 'superseded';
373
462
  /**
374
463
  * Whether a revision needs the whole route re-rendered, and how. After a
375
464
  * refresh the runtime rescans and re-applies the revision, so the unsaved
@@ -377,7 +466,7 @@ interface RouteContext {
377
466
  */
378
467
  interface RouteStrategy {
379
468
  readonly plan: (root: ParentNode, changedFields: ReadonlySet<string>) => boolean;
380
- readonly refresh: (context: RouteContext) => Promise<'refreshed' | 'failed' | 'superseded'>;
469
+ readonly refresh: (context: RouteContext) => Promise<RouteOutcome>;
381
470
  }
382
471
  interface StrategyHandlers {
383
472
  readonly fragment?: FragmentStrategy;
@@ -450,7 +539,15 @@ interface LivePreviewEventMap {
450
539
  readonly documentSave: {
451
540
  readonly timestamp: number;
452
541
  };
453
- /** A data update carried `externallyUpdatedRelationship`: a related document changed in an admin drawer, so the update re-renders unconditionally. */
542
+ /**
543
+ * A save in another document reached the page through
544
+ * `externallyUpdatedRelationship` — an admin-drawer edit. Fires once per
545
+ * such save, not once per message: the panel repeats its last document
546
+ * event in every later message, including its own saves of the previewed
547
+ * document, and neither of those is news. That update re-renders every
548
+ * bound field even under `skipUnchanged`, because a drawer edit changes
549
+ * populated values while the form values stay put.
550
+ */
454
551
  readonly relationshipUpdate: {
455
552
  readonly detail: PayloadDocumentEventDetail;
456
553
  readonly timestamp: number;
@@ -496,6 +593,58 @@ declare class EventEmitter<TMap extends object = LivePreviewEventMap> {
496
593
  eventNames(): (keyof TMap)[];
497
594
  }
498
595
 
596
+ /**
597
+ * `'strict'` (default) strips `id`, `name` and `data-payload-*` and passes
598
+ * other `data-*` only via `allowedDataAttributes`; `'compat'` keeps them.
599
+ */
600
+ type SanitizerPolicyMode = 'compat' | 'strict';
601
+ interface SanitizeOptions {
602
+ /** Overrides the module default set by `setSanitizerPolicy()`. */
603
+ readonly policy?: SanitizerPolicyMode;
604
+ /** `data-*` attributes (full names) that pass under `'strict'`; `data-payload-*` never does. */
605
+ readonly allowedDataAttributes?: readonly string[];
606
+ /**
607
+ * Keep `input`, `button`, `textarea`, `select`, `option` and `label` — only
608
+ * for markup the page author wrote, never for CMS content. `form`,
609
+ * handlers, `style` and unsafe URLs stay dropped.
610
+ */
611
+ readonly allowFormControls?: boolean;
612
+ /** Extra tags to allow. Lower-case, untrimmed. */
613
+ readonly additionalAllowedTags?: readonly string[];
614
+ /**
615
+ * Extra per-tag attributes, lower-case. Cannot re-admit handlers, `style`,
616
+ * or — under `'strict'` — `id`, `name` and `data-payload-*`.
617
+ */
618
+ readonly additionalAllowedAttributes?: Readonly<Record<string, readonly string[]>>;
619
+ /**
620
+ * The input is a page-author item template, so `'strict'` keeps the
621
+ * applier's reconciliation attributes (`TEMPLATE_ATTRIBUTES`) and nothing
622
+ * else — every other `data-payload-*` is still stripped, so a template can
623
+ * never add a binding.
624
+ */
625
+ readonly templateMode?: boolean;
626
+ }
627
+ /**
628
+ * The process-wide default for calls without an explicit `policy`. A runtime
629
+ * instance carries its own `sanitizerPolicy` and never writes here (ADR 0002).
630
+ */
631
+ declare function setSanitizerPolicy(mode: SanitizerPolicyMode): void;
632
+ /** The `Document` surface the sanitizer needs; jsdom, linkedom and happy-dom all provide it. */
633
+ interface SanitizerDocument {
634
+ createElement: (tagName: string) => {
635
+ innerHTML: string;
636
+ readonly content: ParentNode;
637
+ };
638
+ }
639
+ /** Supply a `Document` for SSR, e.g. linkedom's `parseHTML(...).document`; `null` clears it. */
640
+ declare function setSanitizerDocument(doc: SanitizerDocument | null): void;
641
+ /**
642
+ * Sanitize `html`; malformed input is recovered by the parser first.
643
+ *
644
+ * @throws {SanitizerEnvironmentError} when no DOM is available.
645
+ */
646
+ declare function sanitizeHtml(html: string, options?: SanitizeOptions): string;
647
+
499
648
  /** Types shared by the runtime primitives. */
500
649
 
501
650
  /** Payload's field set plus the DOM-binding categories `html`, `url`, `image` and `structural-array`. */
@@ -532,7 +681,7 @@ interface CachedElement {
532
681
  /** Nearest enclosing `data-payload-fragment` boundary. Resolved by the cache. */
533
682
  readonly fragmentBoundary?: Element;
534
683
  /** `data-payload-boundary`: an anchor that hides itself while its field is empty. */
535
- readonly boundary?: boolean;
684
+ readonly hidesWhenEmpty?: boolean;
536
685
  /** Write the value into this attribute instead of the content; policed writes. */
537
686
  readonly targetAttribute?: string;
538
687
  /** Optional sibling-field path bound to the element's `href` attribute. */
@@ -547,8 +696,16 @@ interface CachedElement {
547
696
  readonly arraySeparator?: string;
548
697
  /** Optional locale code locked onto this element (overrides the global locale). */
549
698
  readonly locale?: string;
699
+ /** Raw `data-payload-format`; the date and number renderers read the vocabulary. */
700
+ readonly format?: string;
550
701
  /** The document this binding belongs to, from the nearest `data-payload-owner`. */
551
702
  readonly owner?: string;
703
+ /**
704
+ * The value an auto-binding matched on (`data-payload-guessed`), for a
705
+ * binding the runtime found by value rather than one the template declared.
706
+ * Absent for a declared binding.
707
+ */
708
+ readonly guessed?: string;
552
709
  }
553
710
  /** What a renderer is given; `allFields` lets it resolve a sibling field. */
554
711
  interface RenderContext {
@@ -560,6 +717,20 @@ interface RenderContext {
560
717
  readonly schema: PayloadFieldSchema | undefined;
561
718
  /** The project's rich-text renderer, when the client was configured with one. */
562
719
  readonly renderRichText?: RichTextRenderer;
720
+ /**
721
+ * This instance's sanitizer policy, for every HTML write the renderer makes.
722
+ * Absent, the process default set by `setSanitizerPolicy()` applies.
723
+ */
724
+ readonly sanitizerPolicy?: SanitizerPolicyMode;
725
+ /**
726
+ * Say that this write cannot reproduce what the server drew, so
727
+ * `onUnfaithfulPatch` can have a strategy render the region instead of
728
+ * leaving a degraded patch on the page. The built-in rich-text renderer
729
+ * calls it for a Lexical block whose markup it had to drop; a project
730
+ * renderer may call it for any value it can only approximate. `reason`
731
+ * completes the sentence 'field "x" …' in LP0411.
732
+ */
733
+ readonly reportUnfaithful?: (target: CachedElement, reason: string) => void;
563
734
  }
564
735
  /**
565
736
  * A renderer writes one value into its element. It must not throw: one bad
@@ -636,6 +807,10 @@ interface LivePreviewPlugin {
636
807
  * one side — the adapter's request decision or the browser runtime — and a
637
808
  * test asserts the profile assigns every readiness row that has an option, so
638
809
  * a row added later cannot be forgotten. See ADR 0007.
810
+ *
811
+ * It lives in the leaf `types` domain, like `merge-depth.ts`, because the
812
+ * inline generator resolves the profile too, and the generator is server-side
813
+ * code that may not reach the browser runtime in `core`.
639
814
  */
640
815
  /** `'v2'` is the 2.0 default; `'v1'` is the 1.x table. */
641
816
  type DefaultsProfile = 'v1' | 'v2';
@@ -672,6 +847,13 @@ interface LivePreviewClientConfig {
672
847
  readonly skipUnchanged?: boolean;
673
848
  /** Scroll the preview to the field being edited when its value changes. Default `false`. */
674
849
  readonly revealEditedField?: boolean;
850
+ /**
851
+ * Find bindings by value on the connection's first message: a scalar whose
852
+ * value is the whole content of exactly one element is bound to it as if
853
+ * `data-payload-field` stood there; every guess is stamped `data-payload-guessed`
854
+ * and listed in `inspect().bindings.guessed`. Default `'off'`.
855
+ */
856
+ readonly autoBind?: 'off' | 'unique';
675
857
  /** Fields whose change re-applies other bindings regardless of their own value: `{ price: ['priceLabel'] }`. Used with `skipUnchanged`. */
676
858
  readonly dependencies?: Readonly<Record<string, readonly string[]>>;
677
859
  /** Strategy handlers beyond patching; `createFragmentStrategy()` from `payload-live-preview/fragment` builds one. */
@@ -696,7 +878,11 @@ interface LivePreviewClientConfig {
696
878
  readonly disableLocalhostMatching?: boolean;
697
879
  /** Which windows may post updates. Default `'parent-or-opener'`; `defaults: 'v1'` sets `'any'`. */
698
880
  readonly eventSourcePolicy?: EventSourcePolicy;
699
- /** Sanitizer policy for rich text and HTML writes. Default `'strict'`; `defaults: 'v1'` sets `'compat'`. */
881
+ /**
882
+ * Sanitizer policy for this client's rich text and HTML writes. Default
883
+ * `'strict'`; `defaults: 'v1'` sets `'compat'`. Per instance: it leaves the
884
+ * process default that `setSanitizerPolicy()` sets for direct `sanitizeHtml()` calls alone.
885
+ */
700
886
  readonly sanitizerPolicy?: 'compat' | 'strict';
701
887
  /** `'v2'` (default) is the 2.0 table; `'v1'` restores every 1.x row at once. Explicit options win. */
702
888
  readonly defaults?: DefaultsProfile;
@@ -759,6 +945,7 @@ declare function initLivePreview(config?: LivePreviewClientConfig): LivePreviewC
759
945
  interface FocusReportTarget {
760
946
  postMessage: (message: unknown, targetOrigin: string) => void;
761
947
  }
948
+ /** @internal */
762
949
  interface PreviewFocusMessage {
763
950
  readonly type: 'payload-live-preview-focus';
764
951
  readonly field: string;
@@ -794,6 +981,39 @@ interface NavigationLifecycleOptions {
794
981
  /** Returns an unbind function; calling it twice is harmless. */
795
982
  declare function bindNavigationLifecycle(target: NavigationLifecycleTarget, options?: NavigationLifecycleOptions): () => void;
796
983
 
984
+ /**
985
+ * The seam between a host framework's own router and the route strategy.
986
+ *
987
+ * The route strategy answers a revision by fetching the route and morphing it
988
+ * into the living page. On a page whose DOM belongs to a reconciler that is
989
+ * working against the framework, and it was seen to break once: `removeChild`
990
+ * on `null` inside React's commit phase, over markup this package had patched.
991
+ * A host that re-renders the route itself does the same job without the morph
992
+ * and without the second HTML request, so it is given the chance to.
993
+ *
994
+ * Why a named slot on `window` and not a reference: the runtime is an inline
995
+ * script that builds its strategy before any application code has hydrated, so
996
+ * there is nothing to hand a component; `window.__livePreview`, the only other
997
+ * public surface, is created later and not at all outside a preview; and the
998
+ * two richer extension points — plugins and events — are reachable only through
999
+ * the programmatic client, which a page using an adapter does not have. One
1000
+ * slot, written by whoever mounts and read at the moment of a refresh, is the
1001
+ * smallest thing that survives both orders of arrival.
1002
+ */
1003
+ /**
1004
+ * A host's own route refresh. It must settle once the fresh markup is
1005
+ * committed: the runtime re-applies the revision on top of it, and doing that
1006
+ * against the markup being replaced would write into nodes about to be dropped.
1007
+ */
1008
+ type RouteRefresh = () => void | Promise<void>;
1009
+ /**
1010
+ * Lend the runtime the host's route refresh; the return value undoes it, for a
1011
+ * component's cleanup. A later registration wins, and undoing one that has
1012
+ * already been replaced does nothing — two components on one page would
1013
+ * otherwise take the slot from each other on unmount.
1014
+ */
1015
+ declare function registerRouteRefresh(refresh: RouteRefresh): () => void;
1016
+
797
1017
  interface RuntimeBuildInfo {
798
1018
  readonly generatedAt: string;
799
1019
  readonly size: number;
@@ -844,13 +1064,89 @@ interface InlineScriptConfig {
844
1064
  readonly sanitizerPolicy?: 'compat' | 'strict';
845
1065
  /** Same-origin path of a fragment endpoint; the script then carries the fragment client ahead of the runtime (ADR 0011). */
846
1066
  readonly fragmentEndpoint?: string;
847
- /** Which defaults the omitted options fall back to. Not serialized: `'v1'` only relaxes the generator's `mergeDepth` check. */
1067
+ /**
1068
+ * Carry the route strategy, so a binding in `<head>` or one marked
1069
+ * `data-payload-strategy="route"` refreshes the route. `fragmentEndpoint`
1070
+ * implies it — the fragment prelude already contains it. Default `false`.
1071
+ */
1072
+ readonly routeStrategy?: boolean;
1073
+ /**
1074
+ * The 2.0 name for `onUnfaithfulPatch`, kept until 3.0. `'route'` means
1075
+ * `'escalate'`, `'ignore'` means `'ignore'`.
1076
+ *
1077
+ * @deprecated Renamed to `onUnfaithfulPatch`.
1078
+ */
1079
+ readonly onUnboundChange?: 'ignore' | 'route';
1080
+ /**
1081
+ * What to do when the runtime knows a patch cannot reach what the server
1082
+ * would have drawn. `'escalate'` (the default) hands the region to the
1083
+ * fragment strategy when a boundary covers it and to the route otherwise, so
1084
+ * it needs `fragmentEndpoint` or `routeStrategy` to do anything. `'warn'`
1085
+ * reports LP0411 and keeps the patch; `'ignore'` keeps it silently.
1086
+ */
1087
+ readonly onUnfaithfulPatch?: 'ignore' | 'warn' | 'escalate';
1088
+ /**
1089
+ * Find bindings by value on the connection's first message (ADR 0014): a
1090
+ * scalar whose value is the whole content of exactly one element is bound
1091
+ * to it as if `data-payload-field` stood there. Default `'off'`.
1092
+ */
1093
+ readonly autoBind?: 'off' | 'unique';
1094
+ /**
1095
+ * The framework that hydrates this page (ADR 0015). Under `'react'` the
1096
+ * runtime holds its first write until React has committed the tree that
1097
+ * holds the bindings — otherwise React finds markup it did not render,
1098
+ * throws `Hydration failed` and regenerates the tree, and the write is gone.
1099
+ * Under `'vue'` it holds the write until Vue has mounted the app around them
1100
+ * — otherwise Vue's hydration repairs the write back to the server's value,
1101
+ * quietly. The Next.js and Nuxt adapters set it on every script they emit; a
1102
+ * page built by hand with `generateInlineScript()` may. Omitted: the runtime
1103
+ * starts on `DOMContentLoaded`, as on a static page.
1104
+ */
1105
+ readonly hydration?: 'react' | 'vue';
1106
+ /**
1107
+ * Which defaults the omitted options fall back to, resolved by the generator
1108
+ * rather than the runtime, whose own fallbacks are the 2.0 rows: `'v1'`
1109
+ * writes its four runtime rows into their slots (an explicit option still
1110
+ * wins) and relaxes the `mergeDepth` check. The resolved value always
1111
+ * travels, in the last slot, so a reader of the served page knows what an
1112
+ * empty slot means instead of guessing it — `pll doctor --v2` reads it. The
1113
+ * runtime does not: every row the profile decides is already in its slot.
1114
+ */
848
1115
  readonly defaults?: DefaultsProfile;
1116
+ /**
1117
+ * A runtime artifact to embed instead of the full one — today only
1118
+ * `LEAN_RUNTIME` from `payload-live-preview/lean`, which leaves out the
1119
+ * strategies, the keyed morph, the structural arrays, the item templates and
1120
+ * the announcer (about 5.5 KB gzip less on the page) and reports LP0104 when
1121
+ * a page needs one of them.
1122
+ *
1123
+ * It is an imported value rather than a `profile: 'lean'` string on purpose:
1124
+ * a second artifact behind a string option would sit in every build that can
1125
+ * reach the generator, which measured +24 KB gzip in each adapter entry. This
1126
+ * way the bytes follow the import.
1127
+ *
1128
+ * Not serialized: it decides which bytes are emitted, not how they behave.
1129
+ */
1130
+ readonly runtime?: RuntimeArtifact;
1131
+ }
1132
+ /**
1133
+ * A runtime build this package produces. `source` is the IIFE the page runs;
1134
+ * the two digests describe the same bytes as a servable asset, so asset
1135
+ * delivery can hash-name and SRI-verify whichever artifact was chosen without
1136
+ * hashing anything at request time.
1137
+ */
1138
+ interface RuntimeArtifact {
1139
+ readonly profile: 'lean';
1140
+ readonly source: string;
1141
+ /** Short content hash, for the asset's file name. */
1142
+ readonly contentHash: string;
1143
+ /** `sha384-…`, for the bootstrap's `integrity` attribute. */
1144
+ readonly integrity: string;
849
1145
  }
850
1146
 
851
1147
  /**
852
- * Wraps the build-time runtime IIFE with the consumer's configuration; a page
853
- * with a fragment endpoint gets the fragment prelude ahead of it.
1148
+ * Wraps the build-time runtime IIFE with the consumer's configuration, and
1149
+ * places at most one strategy prelude ahead of it.
854
1150
  */
855
1151
 
856
1152
  /** The inline script body without `<script>` tags; see `wrapWithScriptTag()`. */
@@ -859,12 +1155,13 @@ declare function generateInlineScript(config?: InlineScriptConfig): string;
859
1155
  declare function wrapWithScriptTag(body: string, options?: {
860
1156
  nonce?: string;
861
1157
  }): string;
1158
+ /** @internal */
862
1159
  declare function runtimeBuildInfo(): RuntimeBuildInfo;
863
1160
 
864
1161
  /** HTML and CSS escaping primitives (OWASP XSS Prevention Cheat Sheet). DOM-free. */
865
1162
  /** Escape `text` for an element body or a *quoted* attribute value; strings only, and unquoted attributes are not covered. */
866
1163
  declare function escapeHtml(text: string): string;
867
- /** Escape a value for a *quoted* HTML attribute, leaving URL characters intact; it validates no scheme, so run `isSafeUrl()` on `href`/`src` first. */
1164
+ /** Escape a value for a *quoted* HTML attribute, leaving URL characters intact; it validates no scheme, so run `isSafeUrl()` on `href`/`src` first. @internal */
868
1165
  declare function escapeHtmlAttribute(value: string): string;
869
1166
 
870
1167
  /**
@@ -873,58 +1170,9 @@ declare function escapeHtmlAttribute(value: string): string;
873
1170
  */
874
1171
  /** `true` only for absolute `http`/`https`/`mailto`/`tel` URLs, protocol-relative URLs, paths, `#`/`?` fragments and relative paths. */
875
1172
  declare function isSafeUrl(url: unknown): boolean;
876
- /** Whether a safe URL points at another HTTP(S) origin, protocol-relative forms included, and so needs `noopener` hardening. */
1173
+ /** Whether a URL points at another HTTP(S) origin, protocol-relative forms included, and so needs `noopener` hardening; every URL these two patterns match is one `isSafeUrl` admits. */
877
1174
  declare function isExternalHttpUrl(url: string): boolean;
878
1175
 
879
- /**
880
- * `'strict'` (default) strips `id`, `name` and `data-payload-*` and passes
881
- * other `data-*` only via `allowedDataAttributes`; `'compat'` keeps them.
882
- */
883
- type SanitizerPolicyMode = 'compat' | 'strict';
884
- interface SanitizeOptions {
885
- /** Overrides the module default set by `setSanitizerPolicy()`. */
886
- readonly policy?: SanitizerPolicyMode;
887
- /** `data-*` attributes (full names) that pass under `'strict'`; `data-payload-*` never does. */
888
- readonly allowedDataAttributes?: readonly string[];
889
- /**
890
- * Keep `input`, `button`, `textarea`, `select`, `option` and `label` — only
891
- * for markup the page author wrote, never for CMS content. `form`,
892
- * handlers, `style` and unsafe URLs stay dropped.
893
- */
894
- readonly allowFormControls?: boolean;
895
- /** Extra tags to allow. Lower-case, untrimmed. */
896
- readonly additionalAllowedTags?: readonly string[];
897
- /**
898
- * Extra per-tag attributes, lower-case. Cannot re-admit handlers, `style`,
899
- * or — under `'strict'` — `id`, `name` and `data-payload-*`.
900
- */
901
- readonly additionalAllowedAttributes?: Readonly<Record<string, readonly string[]>>;
902
- /**
903
- * The input is a page-author item template, so `'strict'` keeps the
904
- * applier's reconciliation attributes (`TEMPLATE_ATTRIBUTES`) and nothing
905
- * else — every other `data-payload-*` is still stripped, so a template can
906
- * never add a binding.
907
- */
908
- readonly templateMode?: boolean;
909
- }
910
- /** Set the policy for calls without an explicit `policy`. The runtime sets it from `sanitizerPolicy`. */
911
- declare function setSanitizerPolicy(mode: SanitizerPolicyMode): void;
912
- /** The `Document` surface the sanitizer needs; jsdom, linkedom and happy-dom all provide it. */
913
- interface SanitizerDocument {
914
- createElement: (tagName: string) => {
915
- innerHTML: string;
916
- readonly content: ParentNode;
917
- };
918
- }
919
- /** Supply a `Document` for SSR, e.g. linkedom's `parseHTML(...).document`; `null` clears it. */
920
- declare function setSanitizerDocument(doc: SanitizerDocument | null): void;
921
- /**
922
- * Sanitize `html`; malformed input is recovered by the parser first.
923
- *
924
- * @throws {SanitizerEnvironmentError} when no DOM is available.
925
- */
926
- declare function sanitizeHtml(html: string, options?: SanitizeOptions): string;
927
-
928
1176
  /**
929
1177
  * Content-Security-Policy helpers: nonce generation, directive builders and
930
1178
  * the header merge every adapter uses. Isomorphic; needs only Web Crypto.
@@ -933,9 +1181,9 @@ declare function sanitizeHtml(html: string, options?: SanitizeOptions): string;
933
1181
  interface WebCryptoLike {
934
1182
  getRandomValues: <T extends ArrayBufferView | null>(array: T) => T;
935
1183
  }
936
- /** Supply a Web Crypto implementation for runtimes without `globalThis.crypto`; `null` clears it. */
1184
+ /** Supply a Web Crypto implementation for runtimes without `globalThis.crypto`; `null` clears it. @internal */
937
1185
  declare function setCspCrypto(crypto: WebCryptoLike | null): void;
938
- /** A base64url nonce of `bytes` random bytes (default 16); throws without Web Crypto, since a predictable nonce silently defeats the CSP. */
1186
+ /** A base64url nonce of `bytes` random bytes (default 16); throws without Web Crypto, since a predictable nonce silently defeats the CSP. @internal */
939
1187
  declare function generateCspNonce(bytes?: number): string;
940
1188
  interface FrameAncestorsOptions {
941
1189
  readonly self?: boolean;
@@ -948,6 +1196,7 @@ declare function buildFrameAncestors(options?: FrameAncestorsOptions): string;
948
1196
  * A `script-src` value permitting one nonce plus optional extra sources.
949
1197
  * `'strict-dynamic'` is opt-in: it makes CSP 3 browsers ignore `'self'` and
950
1198
  * host sources, so every script on the page must then carry the nonce.
1199
+ * @internal
951
1200
  */
952
1201
  declare function buildScriptSrcWithNonce(nonce: string, options?: {
953
1202
  readonly self?: boolean;
@@ -1105,6 +1354,22 @@ type PreviewTokenTransport = {
1105
1354
  * a load balancer, so the store is a deployment decision.
1106
1355
  */
1107
1356
  interface PreviewTokenReplayStore {
1357
+ /**
1358
+ * Record `id` as used until `expiresAt` and say whether this call was the
1359
+ * first: `true` admits the token, anything else refuses it as `replayed`, a
1360
+ * throw refuses it as `unavailable`. Check and record in one step (Redis
1361
+ * `SET NX PX`, a unique insert): a read followed by a write lets two requests
1362
+ * that carry the same token and arrive together both pass.
1363
+ */
1364
+ consume(id: string, expiresAt: number): Promise<boolean> | boolean;
1365
+ }
1366
+ /**
1367
+ * @deprecated The 1.x store shape, removed in 3.0. Its two calls cannot be one
1368
+ * step, so two requests with the same token that arrive together both pass
1369
+ * `isUsed` before either reaches `markUsed`. Implement
1370
+ * {@link PreviewTokenReplayStore.consume} instead.
1371
+ */
1372
+ interface PreviewTokenReplayChecks {
1108
1373
  isUsed(id: string): Promise<boolean> | boolean;
1109
1374
  markUsed(id: string, expiresAt: number): Promise<void> | void;
1110
1375
  }
@@ -1120,7 +1385,7 @@ interface SignedTokenStrategy {
1120
1385
  readonly transport?: PreviewTokenTransport;
1121
1386
  /** Resolve the request's locale for the `loc` binding. Unset: tokens with `loc` are refused as `wrong-locale`. */
1122
1387
  readonly locale?: (request: PreviewAuthorizationRequest) => string | undefined;
1123
- readonly replay?: PreviewTokenReplayStore;
1388
+ readonly replay?: PreviewTokenReplayStore | PreviewTokenReplayChecks;
1124
1389
  readonly crypto?: SubtleCryptoLike;
1125
1390
  readonly now?: () => number;
1126
1391
  }
@@ -1177,13 +1442,14 @@ declare function authorizePreviewRequest(request: PreviewAuthorizationRequest, s
1177
1442
  interface TrustedHtmlPolicyLike {
1178
1443
  createHTML(input: string): unknown;
1179
1444
  }
1445
+ /** @internal */
1180
1446
  declare const TRUSTED_TYPES_POLICY_NAME = "payload-live-preview";
1181
1447
  /**
1182
1448
  * Use `policy` for every sink, `null` to assign plain strings, `undefined` to
1183
1449
  * return to the auto-created package policy.
1184
1450
  */
1185
1451
  declare function setTrustedTypesPolicy(policy: TrustedHtmlPolicyLike | null | undefined): void;
1186
- /** `html` as a `TrustedHTML` when a policy exists, else the string. Typed `string` for `innerHTML`. */
1452
+ /** `html` as a `TrustedHTML` when a policy exists, else the string. Typed `string` for `innerHTML`. @internal */
1187
1453
  declare function trustedHtml(html: string): string;
1188
1454
 
1189
1455
  /**
@@ -1198,7 +1464,9 @@ interface PreviewRequestOptions {
1198
1464
  readonly signals?: readonly PreviewSignal[];
1199
1465
  /** Query parameters (value `true` or `1`) that signal intent. Default `['preview', 'draft', 'livePreview']`. */
1200
1466
  readonly queryParams?: readonly string[];
1201
- /** Admin origins whose Referer signals intent, e.g. `['https://cms.example.com']`. */
1467
+ /** Admin origins whose Referer signals intent, e.g. `['https://cms.example.com']` — the adapters' option of the same name. */
1468
+ readonly allowedOrigins?: readonly string[];
1469
+ /** @deprecated Use `allowedOrigins`; removed in 3.0. Ignored when `allowedOrigins` is given. */
1202
1470
  readonly adminOrigins?: readonly string[];
1203
1471
  }
1204
1472
  /** The request surface the predicate reads; `Request` satisfies it, Nitro/H3 events need a shim. */
@@ -1211,6 +1479,26 @@ interface PreviewRequestLike {
1211
1479
  /** Whether `request` carries live-preview intent. Intent, not authorization. */
1212
1480
  declare function hasPreviewIntent(request: PreviewRequestLike, options?: PreviewRequestOptions): boolean;
1213
1481
 
1482
+ /**
1483
+ * The 1.x names that 2.0 renamed, kept so a 1.x project compiles unchanged.
1484
+ *
1485
+ * A file of its own, and a small one: everything deprecated for 3.0 that the
1486
+ * rename ledger produced lives here, so removing it is one deletion rather than
1487
+ * a search. It also keeps the alias out of the module that defines the real
1488
+ * function, where two exports of one value read as an accident.
1489
+ *
1490
+ * Measured against the published 1.8.1 declarations, entry by entry, not
1491
+ * guessed: `isPreviewRequest` was exported from the root **and** from
1492
+ * `./astro`, so it is re-exported from both. The other seven names 2.0 dropped
1493
+ * moved behind `definePreview()` or changed shape, where an alias would restore
1494
+ * the very defaults the move removed (ADR 0007, ledger rows 1 and 9).
1495
+ */
1496
+
1497
+ /**
1498
+ * @deprecated Use `hasPreviewIntent`; removed in 3.0. `pll migrate` rewrites it.
1499
+ */
1500
+ declare const isPreviewRequest: typeof hasPreviewIntent;
1501
+
1214
1502
  interface LexicalNode {
1215
1503
  readonly type: string;
1216
1504
  readonly version?: number;
@@ -1240,7 +1528,16 @@ interface LexicalRoot {
1240
1528
  interface LexicalRenderOptions {
1241
1529
  /** Pass the result through `sanitizeHtml()` (default `true`). */
1242
1530
  readonly sanitize?: boolean;
1531
+ /**
1532
+ * Called for every `block` or `inlineBlock` the registry has no renderer
1533
+ * for, with the block's slug as Payload sent it and the class its empty
1534
+ * placeholder carries. The `richText` write listens: it is the one caller
1535
+ * that later knows whether the server's markup for the block survived, so
1536
+ * the diagnostic is spoken there (LP0410, LP0413), not here.
1537
+ */
1538
+ readonly onUnrenderedBlock?: (blockType: string, placeholderClass: string) => void;
1243
1539
  }
1540
+ /** @internal */
1244
1541
  declare function isLexicalContent(value: unknown): value is LexicalRoot;
1245
1542
  /** Render a Lexical document to HTML; without `setSanitizerDocument()` the result is unsanitised and warns once. */
1246
1543
  declare function lexicalToHtml(content: LexicalRoot, options?: LexicalRenderOptions): string;
@@ -1318,12 +1615,14 @@ declare function documentSavePlugin(options?: DocumentSavePluginOptions): LivePr
1318
1615
  * Where the runtime is running: framed, opened, or on a developer's machine.
1319
1616
  * Nothing reads bundler-injected variables; a Vite consumer passes
1320
1617
  * `import.meta.env.X` explicitly (docs/astro.md).
1618
+ * @internal
1321
1619
  */
1322
1620
  declare function isInIframe(): boolean;
1621
+ /** @internal */
1323
1622
  declare function isInPopup(): boolean;
1324
- /** An iframe or a popup; top-level navigation never starts the preview. */
1623
+ /** An iframe or a popup; top-level navigation never starts the preview. @internal */
1325
1624
  declare function isInPreviewContext(): boolean;
1326
- /** Under Node, `NODE_ENV !== 'production'`; in a browser the hostname, which is the only signal a bundle has. */
1625
+ /** Under Node, `NODE_ENV !== 'production'`; in a browser the hostname, which is the only signal a bundle has. @internal */
1327
1626
  declare function isDevMode(): boolean;
1328
1627
 
1329
1628
  /**
@@ -1365,6 +1664,7 @@ declare class OriginDetector {
1365
1664
  }
1366
1665
 
1367
1666
  /** The locale for `Intl` renders before Payload names one: `<html lang>`, then `navigator.language`, then `'en'`. */
1667
+ /** @internal */
1368
1668
  declare function detectInitialLocale(): string;
1369
1669
 
1370
1670
  /**
@@ -1391,7 +1691,7 @@ interface PayloadMedia {
1391
1691
  readonly height?: number;
1392
1692
  }>>;
1393
1693
  }
1394
- /** `TSlug` is a phantom marker codegen uses to record the target collection; the runtime shape is identical. */
1694
+ /** `TSlug` is a phantom marker codegen uses to record the target collection; the runtime shape is identical. @internal */
1395
1695
  interface PayloadRelationship<TSlug extends string = string> {
1396
1696
  readonly id?: string | number;
1397
1697
  readonly title?: string;
@@ -1404,7 +1704,7 @@ interface PayloadRelationship<TSlug extends string = string> {
1404
1704
 
1405
1705
  /** Built-in field renderers, assembled as values so `sideEffects: false` bundlers keep them all. */
1406
1706
 
1407
- /** One renderer map per client; the stateful text and structural renderers are created fresh each call. */
1707
+ /** One renderer map per client; the stateful text and structural renderers are created fresh each call. @internal */
1408
1708
  declare function buildBuiltinRenderers(): Readonly<Record<string, FieldRenderer>>;
1409
1709
 
1410
1710
  /**
@@ -1412,10 +1712,11 @@ declare function buildBuiltinRenderers(): Readonly<Record<string, FieldRenderer>
1412
1712
  * announces or by observation, since the stock Payload admin announces none:
1413
1713
  * what it can do is read off the messages it sends. See ADR 0010.
1414
1714
  */
1415
- /** Bumped only when this library's understanding of the wire format changes. */
1715
+ /** Bumped only when this library's understanding of the wire format changes. @internal */
1416
1716
  declare const LIBRARY_PROTOCOL_VERSION = 4;
1417
- /** How a capability becomes active. */
1717
+ /** How a capability becomes active. @internal */
1418
1718
  type CapabilitySource = 'version' | 'observed';
1719
+ /** @internal */
1419
1720
  interface CapabilityDeclaration {
1420
1721
  /** Enabled once the negotiated version reaches this (for announced peers). */
1421
1722
  readonly since: number;
@@ -1455,7 +1756,7 @@ declare const CAPABILITY_DECLARATIONS: {
1455
1756
  };
1456
1757
  };
1457
1758
  type ProtocolCapability = keyof typeof CAPABILITY_DECLARATIONS;
1458
- /** Every declared capability, in declaration order. */
1759
+ /** Every declared capability, in declaration order. @internal */
1459
1760
  declare const PROTOCOL_CAPABILITIES: readonly ProtocolCapability[];
1460
1761
  interface ProtocolNegotiation {
1461
1762
  /** This library's protocol version. */
@@ -1471,6 +1772,7 @@ interface ProtocolNegotiation {
1471
1772
  }
1472
1773
  /** Deterministic; the runtime re-runs it whenever either input changes. */
1473
1774
  declare function negotiateProtocol(theirs: number | undefined, observed?: Iterable<ProtocolCapability>): ProtocolNegotiation;
1775
+ /** @internal */
1474
1776
  declare function hasCapability(negotiation: ProtocolNegotiation, capability: ProtocolCapability): boolean;
1475
1777
 
1476
1778
  /**
@@ -1519,12 +1821,12 @@ declare function detectProtocolProfile(observed: ReadonlySet<ProtocolCapability>
1519
1821
  /** Type-level field paths, so a binding name is checked at compile time against the codegen schema. */
1520
1822
  /** String keys of `T`. */
1521
1823
  type FieldName<T> = Extract<keyof T, string>;
1522
- /** Dotted paths into `T`, capped at three levels so IntelliSense stays usable. */
1824
+ /** Dotted paths into `T`, capped at three levels so IntelliSense stays usable. @internal */
1523
1825
  type FieldPath<T, Depth extends 0 | 1 | 2 | 3 = 3> = Depth extends 0 ? never : T extends readonly (infer U)[] ? FieldPath<U, Prev<Depth>> : T extends object ? {
1524
1826
  [K in Extract<keyof T, string>]: K | (T[K] extends object ? `${K}.${FieldPath<T[K], Prev<Depth>>}` : never);
1525
1827
  }[Extract<keyof T, string>] : never;
1526
1828
  type Prev<N extends 0 | 1 | 2 | 3> = N extends 3 ? 2 : N extends 2 ? 1 : N extends 1 ? 0 : 0;
1527
- /** The value type at a dotted path, or `unknown` when the path does not exist. */
1829
+ /** The value type at a dotted path, or `unknown` when the path does not exist. @internal */
1528
1830
  type ValueAt<T, P extends string> = P extends `${infer Head}.${infer Rest}` ? Head extends keyof T ? T[Head] extends readonly (infer U)[] ? ValueAt<U, Rest> : T[Head] extends object ? ValueAt<T[Head], Rest> : unknown : unknown : P extends keyof T ? T[P] : unknown;
1529
1831
 
1530
1832
  /**
@@ -1576,15 +1878,25 @@ declare function bindByPath<T = Record<string, unknown>>(picker: (data: T) => un
1576
1878
  interface OwnerBindingAttributes {
1577
1879
  readonly 'data-payload-owner': string;
1578
1880
  }
1881
+ /** The attributes marking a server-rendered boundary (ADR 0011, docs/hybrid.md). */
1882
+ interface FragmentBoundaryAttributes {
1883
+ readonly 'data-payload-fragment': string;
1884
+ readonly 'data-payload-fragment-key'?: string;
1885
+ readonly 'data-payload-depends'?: string;
1886
+ }
1887
+ interface FragmentBoundaryOptions {
1888
+ /** Distinguishes boundaries when one registry id renders several on a page. */
1889
+ readonly key?: string;
1890
+ /** The fields that re-render the boundary. Without it, every update does. */
1891
+ readonly dependsOn?: readonly string[];
1892
+ }
1579
1893
  /** No attributes at all: an unauthorized response is byte-identical to one that never knew about live preview. */
1580
1894
  type SuppressedBinding = Readonly<Record<string, never>>;
1581
- interface PreviewBindingsCommonOptions {
1582
- /** Document this subtree belongs to, emitted as `data-payload-owner`; needed with `scopeBindingsByOwner`. */
1583
- readonly owner?: string;
1584
- }
1585
1895
  /** The verdict from `authorizePreviewRequest()`, or `null` for a public response. Only a branded context authorizes emission. */
1586
- interface PreviewBindingsOptions extends PreviewBindingsCommonOptions {
1896
+ interface PreviewBindingsOptions {
1587
1897
  readonly authorization: AuthorizedPreviewContext | null;
1898
+ /** Document this subtree belongs to, emitted as `data-payload-owner`; needed with `scopeBindingsByOwner`. */
1899
+ readonly owner?: string;
1588
1900
  }
1589
1901
  /** Request-scoped binding helpers carrying one authorization decision. */
1590
1902
  interface PreviewBindings {
@@ -1595,14 +1907,41 @@ interface PreviewBindings {
1595
1907
  bindByPath: <T = Record<string, unknown>>(picker: (data: T) => unknown, options?: BindOptions) => FieldBindingAttributes | SuppressedBinding;
1596
1908
  /** Owner marker for this subtree, or nothing while unauthorized or without an owner. */
1597
1909
  owner: () => OwnerBindingAttributes | SuppressedBinding;
1910
+ /**
1911
+ * A server-rendered boundary, or nothing while unauthorized — the id and the
1912
+ * fields it depends on describe the content model as much as a binding does.
1913
+ * The registry behind `id` is the endpoint's (docs/hybrid.md).
1914
+ */
1915
+ boundary: (id: string, options?: FragmentBoundaryOptions) => FragmentBoundaryAttributes | SuppressedBinding;
1598
1916
  }
1599
1917
  /** Request-scoped `bind`, `bindByPath` and `owner`, all suppressed unless `authorization` is a real context. */
1600
1918
  declare function createPreviewBindings(options: PreviewBindingsOptions): PreviewBindings;
1601
1919
 
1920
+ /** What a decision publishes for templates on `locals` (Astro, SvelteKit) or `event.context` (Nuxt). */
1921
+
1922
+ /**
1923
+ * The binding helpers for one request, read straight off whatever the framework
1924
+ * calls locals — `Astro.locals`, SvelteKit's `event.locals`, Nuxt's
1925
+ * `event.context`.
1926
+ *
1927
+ * `createPreviewBindings({ authorization: locals.livePreviewAuthorization })`
1928
+ * says the same thing, and a template that spells it out is welcome to. This
1929
+ * exists because generated code should not have to: the build-time annotator
1930
+ * writes one call per component, and a helper that takes `unknown` needs no
1931
+ * `App.Locals` declaration in the project it writes into. The verdict is
1932
+ * checked, not trusted — only a context `authorizePreviewRequest()` produced
1933
+ * emits anything (ADR 0006).
1934
+ * @internal
1935
+ */
1936
+ declare function previewBindingsFromLocals(locals: unknown, options?: {
1937
+ readonly owner?: string;
1938
+ }): PreviewBindings;
1939
+
1602
1940
  /**
1603
1941
  * Hydrated islands own their subtree, so the runtime never patches inside one.
1604
1942
  * Instead every flush dispatches `payload-live-preview:update` on each island
1605
1943
  * root with the update in `detail`. `data-payload-island="patch"` opts back in.
1944
+ * @internal
1606
1945
  */
1607
1946
  declare const ISLAND_EVENT = "payload-live-preview:update";
1608
1947
  interface IslandUpdateDetail {
@@ -1611,7 +1950,7 @@ interface IslandUpdateDetail {
1611
1950
  readonly receivedAt: number;
1612
1951
  readonly locale: string | undefined;
1613
1952
  }
1614
- /** Whether `element` (or an ancestor) is an island that did not opt into patching. */
1953
+ /** Whether `element` (or an ancestor) is an island that did not opt into patching. @internal */
1615
1954
  declare function isInsideIsland(element: Element): boolean;
1616
1955
 
1617
- export { AUTHORIZED_PREVIEW_BRAND_KEY, type AnalyticsSnapshot, type AuthorizedPreviewContext, type AuthorizedPreviewScope, type BindOptions, type BlockRenderContext, type BlockRenderer, CAPABILITY_DECLARATIONS, CAPABILITY_DOCUMENTATION, type CachedElement, type CapabilityDeclaration, type CapabilityDocumentation, type CapabilitySource, type ConnectionStatus, type CspDirectiveMerge, type CustomRendererKey, DIAGNOSTIC_CODES, type DefaultsProfile, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type EventSourcePolicy, type FetchLike, type FieldBindingAttributes, type FieldName, type FieldPath, type FieldRenderer, type FieldTransform, type FieldType, type FocusReportTarget, type FragmentContext, type FragmentReport, type FragmentStrategy, type FrameAncestorsOptions, ISLAND_EVENT, type InlineScriptConfig, type InspectionBindings, type InspectionFragments, type InspectionOrigins, type InspectionProtocol, type InspectionRevisions, type InspectionRoute, type InspectionScheduler, type IslandUpdateDetail, type IssuePreviewTokenOptions, LIBRARY_PROTOCOL_VERSION, type LexicalNode, type LexicalRoot, LivePreviewClient, type LivePreviewClientConfig, type LivePreviewEventMap, type LivePreviewInspection, type LivePreviewPlugin, type NavigationLifecycleOptions, type NavigationLifecycleTarget, OriginDetector, type OwnerBindingAttributes, PROTOCOL_CAPABILITIES, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PayloadLivePreviewMessage, type PayloadMedia, type PayloadRelationship, type PayloadSessionStrategy, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, type PreviewAuthorization, type PreviewAuthorizationOutcome, type PreviewAuthorizationRequest, type PreviewAuthorizationStrategy, type PreviewAuthorizationStrategyName, type PreviewBindings, type PreviewBindingsCommonOptions, type PreviewBindingsOptions, type PreviewFocusMessage, type PreviewRequestLike, type PreviewRequestOptions, type PreviewTokenClaims, type PreviewTokenReplayStore, type PreviewTokenTransport, type PreviewVerifierClaims, type ProtocolCapability, type ProtocolNegotiation, type ProtocolProfile, type ProtocolProfileName, type RenderContext, type RendererKey, type RichTextRenderer, type RouteContext, type RouteStrategy, type SanitizerDocument, type SanitizerPolicyMode, type SignedTokenStrategy, type StrategyHandlers, type SubtleCryptoLike, type SuppressedBinding, TRUSTED_TYPES_POLICY_NAME, type TrustedHtmlPolicyLike, type Unsubscribe, type UpdateSource, VERSION, type ValueAt, type VerifierStrategy, authorizePreviewRequest, bind, bindByPath, bindNavigationLifecycle, buildBuiltinRenderers, buildFrameAncestors, buildScriptSrcWithNonce, createAnalyticsPlugin, createPreviewBindings, createPreviewFocusReporter, debugPlugin, detectInitialLocale, detectProtocolProfile, documentSavePlugin, escapeHtml, escapeHtmlAttribute, generateCspNonce, generateInlineScript, hasCapability, hasPreviewIntent, highlightPlugin, initLivePreview, isAuthorizedPreviewContext, isDevMode, isExternalHttpUrl, isInIframe, isInPopup, isInPreviewContext, isInsideIsland, isLexicalContent, isSafeUrl, issuePreviewToken, lexicalToHtml, lexicalToPlainText, mergeCspHeader, negotiateProtocol, registerBlockRenderer, registerBuiltinRenderer, reportPreviewFocus, runtimeBuildInfo, sanitizeHtml, setCspCrypto, setSanitizerDocument, setSanitizerPolicy, setTrustedTypesPolicy, trustedHtml, wrapWithScriptTag };
1956
+ export { AUTHORIZED_PREVIEW_BRAND_KEY, type AnalyticsSnapshot, type AuthorizedPreviewContext, type AuthorizedPreviewScope, type BindOptions, type BlockRenderContext, type BlockRenderer, CAPABILITY_DECLARATIONS, CAPABILITY_DOCUMENTATION, type CachedElement, type CapabilityDeclaration, type CapabilityDocumentation, type CapabilitySource, type ConnectionStatus, type CspDirectiveMerge, type CustomRendererKey, DIAGNOSTIC_CODES, type DefaultsProfile, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type EventSourcePolicy, type FetchLike, type FieldBindingAttributes, type FieldName, type FieldPath, type FieldRenderer, type FieldTransform, type FieldType, type FocusReportTarget, type FragmentBoundaryAttributes, type FragmentBoundaryOptions, type FragmentContext, type FragmentReport, type FragmentStrategy, type FrameAncestorsOptions, ISLAND_EVENT, type InlineScriptConfig, type InspectionBindings, type InspectionFidelity, type InspectionFragments, type InspectionOrigins, type InspectionProtocol, type InspectionRevisions, type InspectionRoute, type InspectionScheduler, type IslandUpdateDetail, type IssuePreviewTokenOptions, LIBRARY_PROTOCOL_VERSION, type LexicalNode, type LexicalRoot, LivePreviewClient, type LivePreviewClientConfig, type LivePreviewEventMap, type LivePreviewInspection, type LivePreviewPlugin, type NavigationLifecycleOptions, type NavigationLifecycleTarget, OriginDetector, type OwnerBindingAttributes, PROTOCOL_CAPABILITIES, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PayloadLivePreviewMessage, type PayloadMedia, type PayloadRelationship, type PayloadSessionStrategy, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, type PreviewAuthorization, type PreviewAuthorizationOutcome, type PreviewAuthorizationRequest, type PreviewAuthorizationStrategy, type PreviewAuthorizationStrategyName, type PreviewBindings, type PreviewBindingsOptions, type PreviewFocusMessage, type PreviewRequestLike, type PreviewRequestOptions, type PreviewTokenClaims, type PreviewTokenReplayChecks, type PreviewTokenReplayStore, type PreviewTokenTransport, type PreviewVerifierClaims, type ProtocolCapability, type ProtocolNegotiation, type ProtocolProfile, type ProtocolProfileName, type RenderContext, type RendererKey, type RichTextRenderer, type RouteContext, type RouteOutcome, type RouteRefresh, type RouteStrategy, type RuntimeArtifact, type SanitizerDocument, type SanitizerPolicyMode, type SignedTokenStrategy, type StrategyHandlers, type SubtleCryptoLike, type SuppressedBinding, TRUSTED_TYPES_POLICY_NAME, type TrustedHtmlPolicyLike, type Unsubscribe, type UpdateSource, VERSION, type ValueAt, type VerifierStrategy, authorizePreviewRequest, bind, bindByPath, bindNavigationLifecycle, buildBuiltinRenderers, buildFrameAncestors, buildScriptSrcWithNonce, createAnalyticsPlugin, createPreviewBindings, createPreviewFocusReporter, debugPlugin, detectInitialLocale, detectProtocolProfile, documentSavePlugin, escapeHtml, escapeHtmlAttribute, generateCspNonce, generateInlineScript, hasCapability, hasPreviewIntent, highlightPlugin, initLivePreview, isAuthorizedPreviewContext, isDevMode, isExternalHttpUrl, isInIframe, isInPopup, isInPreviewContext, isInsideIsland, isLexicalContent, isPreviewRequest, isSafeUrl, issuePreviewToken, lexicalToHtml, lexicalToPlainText, mergeCspHeader, negotiateProtocol, previewBindingsFromLocals, registerBlockRenderer, registerBuiltinRenderer, registerRouteRefresh, reportPreviewFocus, runtimeBuildInfo, sanitizeHtml, setCspCrypto, setSanitizerDocument, setSanitizerPolicy, setTrustedTypesPolicy, trustedHtml, wrapWithScriptTag };