payload-live-preview 2.0.5 → 2.1.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 (116) hide show
  1. package/README.md +143 -39
  2. package/dist/adapters/astro/FragmentBridge.astro +25 -0
  3. package/dist/adapters/astro/PreviewBoundary.astro +2 -4
  4. package/dist/adapters/astro/RichText.astro +26 -5
  5. package/dist/adapters/astro/index.d.ts +41 -9
  6. package/dist/adapters/astro/index.js +1 -1
  7. package/dist/adapters/astro/index.js.map +1 -1
  8. package/dist/adapters/astro/middleware-entry.d.ts +3 -3
  9. package/dist/adapters/astro/middleware-entry.js +1 -1
  10. package/dist/adapters/astro/middleware-entry.js.map +1 -1
  11. package/dist/adapters/nextjs/index.d.ts +17 -12
  12. package/dist/adapters/nextjs/index.js +1 -1
  13. package/dist/adapters/nextjs/index.js.map +1 -1
  14. package/dist/adapters/nuxt/index.d.ts +11 -6
  15. package/dist/adapters/nuxt/index.js +1 -1
  16. package/dist/adapters/nuxt/index.js.map +1 -1
  17. package/dist/adapters/nuxt/module.d.ts +64 -13
  18. package/dist/adapters/nuxt/module.js +1 -1
  19. package/dist/adapters/nuxt/module.js.map +1 -1
  20. package/dist/adapters/react/index.d.ts +11 -7
  21. package/dist/adapters/react/index.js +1 -1
  22. package/dist/adapters/react/index.js.map +1 -1
  23. package/dist/adapters/sveltekit/index.d.ts +10 -5
  24. package/dist/adapters/sveltekit/index.js +1 -1
  25. package/dist/adapters/sveltekit/index.js.map +1 -1
  26. package/dist/adapters/vue/index.d.ts +10 -7
  27. package/dist/adapters/vue/index.js +1 -1
  28. package/dist/adapters/vue/index.js.map +1 -1
  29. package/dist/annotate.d.ts +15 -2
  30. package/dist/annotate.js.map +1 -1
  31. package/dist/client.cjs +1 -1
  32. package/dist/client.cjs.map +1 -1
  33. package/dist/client.d.cts +367 -266
  34. package/dist/client.d.ts +367 -266
  35. package/dist/client.js +1 -1
  36. package/dist/client.js.map +1 -1
  37. package/dist/codegen-cli.js.map +1 -1
  38. package/dist/codegen.cjs.map +1 -1
  39. package/dist/codegen.d.cts +7 -1
  40. package/dist/codegen.d.ts +7 -1
  41. package/dist/codegen.js.map +1 -1
  42. package/dist/core.cjs +1 -1
  43. package/dist/core.cjs.map +1 -1
  44. package/dist/core.d.cts +544 -392
  45. package/dist/core.d.ts +544 -392
  46. package/dist/core.js +1 -1
  47. package/dist/core.js.map +1 -1
  48. package/dist/doctor-cli.d.ts +1 -1
  49. package/dist/doctor-cli.js +1 -1
  50. package/dist/doctor-cli.js.map +1 -1
  51. package/dist/doctor.d.ts +2 -2
  52. package/dist/doctor.js +1 -1
  53. package/dist/doctor.js.map +1 -1
  54. package/dist/{document-session-BfBfLVpg.d.ts → document-session-DWi9H3Qk.d.ts} +7 -0
  55. package/dist/{fragment-endpoint-DATKU183.d.ts → fragment-endpoint-B2qcRw5T.d.ts} +22 -7
  56. package/dist/fragment.cjs +1 -1
  57. package/dist/fragment.cjs.map +1 -1
  58. package/dist/fragment.d.cts +37 -16
  59. package/dist/fragment.d.ts +37 -16
  60. package/dist/fragment.js +1 -1
  61. package/dist/fragment.js.map +1 -1
  62. package/dist/index.cjs +1 -1
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +598 -400
  65. package/dist/index.d.ts +598 -400
  66. package/dist/index.js +1 -1
  67. package/dist/index.js.map +1 -1
  68. package/dist/lean.cjs +1 -1
  69. package/dist/lean.cjs.map +1 -1
  70. package/dist/lean.d.cts +5 -2
  71. package/dist/lean.d.ts +5 -2
  72. package/dist/lean.js +1 -1
  73. package/dist/lean.js.map +1 -1
  74. package/dist/lexical.cjs +1 -1
  75. package/dist/lexical.cjs.map +1 -1
  76. package/dist/lexical.d.cts +32 -11
  77. package/dist/lexical.d.ts +32 -11
  78. package/dist/lexical.js +1 -1
  79. package/dist/lexical.js.map +1 -1
  80. package/dist/{locals-CNUGYbA_.d.ts → locals-B1mF3aTb.d.ts} +1 -1
  81. package/dist/{middleware-CWObDO37.d.ts → middleware-BGobLN9P.d.ts} +11 -5
  82. package/dist/migrate.js +1 -1
  83. package/dist/migrate.js.map +1 -1
  84. package/dist/{options-uHKrDM2U.d.ts → options-Cm8fC7dj.d.ts} +31 -1
  85. package/dist/payload.cjs +1 -1
  86. package/dist/payload.cjs.map +1 -1
  87. package/dist/payload.d.cts +18 -2
  88. package/dist/payload.d.ts +18 -2
  89. package/dist/payload.js +1 -1
  90. package/dist/payload.js.map +1 -1
  91. package/dist/plugin.cjs +2 -0
  92. package/dist/plugin.cjs.map +1 -0
  93. package/dist/plugin.d.cts +30 -0
  94. package/dist/plugin.d.ts +30 -0
  95. package/dist/plugin.js +2 -0
  96. package/dist/plugin.js.map +1 -0
  97. package/dist/plugins.cjs +1 -1
  98. package/dist/plugins.cjs.map +1 -1
  99. package/dist/plugins.d.cts +102 -29
  100. package/dist/plugins.d.ts +102 -29
  101. package/dist/plugins.js +1 -1
  102. package/dist/plugins.js.map +1 -1
  103. package/dist/{probe-Bzm4fYFL.d.ts → probe-DGPDsnbj.d.ts} +6 -2
  104. package/dist/server.cjs +1 -1
  105. package/dist/server.cjs.map +1 -1
  106. package/dist/server.d.cts +43 -4
  107. package/dist/server.d.ts +43 -4
  108. package/dist/server.js +1 -1
  109. package/dist/server.js.map +1 -1
  110. package/dist/structural.cjs +2 -2
  111. package/dist/structural.cjs.map +1 -1
  112. package/dist/structural.d.cts +61 -13
  113. package/dist/structural.d.ts +61 -13
  114. package/dist/structural.js +2 -2
  115. package/dist/structural.js.map +1 -1
  116. package/package.json +35 -4
@@ -125,13 +125,13 @@ declare const DIAGNOSTIC_CODES: Readonly<{
125
125
  readonly StartupFailed: "LP0605";
126
126
  /** Sending the ready handshake failed. */
127
127
  readonly ReadyFailed: "LP0606";
128
- /** The page declared hydration, but no React commit or Vue mount came within the cap; the runtime started without waiting. */
128
+ /** The page declared hydration, but no React commit, Vue mount or SvelteKit mount came within the cap; the runtime started without waiting. */
129
129
  readonly HydrationWaitTimedOut: "LP0607";
130
130
  /** The audit found no runtime in a response that carried preview intent. */
131
131
  readonly AuditRuntimeMissing: "LP0701";
132
132
  /** The preview response declares no `frame-ancestors`. */
133
133
  readonly AuditNoFrameAncestors: "LP0702";
134
- /** `X-Frame-Options` forbids framing, which no CSP can undo; `SAMEORIGIN` forbids it from another origin only. */
134
+ /** `X-Frame-Options` forbids framing on a response that declares no `frame-ancestors`; `SAMEORIGIN` forbids it from another origin only. */
135
135
  readonly AuditFrameOptionsBlocks: "LP0703";
136
136
  /** Binding attributes are served to anonymous visitors. */
137
137
  readonly AuditBindingsExposed: "LP0704";
@@ -159,6 +159,10 @@ declare const DIAGNOSTIC_CODES: Readonly<{
159
159
  readonly UnboundChangeRefresh: "LP0807";
160
160
  /** `onUnfaithfulPatch: 'escalate'` found no route or fragment strategy to hand an unfaithful patch to; the page keeps it. */
161
161
  readonly EscalationUnavailable: "LP0808";
162
+ /** A fragment inserted an Astro island the page cannot start: it never loaded the island element or that client directive. */
163
+ readonly IslandStartUnavailable: "LP0809";
164
+ /** The host's route refresh returned no promise, so the revision was re-applied before the host committed. */
165
+ readonly RouteRefreshUnconfirmed: "LP0810";
162
166
  /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */
163
167
  readonly V2ReadinessGap: "LP0709";
164
168
  /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */
@@ -177,6 +181,13 @@ type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];
177
181
 
178
182
  /** What produced an update: the runtime's DOM patching, a server-rendered fragment, or a route refresh. */
179
183
  type UpdateSource = 'patch' | 'fragment' | 'route';
184
+ /**
185
+ * What one refresh did. `refreshed` asserts that the strategy rendered the
186
+ * current unsaved revision. `partial` completed a render whose data source was
187
+ * not proven current; the runtime still reapplies every binding it can reach.
188
+ * `refused` is the strategy's own brake and not a failure.
189
+ */
190
+ type RouteOutcome = 'refreshed' | 'partial' | 'failed' | 'refused' | 'superseded';
180
191
 
181
192
  /** Types shared by the runtime primitives. */
182
193
 
@@ -250,6 +261,13 @@ interface RenderContext {
250
261
  readonly schema: PayloadFieldSchema | undefined;
251
262
  /** The project's rich-text renderer, when the client was configured with one. */
252
263
  readonly renderRichText?: RichTextRenderer;
264
+ /**
265
+ * The Payload server the runtime reads populated documents from (`serverURL`),
266
+ * absent without one. A renderer that writes a URL out of a media document
267
+ * resolves a path against it, as Payload's admin does; the built-in `upload`
268
+ * and `image` renderers do.
269
+ */
270
+ readonly serverURL?: string;
253
271
  /**
254
272
  * This instance's sanitizer policy, for every HTML write the renderer makes.
255
273
  * Absent, the process default set by `setSanitizerPolicy()` applies.
@@ -275,29 +293,6 @@ interface FieldRenderer {
275
293
  render(target: CachedElement, value: unknown, context: RenderContext): void;
276
294
  }
277
295
 
278
- /**
279
- * Shape of the `inspect()` snapshot. It only re-reads what the page already
280
- * shows — origins from the injected script, field names from the DOM,
281
- * counters derived from both — so it stays available in production, where a
282
- * misbehaving preview is exactly the case worth diagnosing. Reading one
283
- * performs no I/O and transmits nothing.
284
- */
285
-
286
- /** One plugin as `inspect().plugins` reports it. */
287
- interface PluginInspection {
288
- readonly name: string;
289
- readonly version: string | undefined;
290
- /** `initializing` while `init` runs, `active` afterwards, `tearing-down` while `destroy` runs. */
291
- readonly state: 'initializing' | 'active' | 'tearing-down';
292
- /** Live registrations owned by the plugin's scope, by kind. */
293
- readonly registrations: {
294
- readonly transforms: number;
295
- readonly renderers: number;
296
- readonly subscriptions: number;
297
- readonly cleanups: number;
298
- };
299
- }
300
-
301
296
  /** Public event payloads. The map keys are the valid event names; `EventEmitter` is generic over it. */
302
297
 
303
298
  interface LivePreviewEventMap {
@@ -360,6 +355,12 @@ interface LivePreviewEventMap {
360
355
  readonly revision: number;
361
356
  readonly receivedAt: number;
362
357
  };
358
+ /**
359
+ * A revision left `pending`: it is current, partial (with the shortfalls
360
+ * that kept it from being current), unconfirmed by an island, or superseded.
361
+ * Fires again when an unconfirmed revision is confirmed (ADR 0023).
362
+ */
363
+ readonly revisionDisplay: RevisionDisplay;
363
364
  /** A `payload-document-event` message arrived (document save). */
364
365
  readonly documentSave: {
365
366
  readonly timestamp: number;
@@ -418,6 +419,73 @@ declare class EventEmitter<TMap extends object = LivePreviewEventMap> {
418
419
  eventNames(): (keyof TMap)[];
419
420
  }
420
421
 
422
+ /**
423
+ * How completely the page shows one revision (ADR 0023). The session counters
424
+ * say what happened over a session; this says, for the revision in flight,
425
+ * whether work is outstanding and which step fell short, so a host does not
426
+ * have to attribute route outcomes and fragment fallbacks itself.
427
+ */
428
+
429
+ /** Where a revision stands: work left, shown, shown with shortfalls, awaiting an island, or replaced (ADR 0023). */
430
+ type RevisionDisplayState = 'pending' | 'current' | 'partial' | 'unconfirmed' | 'superseded';
431
+ /** One step that kept a settled revision from being current. */
432
+ type RevisionShortfall = {
433
+ readonly kind: 'fragment';
434
+ readonly id: string;
435
+ readonly key: string | undefined;
436
+ readonly code: DiagnosticCode;
437
+ } | {
438
+ readonly kind: 'route-saved';
439
+ } | {
440
+ readonly kind: 'route-failed';
441
+ readonly outcome: RouteOutcome;
442
+ } | {
443
+ readonly kind: 'unfaithful' | 'unbound';
444
+ readonly field: string;
445
+ } | {
446
+ readonly kind: 'write';
447
+ readonly field: string;
448
+ readonly code: DiagnosticCode;
449
+ } | {
450
+ readonly kind: 'merge';
451
+ };
452
+ /** How completely the page shows one accepted revision (ADR 0023). */
453
+ interface RevisionDisplay {
454
+ /** The message revision this record is about. */
455
+ readonly revision: number;
456
+ /** `pending` while work is left; the other states once it settled. */
457
+ readonly state: RevisionDisplayState;
458
+ /** What kept a settled revision from being current; empty unless `state` is `partial`. */
459
+ readonly shortfalls: readonly RevisionShortfall[];
460
+ /** Writes the visibility gate holds until their element is seen; they count as landed. */
461
+ readonly deferred: number;
462
+ /** Islands the revision was handed to that have not called `displayed()`. */
463
+ readonly awaitingIslands: number;
464
+ }
465
+
466
+ /**
467
+ * Shape of the `inspect()` snapshot. It only re-reads what the page already
468
+ * shows — origins from the injected script, field names from the DOM,
469
+ * counters derived from both — so it stays available in production, where a
470
+ * misbehaving preview is exactly the case worth diagnosing. Reading one
471
+ * performs no I/O and transmits nothing.
472
+ */
473
+
474
+ /** One plugin as `inspect().plugins` reports it. */
475
+ interface PluginInspection {
476
+ readonly name: string;
477
+ readonly version: string | undefined;
478
+ /** `initializing` while `init` runs, `active` afterwards, `tearing-down` while `destroy` runs. */
479
+ readonly state: 'initializing' | 'active' | 'tearing-down';
480
+ /** Live registrations owned by the plugin's scope, by kind. */
481
+ readonly registrations: {
482
+ readonly transforms: number;
483
+ readonly renderers: number;
484
+ readonly subscriptions: number;
485
+ readonly cleanups: number;
486
+ };
487
+ }
488
+
421
489
  /**
422
490
  * Plugin compatibility claims. The range grammar is the subset a plugin
423
491
  * author writes (`*`, `1.2.3`, `^`, `~`, `>=`, `>`, `<`, `<=`, space-joined
@@ -520,7 +588,7 @@ declare class PluginManager {
520
588
 
521
589
  declare const highlightPlugin: LivePreviewPlugin;
522
590
 
523
- /** `debug` plugin: logs every lifecycle event through the plugin context. */
591
+ /** `debug` plugin: logs init, connect, disconnect, cacheRefresh, beforeUpdate, afterUpdate and error through the plugin context. */
524
592
 
525
593
  declare const debugPlugin: LivePreviewPlugin;
526
594
 
@@ -602,8 +670,13 @@ interface UnboundFieldsOverlayOptions {
602
670
  /** Corner of the preview to sit in. Default `'bottom-right'`. */
603
671
  readonly position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
604
672
  }
605
- /** The document this update named, minus everything the page can already show. @internal */
606
- declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, boundNames: Iterable<string>, locale?: string): readonly string[];
673
+ /**
674
+ * The document this update named, minus everything the page can already show
675
+ * or declares with `data-payload-covers`. Under `subfieldCoverage: 'declared'`
676
+ * the uncovered paths inside partly bound groups are listed too (ADR 0022).
677
+ * @internal
678
+ */
679
+ declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, boundNames: Iterable<string>, locale?: string, coverPaths?: readonly string[], subfieldCoverage?: 'descendant' | 'declared'): readonly string[];
607
680
  /**
608
681
  * ```ts
609
682
  * client.use(createUnboundFieldsOverlayPlugin());
@@ -615,4 +688,4 @@ declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, bo
615
688
  */
616
689
  declare function createUnboundFieldsOverlayPlugin(options?: UnboundFieldsOverlayOptions): LivePreviewPlugin;
617
690
 
618
- export { type AnalyticsSnapshot, type CachedElement, type CustomRendererKey, DIAGNOSTIC_CODES, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type FieldRenderer, type FieldTransform, type FieldType, type LivePreviewEventMap, type LivePreviewPlugin, type PayloadBlockSchema, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, PluginManager, type PluginManagerOptions, type RenderContext, type RendererKey, type RichTextRenderer, type SanitizerPolicyMode, type UnboundFieldsOverlayOptions, type Unsubscribe, type UpdateSource, createAnalyticsPlugin, createUnboundFieldsOverlayPlugin, debugPlugin, documentSavePlugin, highlightPlugin, unboundFieldNames };
691
+ export { type AnalyticsSnapshot, type CachedElement, type CustomRendererKey, DIAGNOSTIC_CODES, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type FieldRenderer, type FieldTransform, type FieldType, type LivePreviewEventMap, type LivePreviewPlugin, type PayloadBlockSchema, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, PluginManager, type PluginManagerOptions, type RenderContext, type RendererKey, type RevisionDisplay, type RevisionDisplayState, type RevisionShortfall, type RichTextRenderer, type RouteOutcome, type SanitizerPolicyMode, type UnboundFieldsOverlayOptions, type Unsubscribe, type UpdateSource, createAnalyticsPlugin, createUnboundFieldsOverlayPlugin, debugPlugin, documentSavePlugin, highlightPlugin, unboundFieldNames };
package/dist/plugins.d.ts CHANGED
@@ -125,13 +125,13 @@ declare const DIAGNOSTIC_CODES: Readonly<{
125
125
  readonly StartupFailed: "LP0605";
126
126
  /** Sending the ready handshake failed. */
127
127
  readonly ReadyFailed: "LP0606";
128
- /** The page declared hydration, but no React commit or Vue mount came within the cap; the runtime started without waiting. */
128
+ /** The page declared hydration, but no React commit, Vue mount or SvelteKit mount came within the cap; the runtime started without waiting. */
129
129
  readonly HydrationWaitTimedOut: "LP0607";
130
130
  /** The audit found no runtime in a response that carried preview intent. */
131
131
  readonly AuditRuntimeMissing: "LP0701";
132
132
  /** The preview response declares no `frame-ancestors`. */
133
133
  readonly AuditNoFrameAncestors: "LP0702";
134
- /** `X-Frame-Options` forbids framing, which no CSP can undo; `SAMEORIGIN` forbids it from another origin only. */
134
+ /** `X-Frame-Options` forbids framing on a response that declares no `frame-ancestors`; `SAMEORIGIN` forbids it from another origin only. */
135
135
  readonly AuditFrameOptionsBlocks: "LP0703";
136
136
  /** Binding attributes are served to anonymous visitors. */
137
137
  readonly AuditBindingsExposed: "LP0704";
@@ -159,6 +159,10 @@ declare const DIAGNOSTIC_CODES: Readonly<{
159
159
  readonly UnboundChangeRefresh: "LP0807";
160
160
  /** `onUnfaithfulPatch: 'escalate'` found no route or fragment strategy to hand an unfaithful patch to; the page keeps it. */
161
161
  readonly EscalationUnavailable: "LP0808";
162
+ /** A fragment inserted an Astro island the page cannot start: it never loaded the island element or that client directive. */
163
+ readonly IslandStartUnavailable: "LP0809";
164
+ /** The host's route refresh returned no promise, so the revision was re-applied before the host committed. */
165
+ readonly RouteRefreshUnconfirmed: "LP0810";
162
166
  /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */
163
167
  readonly V2ReadinessGap: "LP0709";
164
168
  /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */
@@ -177,6 +181,13 @@ type DiagnosticCode = (typeof DIAGNOSTIC_CODES)[keyof typeof DIAGNOSTIC_CODES];
177
181
 
178
182
  /** What produced an update: the runtime's DOM patching, a server-rendered fragment, or a route refresh. */
179
183
  type UpdateSource = 'patch' | 'fragment' | 'route';
184
+ /**
185
+ * What one refresh did. `refreshed` asserts that the strategy rendered the
186
+ * current unsaved revision. `partial` completed a render whose data source was
187
+ * not proven current; the runtime still reapplies every binding it can reach.
188
+ * `refused` is the strategy's own brake and not a failure.
189
+ */
190
+ type RouteOutcome = 'refreshed' | 'partial' | 'failed' | 'refused' | 'superseded';
180
191
 
181
192
  /** Types shared by the runtime primitives. */
182
193
 
@@ -250,6 +261,13 @@ interface RenderContext {
250
261
  readonly schema: PayloadFieldSchema | undefined;
251
262
  /** The project's rich-text renderer, when the client was configured with one. */
252
263
  readonly renderRichText?: RichTextRenderer;
264
+ /**
265
+ * The Payload server the runtime reads populated documents from (`serverURL`),
266
+ * absent without one. A renderer that writes a URL out of a media document
267
+ * resolves a path against it, as Payload's admin does; the built-in `upload`
268
+ * and `image` renderers do.
269
+ */
270
+ readonly serverURL?: string;
253
271
  /**
254
272
  * This instance's sanitizer policy, for every HTML write the renderer makes.
255
273
  * Absent, the process default set by `setSanitizerPolicy()` applies.
@@ -275,29 +293,6 @@ interface FieldRenderer {
275
293
  render(target: CachedElement, value: unknown, context: RenderContext): void;
276
294
  }
277
295
 
278
- /**
279
- * Shape of the `inspect()` snapshot. It only re-reads what the page already
280
- * shows — origins from the injected script, field names from the DOM,
281
- * counters derived from both — so it stays available in production, where a
282
- * misbehaving preview is exactly the case worth diagnosing. Reading one
283
- * performs no I/O and transmits nothing.
284
- */
285
-
286
- /** One plugin as `inspect().plugins` reports it. */
287
- interface PluginInspection {
288
- readonly name: string;
289
- readonly version: string | undefined;
290
- /** `initializing` while `init` runs, `active` afterwards, `tearing-down` while `destroy` runs. */
291
- readonly state: 'initializing' | 'active' | 'tearing-down';
292
- /** Live registrations owned by the plugin's scope, by kind. */
293
- readonly registrations: {
294
- readonly transforms: number;
295
- readonly renderers: number;
296
- readonly subscriptions: number;
297
- readonly cleanups: number;
298
- };
299
- }
300
-
301
296
  /** Public event payloads. The map keys are the valid event names; `EventEmitter` is generic over it. */
302
297
 
303
298
  interface LivePreviewEventMap {
@@ -360,6 +355,12 @@ interface LivePreviewEventMap {
360
355
  readonly revision: number;
361
356
  readonly receivedAt: number;
362
357
  };
358
+ /**
359
+ * A revision left `pending`: it is current, partial (with the shortfalls
360
+ * that kept it from being current), unconfirmed by an island, or superseded.
361
+ * Fires again when an unconfirmed revision is confirmed (ADR 0023).
362
+ */
363
+ readonly revisionDisplay: RevisionDisplay;
363
364
  /** A `payload-document-event` message arrived (document save). */
364
365
  readonly documentSave: {
365
366
  readonly timestamp: number;
@@ -418,6 +419,73 @@ declare class EventEmitter<TMap extends object = LivePreviewEventMap> {
418
419
  eventNames(): (keyof TMap)[];
419
420
  }
420
421
 
422
+ /**
423
+ * How completely the page shows one revision (ADR 0023). The session counters
424
+ * say what happened over a session; this says, for the revision in flight,
425
+ * whether work is outstanding and which step fell short, so a host does not
426
+ * have to attribute route outcomes and fragment fallbacks itself.
427
+ */
428
+
429
+ /** Where a revision stands: work left, shown, shown with shortfalls, awaiting an island, or replaced (ADR 0023). */
430
+ type RevisionDisplayState = 'pending' | 'current' | 'partial' | 'unconfirmed' | 'superseded';
431
+ /** One step that kept a settled revision from being current. */
432
+ type RevisionShortfall = {
433
+ readonly kind: 'fragment';
434
+ readonly id: string;
435
+ readonly key: string | undefined;
436
+ readonly code: DiagnosticCode;
437
+ } | {
438
+ readonly kind: 'route-saved';
439
+ } | {
440
+ readonly kind: 'route-failed';
441
+ readonly outcome: RouteOutcome;
442
+ } | {
443
+ readonly kind: 'unfaithful' | 'unbound';
444
+ readonly field: string;
445
+ } | {
446
+ readonly kind: 'write';
447
+ readonly field: string;
448
+ readonly code: DiagnosticCode;
449
+ } | {
450
+ readonly kind: 'merge';
451
+ };
452
+ /** How completely the page shows one accepted revision (ADR 0023). */
453
+ interface RevisionDisplay {
454
+ /** The message revision this record is about. */
455
+ readonly revision: number;
456
+ /** `pending` while work is left; the other states once it settled. */
457
+ readonly state: RevisionDisplayState;
458
+ /** What kept a settled revision from being current; empty unless `state` is `partial`. */
459
+ readonly shortfalls: readonly RevisionShortfall[];
460
+ /** Writes the visibility gate holds until their element is seen; they count as landed. */
461
+ readonly deferred: number;
462
+ /** Islands the revision was handed to that have not called `displayed()`. */
463
+ readonly awaitingIslands: number;
464
+ }
465
+
466
+ /**
467
+ * Shape of the `inspect()` snapshot. It only re-reads what the page already
468
+ * shows — origins from the injected script, field names from the DOM,
469
+ * counters derived from both — so it stays available in production, where a
470
+ * misbehaving preview is exactly the case worth diagnosing. Reading one
471
+ * performs no I/O and transmits nothing.
472
+ */
473
+
474
+ /** One plugin as `inspect().plugins` reports it. */
475
+ interface PluginInspection {
476
+ readonly name: string;
477
+ readonly version: string | undefined;
478
+ /** `initializing` while `init` runs, `active` afterwards, `tearing-down` while `destroy` runs. */
479
+ readonly state: 'initializing' | 'active' | 'tearing-down';
480
+ /** Live registrations owned by the plugin's scope, by kind. */
481
+ readonly registrations: {
482
+ readonly transforms: number;
483
+ readonly renderers: number;
484
+ readonly subscriptions: number;
485
+ readonly cleanups: number;
486
+ };
487
+ }
488
+
421
489
  /**
422
490
  * Plugin compatibility claims. The range grammar is the subset a plugin
423
491
  * author writes (`*`, `1.2.3`, `^`, `~`, `>=`, `>`, `<`, `<=`, space-joined
@@ -520,7 +588,7 @@ declare class PluginManager {
520
588
 
521
589
  declare const highlightPlugin: LivePreviewPlugin;
522
590
 
523
- /** `debug` plugin: logs every lifecycle event through the plugin context. */
591
+ /** `debug` plugin: logs init, connect, disconnect, cacheRefresh, beforeUpdate, afterUpdate and error through the plugin context. */
524
592
 
525
593
  declare const debugPlugin: LivePreviewPlugin;
526
594
 
@@ -602,8 +670,13 @@ interface UnboundFieldsOverlayOptions {
602
670
  /** Corner of the preview to sit in. Default `'bottom-right'`. */
603
671
  readonly position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
604
672
  }
605
- /** The document this update named, minus everything the page can already show. @internal */
606
- declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, boundNames: Iterable<string>, locale?: string): readonly string[];
673
+ /**
674
+ * The document this update named, minus everything the page can already show
675
+ * or declares with `data-payload-covers`. Under `subfieldCoverage: 'declared'`
676
+ * the uncovered paths inside partly bound groups are listed too (ADR 0022).
677
+ * @internal
678
+ */
679
+ declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, boundNames: Iterable<string>, locale?: string, coverPaths?: readonly string[], subfieldCoverage?: 'descendant' | 'declared'): readonly string[];
607
680
  /**
608
681
  * ```ts
609
682
  * client.use(createUnboundFieldsOverlayPlugin());
@@ -615,4 +688,4 @@ declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, bo
615
688
  */
616
689
  declare function createUnboundFieldsOverlayPlugin(options?: UnboundFieldsOverlayOptions): LivePreviewPlugin;
617
690
 
618
- export { type AnalyticsSnapshot, type CachedElement, type CustomRendererKey, DIAGNOSTIC_CODES, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type FieldRenderer, type FieldTransform, type FieldType, type LivePreviewEventMap, type LivePreviewPlugin, type PayloadBlockSchema, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, PluginManager, type PluginManagerOptions, type RenderContext, type RendererKey, type RichTextRenderer, type SanitizerPolicyMode, type UnboundFieldsOverlayOptions, type Unsubscribe, type UpdateSource, createAnalyticsPlugin, createUnboundFieldsOverlayPlugin, debugPlugin, documentSavePlugin, highlightPlugin, unboundFieldNames };
691
+ export { type AnalyticsSnapshot, type CachedElement, type CustomRendererKey, DIAGNOSTIC_CODES, type DiagnosticCode, type DocumentSaveHandler, type DocumentSavePluginOptions, type DocumentSaveStrategy, EventEmitter, type EventHandler, type FieldRenderer, type FieldTransform, type FieldType, type LivePreviewEventMap, type LivePreviewPlugin, type PayloadBlockSchema, type PayloadDocumentEventDetail, type PayloadFieldCondition, type PayloadFieldSchema, type PayloadFieldType, type PayloadLivePreviewData, type PluginCompatibility, type PluginContext, type PluginDisposer, type PluginEvents, type PluginInspection, PluginManager, type PluginManagerOptions, type RenderContext, type RendererKey, type RevisionDisplay, type RevisionDisplayState, type RevisionShortfall, type RichTextRenderer, type RouteOutcome, type SanitizerPolicyMode, type UnboundFieldsOverlayOptions, type Unsubscribe, type UpdateSource, createAnalyticsPlugin, createUnboundFieldsOverlayPlugin, debugPlugin, documentSavePlugin, highlightPlugin, unboundFieldNames };
package/dist/plugins.js CHANGED
@@ -1,2 +1,2 @@
1
- function e(e){return("object"==typeof e&&null!==e||"function"==typeof e)&&"function"==typeof e.then&&(Promise.resolve(e).catch(()=>{}),!0)}function t(t){return(...n)=>{try{e(t(...n))}catch{}}}var n=t((...e)=>console.error(...e)),i=()=>{},r=class{#e;#t;#n=/* @__PURE__ */new Set;#i="staging";constructor(e,t){this.#e=e,this.#t=t}assertOpen(){if("closed"===this.#i)throw new Error(`Plugin context for "${this.#e}" is no longer active`)}get active(){return"active"===this.#i}eligible(){return"closed"!==this.#i}own(e){return this.assertOpen(),this.#r({kind:"cleanup",acquire:void 0,finalize:void 0,cleanup:e,disposed:!1})}stage(e,t,n){this.assertOpen();const i={kind:e,acquire:t,finalize:n,cleanup:void 0,disposed:!1},r=this.#r(i);if("active"===this.#i)try{this.#o(i)}catch(e){throw this.#s(i),e}return r}counts(){const e={transform:0,renderer:0,subscription:0,cleanup:0};for(const t of this.#n)e[t.kind]+=1;return e}commit(){if("staging"!==this.#i)throw new Error(`Plugin context for "${this.#e}" cannot be committed`);this.#i="committing";try{for(const e of this.#n)this.#o(e);this.#i="active"}catch(e){throw this.close(),e}}close(){if("closed"!==this.#i){this.#i="closed";for(const e of[...this.#n].reverse())this.#s(e);this.#n.clear()}}#r(e){return this.#n.add(e),()=>{this.#s(e)}}#o(e){if(e.disposed||void 0!==e.cleanup||void 0===e.acquire)return;const t=e.acquire();e.cleanup=t??i}#s(t){if(t.disposed)return;t.disposed=!0,this.#n.delete(t);const n=t.cleanup;if(t.cleanup=void 0,void 0!==n)try{e(n())&&this.#t(`plugin "${this.#e}" cleanup returned a Promise/thenable; cleanups must be synchronous`)}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}try{t.finalize?.()}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}}},o=class{#a;#l;#c=/* @__PURE__ */new Set;constructor(e,t){this.#a=e,this.#l=t}on(e,t){return this.#u("on",e,t)}once(e,t){return this.#u("once",e,t)}off(e,t){const n=t;for(const t of[...this.#c])t.event===e&&t.handler===n&&t.dispose()}emit(e,t){return this.#l.assertOpen(),this.#a.emit(e,t)}emitWhile(e,t,n){return this.#l.assertOpen(),this.#a.emitWhile(e,t,()=>{if(!this.#l.eligible())return!1;const e=n();return!!this.#l.eligible()&&e})}listenerCount(e){let t=0;for(const n of this.#c)n.event===e&&(t+=1);return t}removeAllListeners(e){for(const t of[...this.#c])void 0!==e&&t.event!==e||t.dispose()}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#c)e.add(t.event);return[...e]}#u(e,t,n){this.#l.assertOpen();const r=n,o=[...this.#c].find(n=>n.kind===e&&n.event===t&&n.handler===r);if(void 0!==o)return o.dispose;let s=i,a=!0;const l=async t=>{this.#l.active&&a&&("once"===e&&s(),await n(t))},c={kind:e,event:t,handler:r,dispose:i};return s=this.#l.stage("subscription",()=>this.#a[e](t,l),()=>{a=!1,this.#c.delete(c)}),c.dispose=s,this.#c.add(c),s}},s=class{#a;#d;#h;#f;#t;#p=/* @__PURE__ */new Map;#g=/* @__PURE__ */new Map;#m=/* @__PURE__ */new Map;#v=/* @__PURE__ */new Set;#y=/* @__PURE__ */new Map;#w=Promise.resolve();#b=0;constructor(e){this.#a=e.events,this.#d=e.config,this.#h=e.registerFieldRenderer,this.#t=t(e.log);const n=e.onTransformError;this.#f=void 0===n?void 0:t((...e)=>{const t=e[0];try{return n(t)}catch(e){return void this.#t("transform error reporter failed:",e)}})}register(e){return this.#b>0?this.#P(e,!1):this.#S(()=>this.#P(e,!0))}unregister(e){return this.#b>0?this.#L(e,!1):this.#S(async()=>{await this.#L(e,!0)})}destroyAll(){return this.#b>0?this.#x(!1):this.#S(async()=>{await this.#x(!0)})}applyTransforms(t,n,i,r){const o=this.#y.get(t);if(void 0===o||0===o.length)return n;let s=n;for(const a of[...o]){if(!a.active)continue;const{transform:o}=a;if(!1===r?.())return n;try{s=o(s,{fieldName:t,element:i.element,allFields:i.allFields});const a=e(s);if(!1===r?.())return n;if(a)throw new TypeError(`Transform for "${t}" returned a Promise/thenable; transforms must be synchronous`)}catch(e){if(!1===r?.())return n;const i=e instanceof Error?e:new Error(String(e));return this.#t(`transform for "${t}" failed:`,i),this.#f?.(i),n}}return s}list(){return[...this.#p.keys()]}snapshot(){const e=[],t=(e,t,n,i)=>{const r=i.counts();return{name:e,version:t,state:n,registrations:{transforms:r.transform,renderers:r.renderer,subscriptions:r.subscription,cleanups:r.cleanup}}};for(const[n,i]of this.#g)e.push(t(n,void 0,"initializing",i.scope));for(const[n,i]of this.#p)e.push(t(n,i.plugin.version,"active",i.scope));for(const t of this.#m.keys())e.push({name:t,version:void 0,state:"tearing-down",registrations:{transforms:0,renderers:0,subscriptions:0,cleanups:0}});return e}get size(){return this.#p.size}async#P(e,t){if(this.#p.has(e.name)||this.#g.has(e.name)||this.#m.has(e.name))return void this.#t(`plugin "${e.name}" already registered`);const n=function(e,t){if(void 0!==e){if(void 0!==e.runtime&&!function(e,t){const n=function(e){const t=/^v?(\d+)\.(\d+)\.(\d+)/.exec(e.trim());if(null!==t)return[Number(t[1]),Number(t[2]),Number(t[3])]}(e);return void 0!==n&&t.split("||").some(e=>{const i=e.trim().split(/\s+/).filter(e=>e.length>0);return 0===i.length?""===e.trim()&&""===t.trim():i.every(e=>function(e,t){const n=t.trim();if(""===n||"*"===n)return!0;const i=/^(\^|~|>=|<=|>|<|=)?\s*v?(\d+)\.(\d+)\.(\d+)/.exec(n);if(null===i)return!1;const r=i[1]??"=",o=[Number(i[2]),Number(i[3]),Number(i[4])],s=function(e,t){for(let n=0;n<3;n+=1){const i=(e[n]??0)-(t[n]??0);if(0!==i)return i}return 0}(e,o);switch(r){case"=":return 0===s;case">":return s>0;case">=":return s>=0;case"<":return s<0;case"<=":return s<=0;case"~":return s>=0&&e[0]===o[0]&&e[1]===o[1];case"^":return!(s<0)&&(o[0]>0?e[0]===o[0]:o[1]>0?0===e[0]&&e[1]===o[1]:0===e[0]&&0===e[1]&&e[2]===o[2]);default:return!1}}(n,e))})}(t,e.runtime))return`declares runtime ${e.runtime}, this runtime is ${t}`;if(void 0!==e.protocol){if(!Number.isInteger(e.protocol)||e.protocol<1)return`declares an invalid protocol version ${String(e.protocol)}`;if(e.protocol<4)return`declares protocol ${String(e.protocol)}, this runtime speaks ${String(4)}`}}}(e.compat,"2.0.5");if(void 0!==n)return void this.#k(e.name,n);const i=new r(e.name,this.#t),o=this.#A(e.name,i),s={scope:i,cancelled:!1};this.#g.set(e.name,s);try{if(await this.#N(()=>e.init(o),t),s.cancelled)return;i.commit()}catch(t){return i.close(),void(s.cancelled||this.#t(`plugin "${e.name}" init failed:`,t))}finally{this.#g.get(e.name)===s&&this.#g.delete(e.name)}this.#p.set(e.name,{plugin:e,scope:i}),this.#t(`plugin "${e.name}" registered`)}#k(e,t){const n=`plugin "${e}" refused: ${t}`;this.#t(n),this.#a.emit("error",{error:new Error(n),context:"plugin",code:"LP0103"})}#A(e,t){return{events:new o(this.#a,t),registerFieldRenderer:e=>{t.stage("renderer",()=>{const t=this.#h(e);return"function"==typeof t?t:void 0})},registerTransform:(e,n)=>{const i={transform:n,active:!1};t.stage("transform",()=>{i.active=!0;const t=this.#y.get(e);return void 0===t?this.#y.set(e,[i]):t.push(i),()=>{i.active=!1;const t=this.#y.get(e);if(void 0===t)return;const n=t.indexOf(i);n>=0&&t.splice(n,1),0===t.length&&this.#y.delete(e)}})},registerCleanup:e=>{t.own(e)},getConfig:()=>this.#d,log:(...t)=>{this.#t(`[${e}]`,...t)}}}#L(e,t){const n=this.#g.get(e);if(void 0!==n)return n.cancelled=!0,n.scope.close(),Promise.resolve();const i=this.#m.get(e);if(void 0!==i)return this.#v.has(e)?Promise.resolve():t?this.#C(i):i;const r=this.#p.get(e);if(void 0===r)return Promise.resolve();this.#p.delete(e),r.scope.close();const o=Promise.resolve().then(()=>this.#$(e,r.plugin,t));return this.#m.set(e,o),o.then(()=>{this.#m.get(e)===o&&this.#m.delete(e)}),o}async#$(e,t,n){if(void 0!==t.destroy){this.#v.add(e);try{await this.#N(()=>t.destroy?.(),n)}catch(t){this.#t(`plugin "${e}" destroy failed:`,t)}finally{this.#v.delete(e)}}}async#x(e){for(const e of this.#g.values())e.cancelled=!0,e.scope.close();const t=[...this.#p.keys()];for(const n of t)await this.#L(n,e)}async#N(e,t){t?await this.#C(Promise.resolve().then(e)):await e()}async#C(e){this.#b+=1;try{await e}finally{this.#b-=1}}#S(e){const t=this.#w.then(e);return this.#w=t.catch(e=>{this.#t("plugin manager mutation failed:",e)}),t}},a="payload-live-preview-highlight",l=/* @__PURE__ */new WeakMap,c=/* @__PURE__ */new WeakMap,u={name:"highlight",version:"1.0.0",init:e=>{if("undefined"==typeof document||"undefined"==typeof window)return;const t="function"==typeof window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,n=function(e,t){let n=l.get(e);void 0===n||n.connected()||(l.delete(e),n=void 0),void 0===n&&(n=function(e,t){const n=e.getElementById(a);if(n instanceof HTMLStyleElement)return{pluginOwned:!1,connected:()=>n.isConnected,remove:()=>{},owners:0};const i=function(e,t){try{if(!Array.isArray(e.adoptedStyleSheets)||"function"!=typeof CSSStyleSheet)return;const n=new CSSStyleSheet;if("function"!=typeof n.replaceSync)return;return n.replaceSync(t),e.adoptedStyleSheets=[...e.adoptedStyleSheets,n],n}catch{return}}(e,t);if(void 0!==i)return{pluginOwned:!0,connected:()=>e.adoptedStyleSheets.includes(i),remove:()=>{e.adoptedStyleSheets=e.adoptedStyleSheets.filter(e=>e!==i)},owners:0};const r=e.createElement("style");return r.id=a,r.textContent=t,e.head.appendChild(r),{pluginOwned:!0,connected:()=>r.isConnected,remove:()=>{r.remove()},owners:0}}(e,t?".lp-highlight{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px;}":"@keyframes lp-highlight{0%{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px}100%{outline:2px solid transparent;outline-offset:2px}}.lp-highlight{animation:lp-highlight 0.6s ease-out;}"),l.set(e,n));const i=n;i.owners+=1;let r=!0;return()=>{r&&(r=!1,i.owners-=1,i.owners>0||(l.get(e)===i&&l.delete(e),i.pluginOwned&&i.remove()))}}(document,t),i=t?1e3:600,r=/* @__PURE__ */new WeakMap,o=/* @__PURE__ */new Set;e.registerCleanup?.(()=>{for(const e of[...o])e();n()}),e.events.on("elementUpdate",e=>{const t=e.element;r.get(t)?.();const n=function(e){let t=c.get(e);void 0===t&&(t={owners:0,pluginAdded:!e.classList.contains("lp-highlight")},c.set(e,t));const n=t;n.owners+=1,e.classList.add("lp-highlight");let i=!0;return()=>{i&&(i=!1,n.owners-=1,n.owners>0||(c.delete(e),n.pluginAdded&&e.classList.remove("lp-highlight")))}}(t);let s=!1;const a=()=>{s||(s=!0,window.clearTimeout(l),r.get(t)===a&&r.delete(t),o.delete(a),n())},l=window.setTimeout(a,i);o.add(a),r.set(t,a)})}},d={name:"debug",version:"1.0.0",init:e=>{e.events.on("init",()=>{e.log("init")}),e.events.on("connect",t=>{e.log("connect ←",t.origin)}),e.events.on("disconnect",t=>{e.log("disconnect (",t.reason,")")}),e.events.on("cacheRefresh",t=>{e.log("cacheRefresh",t.elementCount,"elements,",t.fieldCount,"fields")}),e.events.on("beforeUpdate",t=>{e.log("beforeUpdate",Object.keys(t.data.fields).length,"fields")}),e.events.on("afterUpdate",t=>{e.log("afterUpdate",t.updatedCount,"in",t.durationMs.toFixed(2),"ms")}),e.events.on("error",t=>{e.log("error in",t.context,":",t.error.message)})}};function h(){let e=0,t=0,n=0;return{name:"analytics",version:"1.0.0",init:i=>{i.events.on("afterUpdate",i=>{e+=1,t+=i.updatedCount,n+=i.durationMs})},getStats:()=>({updateCount:e,totalElements:t,totalDurationMs:n,averageDurationMs:0===e?0:n/e})}}var f="payload-live-preview:scroll";function p(){"undefined"!=typeof window&&(function(){if("undefined"!=typeof window)try{sessionStorage.setItem(f,JSON.stringify({href:window.location.href,x:window.scrollX,y:window.scrollY}))}catch{}}(),window.location.reload())}function g(e={}){const t=e.strategy??"silent";return{name:"document-save",version:"1.1.0",init:n=>{let i=!0;const r=/* @__PURE__ */new Set;n.registerCleanup?.(()=>{i=!1;for(const e of r)e.abort();r.clear()}),function(){if("undefined"!=typeof window)try{const e=sessionStorage.getItem(f);if(null===e)return;sessionStorage.removeItem(f);const t=JSON.parse(e);if(t.href!==window.location.href)return;window.scrollTo(t.x??0,t.y??0)}catch{}}(),n.events.on("documentSave",()=>{if(!i)return;if("silent"===t)return;if("reload"===t)return void p();const o=new AbortController;r.add(o);const s="fetch"===t?async function(e,t,n){if(e.handler)try{await e.handler(n)}catch(e){if(!i||n.aborted)return;t("document-save handler threw:",e)}else t("document-save: fetch strategy selected but no handler supplied")}(e,n.log,o.signal):async function(e,t,n,i){if("undefined"==typeof fetch)return void t("document-save: revalidate strategy needs fetch — not available");const r=e.revalidateUrl??"/api/revalidate";let o=!1;try{const s=await fetch(r,{method:"POST",signal:n,headers:{"Content-Type":"application/json",...e.revalidateHeaders??{}},body:JSON.stringify({source:"payload-live-preview"})});if(!i()||n.aborted)return;o=s.ok,o||t("document-save revalidate non-2xx:",s.status)}catch(e){if(!i()||n.aborted)return;t("document-save revalidate failed:",e)}o||"reload"!==e.onRevalidateFailure||p()}(e,n.log,o.signal,()=>i);s.finally(()=>{r.delete(o)})})}}}var m="data-payload-field",v="data-payload-guessed",y=/* @__PURE__ */new Set(["id","_id","createdAt","updatedAt","createdBy","updatedBy","_status","globalType","collection","locale","localized"]),w="payload-live-preview-unbound",b={"bottom-right":"bottom:12px;right:12px;","bottom-left":"bottom:12px;left:12px;","top-right":"top:12px;right:12px;","top-left":"top:12px;left:12px;"};function P(e,t,n){const i=function(e,t){const n=new Set(e),i=e=>{if(n.has(e))return!0;const t=`${e}.`;for(const e of n)if(e.startsWith(t))return!0;return!1};return e=>{if(i(e))return!0;const n=function(e,t){if(void 0===t||0===t.length)return e;const n=`_${t}`;return e.endsWith(n)?e.slice(0,-n.length):e}(e,t);return n!==e&&i(n)}}(t,n);return Object.keys(e).filter(e=>!y.has(e)&&!i(e)).sort((e,t)=>e.localeCompare(t))}function S(e,t){const n=e.createElement("textarea");n.value=t,n.setAttribute("readonly",""),n.setAttribute("style","position:fixed;opacity:0;pointer-events:none;"),e.body.append(n),n.select(),n.remove()}function L(e,t,n){const i=e.createElement("button");return i.type="button",i.textContent=n,i.setAttribute("style","display:block;width:100%;text-align:left;margin:2px 0;padding:2px 4px;border:0;border-radius:3px;background:#222;color:#7fd1ff;font:inherit;cursor:pointer;"),i.title=`Copy ${m}="${t}"`,i.addEventListener("click",()=>{!function(e,t){const n=e.defaultView?.navigator.clipboard;null==n?S(e,t):n.writeText(t).catch(()=>{S(e,t)})}(e,`${m}="${t}"`),i.textContent=`${n} ✓`}),i}function x(e={}){return{name:"unbound-fields",version:"1.0.0",init:t=>{const n=e.root??("undefined"==typeof document?void 0:document);if(void 0===n)return;if((e.onlyWithDebug??1)&&!0!==t.getConfig().debug)return void t.log("not mounted: the client runs without `debug: true`");const i=function(e,t){const n=function(e){return 9===e.nodeType?e:e.ownerDocument}(e);if(null==n?.body)return null;const i=n.createElement("aside");i.id=w,i.setAttribute("style","position:fixed;z-index:2147483646;max-width:280px;max-height:40vh;overflow:auto;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;background:#111;color:#eee;border:1px solid #333;border-radius:6px;padding:8px 10px;box-shadow:0 4px 16px rgba(0,0,0,0.4);"+t),i.setAttribute("aria-hidden","true"),i.hidden=!0;const r=e=>{const t=n.createElement("div");return t.textContent=e,t.setAttribute("style","font-weight:600;margin-bottom:4px;"),t},o=r("Unbound fields"),s=n.createElement("div"),a=r("Guessed bindings");a.setAttribute("data-testid","guessed-bindings");const l=n.createElement("div");return i.append(o,s,a,l),n.body.append(i),{update:(e,t)=>{i.isConnected||(n.getElementById(w)?.remove(),n.body.append(i)),i.hidden=0===e.length&&0===t.length,o.hidden=0===e.length,s.replaceChildren(...e.map(e=>L(n,e,e))),a.hidden=0===t.length,l.replaceChildren(...t.map(({field:e,matched:t})=>L(n,e,`${e} ← ${JSON.stringify(t)}`)))},destroy:()=>{i.remove()}}}(n,b[e.position??"bottom-right"]);null!==i&&(t.registerCleanup?.(i.destroy),t.events.on("afterUpdate",e=>{const r=P(e.data.fields,function(e){const t=[];for(const n of e.querySelectorAll(`[${m}]`)){const e=n.getAttribute(m);null!==e&&e.length>0&&t.push(e)}return t}(n),e.data.locale),o=function(e){const t=[];for(const n of e.querySelectorAll(`[${v}]`)){const e=n.getAttribute(m);null!==e&&0!==e.length&&t.push({field:e,matched:n.getAttribute(v)??""})}return t}(n);i.update(r,o),r.length>0&&t.log("unbound:",r.join(", ")),o.length>0&&t.log("guessed:",o.map(e=>e.field).join(", "))}))}}}var EventEmitter=class{#T=/* @__PURE__ */new Map;#O=/* @__PURE__ */new Map;on(e,t){return this.#U(this.#T,e,t)}once(e,t){return this.#U(this.#O,e,t)}off(e,t){this.#E(this.#T,e,t),this.#E(this.#O,e,t)}async emit(e,t){await this.#z(e,t)}async emitWhile(e,t,n){return this.#z(e,t,n)}async#z(e,t,n){const i=()=>n?.()??!0;if(!i())return!1;const r=this.#T.get(e);if(r)for(const n of[...r]){if(!i())return!1;if(await this.#R(n,t,e),!i())return!1}if(!i())return!1;const o=this.#O.get(e);if(o&&o.size>0){const n=[...o];this.#O.delete(e);for(const r of n){if(!i())return!1;if(await this.#R(r,t,e),!i())return!1}}return i()}listenerCount(e){return(this.#T.get(e)?.size??0)+(this.#O.get(e)?.size??0)}removeAllListeners(e){if(void 0===e)return this.#T.clear(),void this.#O.clear();this.#T.delete(e),this.#O.delete(e)}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#T.keys())e.add(t);for(const t of this.#O.keys())e.add(t);return[...e]}#U(e,t,n){let i=e.get(t);return i||(i=/* @__PURE__ */new Set,e.set(t,i)),i.add(n),()=>{this.#E(e,t,n)}}#E(e,t,n){const i=e.get(t);void 0!==i&&(i.delete(n),0===i.size&&e.delete(t))}async#R(e,t,i){try{await e(t)}catch(e){const t="string"==typeof i||"number"==typeof i?String(i):"<event>";n(`[live-preview] LP0601: handler for "${t}" threw:`,e)}}},k=Object.freeze({NoTrustedOrigin:"LP0101",ReferrerOnlyTrust:"LP0102",PluginIncompatible:"LP0103",ProfileFeatureOmitted:"LP0104",OrphanField:"LP0201",UnattributableUpdate:"LP0202",UnboundField:"LP0203",VisibilityGateDeferred:"LP0301",UnsafeAttributeWrite:"LP0401",TextTargetHasChildren:"LP0402",MissingArrayTemplate:"LP0403",StructuralItemUnkeyed:"LP0404",StructuralDuplicateKey:"LP0405",StructuralUnstableKeys:"LP0406",UnsupportedStrategy:"LP0407",UnknownValueFormat:"LP0408",SanitizerDroppedAttribute:"LP0409",UnrenderedBlockKept:"LP0410",UnfaithfulPatch:"LP0411",ServerFormatReplaced:"LP0412",UnrenderedBlockLost:"LP0413",MessageRejected:"LP0501",TokenRejected:"LP0502",ProtocolShapeUnknown:"LP0503",HandlerThrew:"LP0601",TransformThrew:"LP0602",RendererThrew:"LP0603",StartupFailed:"LP0605",ReadyFailed:"LP0606",HydrationWaitTimedOut:"LP0607",AuditRuntimeMissing:"LP0701",AuditNoFrameAncestors:"LP0702",AuditFrameOptionsBlocks:"LP0703",AuditBindingsExposed:"LP0704",AuditGateThresholdExceeded:"LP0705",AuditUnownedBindings:"LP0706",AuditNoBindings:"LP0707",AuditNotAPage:"LP0708",FragmentRequestFailed:"LP0801",FragmentResponseInvalid:"LP0802",FragmentUnauthorized:"LP0803",FragmentSuperseded:"LP0804",RouteRefreshLoop:"LP0805",FragmentStrategyUnavailable:"LP0806",UnboundChangeRefresh:"LP0807",EscalationUnavailable:"LP0808",V2ReadinessGap:"LP0709",RuntimeOnPublicPage:"LP0710"});export{k as DIAGNOSTIC_CODES,EventEmitter,s as PluginManager,h as createAnalyticsPlugin,x as createUnboundFieldsOverlayPlugin,d as debugPlugin,g as documentSavePlugin,u as highlightPlugin,P as unboundFieldNames};
1
+ function e(e){return("object"==typeof e&&null!==e||"function"==typeof e)&&"function"==typeof e.then&&(Promise.resolve(e).catch(()=>{}),!0)}function t(t){return(...n)=>{try{e(t(...n))}catch{}}}var n=t((...e)=>console.error(...e)),r=()=>{},i=class{#e;#t;#n=/* @__PURE__ */new Set;#r="staging";constructor(e,t){this.#e=e,this.#t=t}assertOpen(){if("closed"===this.#r)throw new Error(`Plugin context for "${this.#e}" is no longer active`)}get active(){return"active"===this.#r}eligible(){return"closed"!==this.#r}own(e){return this.assertOpen(),this.#i({kind:"cleanup",acquire:void 0,finalize:void 0,cleanup:e,disposed:!1})}stage(e,t,n){this.assertOpen();const r={kind:e,acquire:t,finalize:n,cleanup:void 0,disposed:!1},i=this.#i(r);if("active"===this.#r)try{this.#o(r)}catch(e){throw this.#s(r),e}return i}counts(){const e={transform:0,renderer:0,subscription:0,cleanup:0};for(const t of this.#n)e[t.kind]+=1;return e}commit(){if("staging"!==this.#r)throw new Error(`Plugin context for "${this.#e}" cannot be committed`);this.#r="committing";try{for(const e of this.#n)this.#o(e);this.#r="active"}catch(e){throw this.close(),e}}close(){if("closed"!==this.#r){this.#r="closed";for(const e of[...this.#n].reverse())this.#s(e);this.#n.clear()}}#i(e){return this.#n.add(e),()=>{this.#s(e)}}#o(e){if(e.disposed||void 0!==e.cleanup||void 0===e.acquire)return;const t=e.acquire();e.cleanup=t??r}#s(t){if(t.disposed)return;t.disposed=!0,this.#n.delete(t);const n=t.cleanup;if(t.cleanup=void 0,void 0!==n)try{e(n())&&this.#t(`plugin "${this.#e}" cleanup returned a Promise/thenable; cleanups must be synchronous`)}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}try{t.finalize?.()}catch(e){this.#t(`plugin "${this.#e}" cleanup failed:`,e)}}},o=class{#a;#c;#l=/* @__PURE__ */new Set;constructor(e,t){this.#a=e,this.#c=t}on(e,t){return this.#u("on",e,t)}once(e,t){return this.#u("once",e,t)}off(e,t){const n=t;for(const t of[...this.#l])t.event===e&&t.handler===n&&t.dispose()}emit(e,t){return this.#c.assertOpen(),this.#a.emit(e,t)}emitWhile(e,t,n){return this.#c.assertOpen(),this.#a.emitWhile(e,t,()=>{if(!this.#c.eligible())return!1;const e=n();return!!this.#c.eligible()&&e})}listenerCount(e){let t=0;for(const n of this.#l)n.event===e&&(t+=1);return t}removeAllListeners(e){for(const t of[...this.#l])void 0!==e&&t.event!==e||t.dispose()}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#l)e.add(t.event);return[...e]}#u(e,t,n){this.#c.assertOpen();const i=n,o=[...this.#l].find(n=>n.kind===e&&n.event===t&&n.handler===i);if(void 0!==o)return o.dispose;let s=r,a=!0;const c=async t=>{this.#c.active&&a&&("once"===e&&s(),await n(t))},l={kind:e,event:t,handler:i,dispose:r};return s=this.#c.stage("subscription",()=>this.#a[e](t,c),()=>{a=!1,this.#l.delete(l)}),l.dispose=s,this.#l.add(l),s}},s=class{#a;#d;#h;#f;#t;#p=/* @__PURE__ */new Map;#g=/* @__PURE__ */new Map;#m=/* @__PURE__ */new Map;#v=/* @__PURE__ */new Set;#y=/* @__PURE__ */new Map;#w=Promise.resolve();#b=0;constructor(e){this.#a=e.events,this.#d=e.config,this.#h=e.registerFieldRenderer,this.#t=t(e.log);const n=e.onTransformError;this.#f=void 0===n?void 0:t((...e)=>{const t=e[0];try{return n(t)}catch(e){return void this.#t("transform error reporter failed:",e)}})}register(e){return this.#b>0?this.#P(e,!1):this.#S(()=>this.#P(e,!0))}unregister(e){return this.#b>0?this.#x(e,!1):this.#S(async()=>{await this.#x(e,!0)})}destroyAll(){return this.#b>0?this.#L(!1):this.#S(async()=>{await this.#L(!0)})}applyTransforms(t,n,r,i){const o=this.#y.get(t);if(void 0===o||0===o.length)return n;let s=n;for(const a of[...o]){if(!a.active)continue;const{transform:o}=a;if(!1===i?.())return n;try{s=o(s,{fieldName:t,element:r.element,allFields:r.allFields});const a=e(s);if(!1===i?.())return n;if(a)throw new TypeError(`Transform for "${t}" returned a Promise/thenable; transforms must be synchronous`)}catch(e){if(!1===i?.())return n;const r=e instanceof Error?e:new Error(String(e));return this.#t(`transform for "${t}" failed:`,r),this.#f?.(r),n}}return s}list(){return[...this.#p.keys()]}snapshot(){const e=[],t=(e,t,n,r)=>{const i=r.counts();return{name:e,version:t,state:n,registrations:{transforms:i.transform,renderers:i.renderer,subscriptions:i.subscription,cleanups:i.cleanup}}};for(const[n,r]of this.#g)e.push(t(n,void 0,"initializing",r.scope));for(const[n,r]of this.#p)e.push(t(n,r.plugin.version,"active",r.scope));for(const t of this.#m.keys())e.push({name:t,version:void 0,state:"tearing-down",registrations:{transforms:0,renderers:0,subscriptions:0,cleanups:0}});return e}get size(){return this.#p.size}async#P(e,t){if(this.#p.has(e.name)||this.#g.has(e.name)||this.#m.has(e.name))return void this.#t(`plugin "${e.name}" already registered`);const n=function(e,t){if(void 0!==e){if(void 0!==e.runtime&&!function(e,t){const n=function(e){const t=/^v?(\d+)\.(\d+)\.(\d+)/.exec(e.trim());if(null!==t)return[Number(t[1]),Number(t[2]),Number(t[3])]}(e);return void 0!==n&&t.split("||").some(e=>{const r=e.trim().split(/\s+/).filter(e=>e.length>0);return 0===r.length?""===e.trim()&&""===t.trim():r.every(e=>function(e,t){const n=t.trim();if(""===n||"*"===n)return!0;const r=/^(\^|~|>=|<=|>|<|=)?\s*v?(\d+)\.(\d+)\.(\d+)/.exec(n);if(null===r)return!1;const i=r[1]??"=",o=[Number(r[2]),Number(r[3]),Number(r[4])],s=function(e,t){for(let n=0;n<3;n+=1){const r=(e[n]??0)-(t[n]??0);if(0!==r)return r}return 0}(e,o);switch(i){case"=":return 0===s;case">":return s>0;case">=":return s>=0;case"<":return s<0;case"<=":return s<=0;case"~":return s>=0&&e[0]===o[0]&&e[1]===o[1];case"^":return!(s<0)&&(o[0]>0?e[0]===o[0]:o[1]>0?0===e[0]&&e[1]===o[1]:0===e[0]&&0===e[1]&&e[2]===o[2]);default:return!1}}(n,e))})}(t,e.runtime))return`declares runtime ${e.runtime}, this runtime is ${t}`;if(void 0!==e.protocol){if(!Number.isInteger(e.protocol)||e.protocol<1)return`declares an invalid protocol version ${String(e.protocol)}`;if(e.protocol<4)return`declares protocol ${String(e.protocol)}, this runtime speaks ${String(4)}`}}}(e.compat,"2.1.0");if(void 0!==n)return void this.#k(e.name,n);const r=new i(e.name,this.#t),o=this.#A(e.name,r),s={scope:r,cancelled:!1};this.#g.set(e.name,s);try{if(await this.#$(()=>e.init(o),t),s.cancelled)return;r.commit()}catch(t){return r.close(),void(s.cancelled||this.#t(`plugin "${e.name}" init failed:`,t))}finally{this.#g.get(e.name)===s&&this.#g.delete(e.name)}this.#p.set(e.name,{plugin:e,scope:r}),this.#t(`plugin "${e.name}" registered`)}#k(e,t){const n=`plugin "${e}" refused: ${t}`;this.#t(n),this.#a.emit("error",{error:new Error(n),context:"plugin",code:"LP0103"})}#A(e,t){return{events:new o(this.#a,t),registerFieldRenderer:e=>{t.stage("renderer",()=>{const t=this.#h(e);return"function"==typeof t?t:void 0})},registerTransform:(e,n)=>{const r={transform:n,active:!1};t.stage("transform",()=>{r.active=!0;const t=this.#y.get(e);return void 0===t?this.#y.set(e,[r]):t.push(r),()=>{r.active=!1;const t=this.#y.get(e);if(void 0===t)return;const n=t.indexOf(r);n>=0&&t.splice(n,1),0===t.length&&this.#y.delete(e)}})},registerCleanup:e=>{t.own(e)},getConfig:()=>this.#d,log:(...t)=>{this.#t(`[${e}]`,...t)}}}#x(e,t){const n=this.#g.get(e);if(void 0!==n)return n.cancelled=!0,n.scope.close(),Promise.resolve();const r=this.#m.get(e);if(void 0!==r)return this.#v.has(e)?Promise.resolve():t?this.#C(r):r;const i=this.#p.get(e);if(void 0===i)return Promise.resolve();this.#p.delete(e),i.scope.close();const o=Promise.resolve().then(()=>this.#N(e,i.plugin,t));return this.#m.set(e,o),o.then(()=>{this.#m.get(e)===o&&this.#m.delete(e)}),o}async#N(e,t,n){if(void 0!==t.destroy){this.#v.add(e);try{await this.#$(()=>t.destroy?.(),n)}catch(t){this.#t(`plugin "${e}" destroy failed:`,t)}finally{this.#v.delete(e)}}}async#L(e){for(const e of this.#g.values())e.cancelled=!0,e.scope.close();const t=[...this.#p.keys()];for(const n of t)await this.#x(n,e)}async#$(e,t){t?await this.#C(Promise.resolve().then(e)):await e()}async#C(e){this.#b+=1;try{await e}finally{this.#b-=1}}#S(e){const t=this.#w.then(e);return this.#w=t.catch(e=>{this.#t("plugin manager mutation failed:",e)}),t}},a="payload-live-preview-highlight",c=/* @__PURE__ */new WeakMap,l=/* @__PURE__ */new WeakMap,u={name:"highlight",version:"1.0.0",init:e=>{if("undefined"==typeof document||"undefined"==typeof window)return;const t="function"==typeof window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,n=function(e,t){let n=c.get(e);void 0===n||n.connected()||(c.delete(e),n=void 0),void 0===n&&(n=function(e,t){const n=e.getElementById(a);if(n instanceof HTMLStyleElement)return{pluginOwned:!1,connected:()=>n.isConnected,remove:()=>{},owners:0};const r=function(e,t){try{if(!Array.isArray(e.adoptedStyleSheets)||"function"!=typeof CSSStyleSheet)return;const n=new CSSStyleSheet;if("function"!=typeof n.replaceSync)return;return n.replaceSync(t),e.adoptedStyleSheets=[...e.adoptedStyleSheets,n],n}catch{return}}(e,t);if(void 0!==r)return{pluginOwned:!0,connected:()=>e.adoptedStyleSheets.includes(r),remove:()=>{e.adoptedStyleSheets=e.adoptedStyleSheets.filter(e=>e!==r)},owners:0};const i=e.createElement("style");return i.id=a,i.textContent=t,e.head.appendChild(i),{pluginOwned:!0,connected:()=>i.isConnected,remove:()=>{i.remove()},owners:0}}(e,t?".lp-highlight{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px;}":"@keyframes lp-highlight{0%{outline:2px solid rgba(0,102,204,0.85);outline-offset:2px}100%{outline:2px solid transparent;outline-offset:2px}}.lp-highlight{animation:lp-highlight 0.6s ease-out;}"),c.set(e,n));const r=n;r.owners+=1;let i=!0;return()=>{i&&(i=!1,r.owners-=1,r.owners>0||(c.get(e)===r&&c.delete(e),r.pluginOwned&&r.remove()))}}(document,t),r=t?1e3:600,i=/* @__PURE__ */new WeakMap,o=/* @__PURE__ */new Set;e.registerCleanup?.(()=>{for(const e of[...o])e();n()}),e.events.on("elementUpdate",e=>{const t=e.element;i.get(t)?.();const n=function(e){let t=l.get(e);void 0===t&&(t={owners:0,pluginAdded:!e.classList.contains("lp-highlight")},l.set(e,t));const n=t;n.owners+=1,e.classList.add("lp-highlight");let r=!0;return()=>{r&&(r=!1,n.owners-=1,n.owners>0||(l.delete(e),n.pluginAdded&&e.classList.remove("lp-highlight")))}}(t);let s=!1;const a=()=>{s||(s=!0,window.clearTimeout(c),i.get(t)===a&&i.delete(t),o.delete(a),n())},c=window.setTimeout(a,r);o.add(a),i.set(t,a)})}},d={name:"debug",version:"1.0.0",init:e=>{e.events.on("init",()=>{e.log("init")}),e.events.on("connect",t=>{e.log("connect ←",t.origin)}),e.events.on("disconnect",t=>{e.log("disconnect (",t.reason,")")}),e.events.on("cacheRefresh",t=>{e.log("cacheRefresh",t.elementCount,"elements,",t.fieldCount,"fields")}),e.events.on("beforeUpdate",t=>{e.log("beforeUpdate",Object.keys(t.data.fields).length,"fields")}),e.events.on("afterUpdate",t=>{e.log("afterUpdate",t.updatedCount,"in",t.durationMs.toFixed(2),"ms")}),e.events.on("error",t=>{e.log("error in",t.context,":",t.error.message)})}};function h(){let e=0,t=0,n=0;return{name:"analytics",version:"1.0.0",init:r=>{r.events.on("afterUpdate",r=>{e+=1,t+=r.updatedCount,n+=r.durationMs})},getStats:()=>({updateCount:e,totalElements:t,totalDurationMs:n,averageDurationMs:0===e?0:n/e})}}var f="payload-live-preview:scroll";function p(){"undefined"!=typeof window&&(function(){if("undefined"!=typeof window)try{sessionStorage.setItem(f,JSON.stringify({href:window.location.href,x:window.scrollX,y:window.scrollY}))}catch{}}(),window.location.reload())}function g(e={}){const t=e.strategy??"silent";return{name:"document-save",version:"1.1.0",init:n=>{let r=!0;const i=/* @__PURE__ */new Set;n.registerCleanup?.(()=>{r=!1;for(const e of i)e.abort();i.clear()}),function(){if("undefined"!=typeof window)try{const e=sessionStorage.getItem(f);if(null===e)return;sessionStorage.removeItem(f);const t=JSON.parse(e);if(t.href!==window.location.href)return;window.scrollTo(t.x??0,t.y??0)}catch{}}(),n.events.on("documentSave",()=>{if(!r)return;if("silent"===t)return;if("reload"===t)return void p();const o=new AbortController;i.add(o);const s="fetch"===t?async function(e,t,n){if(e.handler)try{await e.handler(n)}catch(e){if(!r||n.aborted)return;t("document-save handler threw:",e)}else t("document-save: fetch strategy selected but no handler supplied")}(e,n.log,o.signal):async function(e,t,n,r){if("undefined"==typeof fetch)return void t("document-save: revalidate strategy needs fetch — not available");const i=e.revalidateUrl??"/api/revalidate";let o=!1;try{const s=await fetch(i,{method:"POST",signal:n,headers:{"Content-Type":"application/json",...e.revalidateHeaders??{}},body:JSON.stringify({source:"payload-live-preview"})});if(!r()||n.aborted)return;o=s.ok,o||t("document-save revalidate non-2xx:",s.status)}catch(e){if(!r()||n.aborted)return;t("document-save revalidate failed:",e)}o||"reload"!==e.onRevalidateFailure||p()}(e,n.log,o.signal,()=>r);s.finally(()=>{i.delete(o)})})}}}function m(e){if(null==e)return[];const t=/* @__PURE__ */new Set,n=[];for(const r of e.split(/[\s,]+/)){const e=r.trim();0===e.length||t.has(e)||(t.add(e),n.push(e))}return n}var v="data-payload-island";function y(e){return function(e){return"astro-island"===e.tagName.toLowerCase()||e.hasAttribute(v)}(e)&&!("patch"===e.getAttribute(v))}function isInsideIsland(e){let t=e;for(;null!==t;){if(y(t))return!0;t=t.parentElement}return!1}var w="data-payload-field",b="data-payload-depends",P="data-payload-guessed",S="data-payload-covers";function x(e){if((e.getAttribute("data-payload-fragment")??"").length>0)return"fragment";const t=e.getAttribute("data-payload-strategy");return null!==t?"route"===t?"route":void 0:e.hasAttribute(w)&&null!==e.closest("head")?"route":void 0}function L(e){switch(typeof e){case"string":return e.length>65536?void 0:`s:${e}`;case"number":return`n:${Object.is(e,-0)?"-0":String(e)}`;case"boolean":return"b:"+(e?"1":"0");case"bigint":return`i:${String(e)}`;case"undefined":return"u";case"object":{if(null===e)return"z";let t;try{t=JSON.stringify(e)}catch{return}return t.length>65536?void 0:`o:${t}`}case"symbol":case"function":return}}function k(e){return"object"==typeof e&&null!==e}function A(e){return Array.isArray(e)?"array":k(e)?"object":"scalar"}function $(e,t){return k(e)?e[t]:void 0}function C(e,t,n,r){const i=[];let o=0;const s=(e,t,n,a)=>{if(o+=1,r.covers(e))return;const c=L(n);if(void 0!==c&&c===L(t))return;if(!((void 0===t||A(t)===A(n))&&k(n)&&r.reachesBelow(e)&&a<8))return void i.push({path:e,value:n});const l=function(e,t){const n=new Set(Object.keys(t));if(k(e))for(const t of Object.keys(e))n.add(t);return[...n]}(t,n);0===l.length&&i.push({path:e,value:n});for(const r of l){if(o>=1024)return void i.push({path:e,value:n});s(`${e}.${r}`,$(t,r),$(n,r),a+1)}};return s(e,t,n,0),i}var N=/* @__PURE__ */new Set(["id","_id","createdAt","updatedAt","createdBy","updatedBy","_status","globalType","collection","locale","localized"]);function T(e,t){if(void 0===t||0===t.length)return e;const n=`_${t}`;return e.endsWith(n)?e.slice(0,-n.length):e}function O(e,t){const n=new Set(e),r=[...t],i=(e,t)=>{const n=`${t}.`;for(const t of e)if(t.startsWith(n))return!0;return!1};return{covers:e=>n.has(e)||r.some(t=>t===e||e.startsWith(`${t}.`)),reachesBelow:e=>i(n,e)||i(r,e)}}var U="payload-live-preview-unbound",E={"bottom-right":"bottom:12px;right:12px;","bottom-left":"bottom:12px;left:12px;","top-right":"top:12px;right:12px;","top-left":"top:12px;left:12px;"};function R(e,t,n,r=[],i="descendant"){const o=[...t],s=function(e,t,n){const r=O(e,n),i=e=>r.covers(e)||r.reachesBelow(e);return e=>{if(i(e))return!0;const n=T(e,t);return n!==e&&i(n)}}(o,n,r),a=Object.keys(e).filter(e=>!N.has(e)&&!s(e));return"declared"===i&&a.push(...function(e,t,n,r){const i=O(t,r),o=[];for(const[t,r]of Object.entries(e)){if(N.has(t))continue;const e=T(t,n);if(!i.covers(e)&&i.reachesBelow(e))for(const{path:t}of C(e,void 0,r,i))o.push(t)}return o}(e,o,n,r)),[...new Set(a)].sort((e,t)=>e.localeCompare(t))}function z(e,t){const n=e.createElement("textarea");n.value=t,n.setAttribute("readonly",""),n.style.cssText="position:fixed;opacity:0;pointer-events:none;",e.body.append(n),n.select(),n.remove()}function q(e,t,n){const r=e.createElement("button");return r.type="button",r.textContent=n,r.style.cssText="display:block;width:100%;text-align:left;margin:2px 0;padding:2px 4px;border:0;border-radius:3px;background:#222;color:#7fd1ff;font:inherit;cursor:pointer;",r.title=`Copy ${w}="${t}"`,r.addEventListener("click",()=>{!function(e,t){const n=e.defaultView?.navigator.clipboard;null==n?z(e,t):n.writeText(t).catch(()=>{z(e,t)})}(e,`${w}="${t}"`),r.textContent=`${n} ✓`}),r}function F(e={}){return{name:"unbound-fields",version:"1.0.0",init:t=>{const n=e.root??("undefined"==typeof document?void 0:document);if(void 0===n)return;if((e.onlyWithDebug??1)&&!0!==t.getConfig().debug)return void t.log("not mounted: the client runs without `debug: true`");const r=function(e,t){const n=function(e){return 9===e.nodeType?e:e.ownerDocument}(e);if(null==n?.body)return null;const r=n.createElement("aside");r.id=U,r.style.cssText="position:fixed;z-index:2147483646;max-width:280px;max-height:40vh;overflow:auto;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;background:#111;color:#eee;border:1px solid #333;border-radius:6px;padding:8px 10px;box-shadow:0 4px 16px rgba(0,0,0,0.4);"+t,r.setAttribute("aria-hidden","true"),r.hidden=!0;const i=e=>{const t=n.createElement("div");return t.textContent=e,t.style.cssText="font-weight:600;margin-bottom:4px;",t},o=i("Unbound fields"),s=n.createElement("div"),a=i("Guessed bindings");a.setAttribute("data-testid","guessed-bindings");const c=n.createElement("div");return r.append(o,s,a,c),n.body.append(r),{update:(e,t)=>{r.isConnected||(n.getElementById(U)?.remove(),n.body.append(r)),r.hidden=0===e.length&&0===t.length,o.hidden=0===e.length,s.replaceChildren(...e.map(e=>q(n,e,e))),a.hidden=0===t.length,c.replaceChildren(...t.map(({field:e,matched:t})=>q(n,e,`${e} ← ${JSON.stringify(t)}`)))},destroy:()=>{r.remove()}}}(n,E[e.position??"bottom-right"]);if(null===r)return;t.registerCleanup?.(r.destroy);const i="declared"===t.getConfig().subfieldCoverage?"declared":"descendant",o=t.getConfig().strategies??{};t.events.on("afterUpdate",e=>{const s=R(e.data.fields,function(e){const t=[];for(const n of e.querySelectorAll(`[${w}]`)){const e=n.getAttribute(w);null!==e&&e.length>0&&t.push(e)}return t}(n),e.data.locale,function(e,t){const n=[];for(const t of e.querySelectorAll(`[${S}]`))n.push(...m(t.getAttribute(S)));for(const r of e.querySelectorAll(`[${b}]`)){const e=x(r);void 0!==e&&void 0!==t[e]&&(isInsideIsland(r)||n.push(...m(r.getAttribute(b))))}return n}(n,o),i),a=function(e){const t=[];for(const n of e.querySelectorAll(`[${P}]`)){const e=n.getAttribute(w);null!==e&&0!==e.length&&t.push({field:e,matched:n.getAttribute(P)??""})}return t}(n);r.update(s,a),s.length>0&&t.log("unbound:",s.join(", ")),a.length>0&&t.log("guessed:",a.map(e=>e.field).join(", "))})}}}var EventEmitter=class{#T=/* @__PURE__ */new Map;#O=/* @__PURE__ */new Map;on(e,t){return this.#U(this.#T,e,t)}once(e,t){return this.#U(this.#O,e,t)}off(e,t){this.#E(this.#T,e,t),this.#E(this.#O,e,t)}async emit(e,t){await this.#R(e,t)}async emitWhile(e,t,n){return this.#R(e,t,n)}async#R(e,t,n){const r=()=>n?.()??!0;if(!r())return!1;const i=this.#T.get(e);if(i)for(const n of[...i]){if(!r())return!1;if(await this.#z(n,t,e),!r())return!1}if(!r())return!1;const o=this.#O.get(e);if(o&&o.size>0){const n=[...o];this.#O.delete(e);for(const i of n){if(!r())return!1;if(await this.#z(i,t,e),!r())return!1}}return r()}listenerCount(e){return(this.#T.get(e)?.size??0)+(this.#O.get(e)?.size??0)}removeAllListeners(e){if(void 0===e)return this.#T.clear(),void this.#O.clear();this.#T.delete(e),this.#O.delete(e)}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#T.keys())e.add(t);for(const t of this.#O.keys())e.add(t);return[...e]}#U(e,t,n){let r=e.get(t);return r||(r=/* @__PURE__ */new Set,e.set(t,r)),r.add(n),()=>{this.#E(e,t,n)}}#E(e,t,n){const r=e.get(t);void 0!==r&&(r.delete(n),0===r.size&&e.delete(t))}async#z(e,t,r){try{await e(t)}catch(e){const t="string"==typeof r||"number"==typeof r?String(r):"<event>";n(`[live-preview] LP0601: handler for "${t}" threw:`,e)}}},M=Object.freeze({NoTrustedOrigin:"LP0101",ReferrerOnlyTrust:"LP0102",PluginIncompatible:"LP0103",ProfileFeatureOmitted:"LP0104",OrphanField:"LP0201",UnattributableUpdate:"LP0202",UnboundField:"LP0203",VisibilityGateDeferred:"LP0301",UnsafeAttributeWrite:"LP0401",TextTargetHasChildren:"LP0402",MissingArrayTemplate:"LP0403",StructuralItemUnkeyed:"LP0404",StructuralDuplicateKey:"LP0405",StructuralUnstableKeys:"LP0406",UnsupportedStrategy:"LP0407",UnknownValueFormat:"LP0408",SanitizerDroppedAttribute:"LP0409",UnrenderedBlockKept:"LP0410",UnfaithfulPatch:"LP0411",ServerFormatReplaced:"LP0412",UnrenderedBlockLost:"LP0413",MessageRejected:"LP0501",TokenRejected:"LP0502",ProtocolShapeUnknown:"LP0503",HandlerThrew:"LP0601",TransformThrew:"LP0602",RendererThrew:"LP0603",StartupFailed:"LP0605",ReadyFailed:"LP0606",HydrationWaitTimedOut:"LP0607",AuditRuntimeMissing:"LP0701",AuditNoFrameAncestors:"LP0702",AuditFrameOptionsBlocks:"LP0703",AuditBindingsExposed:"LP0704",AuditGateThresholdExceeded:"LP0705",AuditUnownedBindings:"LP0706",AuditNoBindings:"LP0707",AuditNotAPage:"LP0708",FragmentRequestFailed:"LP0801",FragmentResponseInvalid:"LP0802",FragmentUnauthorized:"LP0803",FragmentSuperseded:"LP0804",RouteRefreshLoop:"LP0805",FragmentStrategyUnavailable:"LP0806",UnboundChangeRefresh:"LP0807",EscalationUnavailable:"LP0808",IslandStartUnavailable:"LP0809",RouteRefreshUnconfirmed:"LP0810",V2ReadinessGap:"LP0709",RuntimeOnPublicPage:"LP0710"});export{M as DIAGNOSTIC_CODES,EventEmitter,s as PluginManager,h as createAnalyticsPlugin,F as createUnboundFieldsOverlayPlugin,d as debugPlugin,g as documentSavePlugin,u as highlightPlugin,R as unboundFieldNames};
2
2
  //# sourceMappingURL=plugins.js.map