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
@@ -40,6 +40,12 @@ type PayloadFieldType = 'text' | 'textarea' | 'richText' | 'email' | 'number' |
40
40
  /** `admin.condition` is a function in source and cannot cross `postMessage`; modelled, not consumed. */
41
41
  type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
42
42
 
43
+ /**
44
+ * `'strict'` (default) strips `id`, `name` and `data-payload-*` and passes
45
+ * other `data-*` only via `allowedDataAttributes`; `'compat'` keeps them.
46
+ */
47
+ type SanitizerPolicyMode = 'compat' | 'strict';
48
+
43
49
  /**
44
50
  * Every diagnostic code the runtime and tools emit, so a consumer can branch
45
51
  * on `e.code` instead of matching message text. A code is never reused for a
@@ -47,7 +53,9 @@ type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
47
53
  *
48
54
  * Browser-side reporting sites write the literal (`code: 'LP0603'`) rather than
49
55
  * reading it from this record: the frozen table would then ship in the inline
50
- * runtime for the sake of six characters. Server-side tools may import it.
56
+ * runtime for the sake of six characters — it did, 1 287 B in every page, for
57
+ * the one read Z6 left in the strategy runner, and `diagnostic-codes.test.ts`
58
+ * now holds the artifact free of it. Server-side tools may import it.
51
59
  */
52
60
  /**
53
61
  * Every diagnostic code the runtime can report, by name.
@@ -65,6 +73,8 @@ declare const DIAGNOSTIC_CODES: Readonly<{
65
73
  readonly ReferrerOnlyTrust: "LP0102";
66
74
  /** A plugin declares a runtime range this runtime does not satisfy; it was refused. */
67
75
  readonly PluginIncompatible: "LP0103";
76
+ /** The page carries the lean runtime and needs a feature that profile leaves out. */
77
+ readonly ProfileFeatureOmitted: "LP0104";
68
78
  /** An update named a field with no binding anchor on the page. */
69
79
  readonly OrphanField: "LP0201";
70
80
  /** Owner scoping is on and the update names no document it could belong to. */
@@ -85,10 +95,24 @@ declare const DIAGNOSTIC_CODES: Readonly<{
85
95
  readonly StructuralUnstableKeys: "LP0406";
86
96
  /** A binding asks for a delivery strategy this release does not have; it is left unchanged. */
87
97
  readonly UnsupportedStrategy: "LP0407";
98
+ /** `data-payload-format` names a format the vocabulary does not contain; the default formatting was used instead. */
99
+ readonly UnknownValueFormat: "LP0408";
100
+ /** The strict sanitizer removed an attribute the 1.x `'compat'` policy kept. */
101
+ readonly SanitizerDroppedAttribute: "LP0409";
102
+ /** A Lexical block has no renderer; the markup the server rendered for it is kept instead. */
103
+ readonly UnrenderedBlockKept: "LP0410";
104
+ /** A patch cannot reach what the server would have drawn; `onUnfaithfulPatch` decided what happens next. */
105
+ readonly UnfaithfulPatch: "LP0411";
106
+ /** The first write to a date, number or checkbox binding replaced a different reading of the same value. */
107
+ readonly ServerFormatReplaced: "LP0412";
108
+ /** A Lexical block has no renderer, and the write could not keep the markup the server rendered for it; it is gone. */
109
+ readonly UnrenderedBlockLost: "LP0413";
88
110
  /** A message was rejected before it reached the update pipeline. */
89
111
  readonly MessageRejected: "LP0501";
90
112
  /** A preview token was rejected. */
91
113
  readonly TokenRejected: "LP0502";
114
+ /** A trusted origin sent a message this protocol version does not recognise. */
115
+ readonly ProtocolShapeUnknown: "LP0503";
92
116
  /** A consumer event handler threw. */
93
117
  readonly HandlerThrew: "LP0601";
94
118
  /** A consumer transform threw; the original value was kept. */
@@ -99,11 +123,13 @@ declare const DIAGNOSTIC_CODES: Readonly<{
99
123
  readonly StartupFailed: "LP0605";
100
124
  /** Sending the ready handshake failed. */
101
125
  readonly ReadyFailed: "LP0606";
126
+ /** The page declared hydration, but no React commit or Vue mount came within the cap; the runtime started without waiting. */
127
+ readonly HydrationWaitTimedOut: "LP0607";
102
128
  /** The audit found no runtime in a response that carried preview intent. */
103
129
  readonly AuditRuntimeMissing: "LP0701";
104
130
  /** The preview response declares no `frame-ancestors`. */
105
131
  readonly AuditNoFrameAncestors: "LP0702";
106
- /** `X-Frame-Options` forbids framing, which no CSP can undo. */
132
+ /** `X-Frame-Options` forbids framing, which no CSP can undo; `SAMEORIGIN` forbids it from another origin only. */
107
133
  readonly AuditFrameOptionsBlocks: "LP0703";
108
134
  /** Binding attributes are served to anonymous visitors. */
109
135
  readonly AuditBindingsExposed: "LP0704";
@@ -123,10 +149,12 @@ declare const DIAGNOSTIC_CODES: Readonly<{
123
149
  readonly FragmentUnauthorized: "LP0803";
124
150
  /** A fragment response arrived for a revision that was already superseded and was discarded. */
125
151
  readonly FragmentSuperseded: "LP0804";
126
- /** A route refresh was requested again for the same revision; the loop guard stopped it. */
152
+ /** A route refresh was refused: the loop guard, or the strategy's minimum interval. */
127
153
  readonly RouteRefreshLoop: "LP0805";
128
154
  /** A boundary asks for the fragment strategy but no fragment handler is configured; it is patched. */
129
155
  readonly FragmentStrategyUnavailable: "LP0806";
156
+ /** A revision changed a field with no binding; `onUnfaithfulPatch` refreshed the route. */
157
+ readonly UnboundChangeRefresh: "LP0807";
130
158
  /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */
131
159
  readonly V2ReadinessGap: "LP0709";
132
160
  /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */
@@ -182,7 +210,7 @@ interface CachedElement {
182
210
  /** Nearest enclosing `data-payload-fragment` boundary. Resolved by the cache. */
183
211
  readonly fragmentBoundary?: Element;
184
212
  /** `data-payload-boundary`: an anchor that hides itself while its field is empty. */
185
- readonly boundary?: boolean;
213
+ readonly hidesWhenEmpty?: boolean;
186
214
  /** Write the value into this attribute instead of the content; policed writes. */
187
215
  readonly targetAttribute?: string;
188
216
  /** Optional sibling-field path bound to the element's `href` attribute. */
@@ -197,8 +225,16 @@ interface CachedElement {
197
225
  readonly arraySeparator?: string;
198
226
  /** Optional locale code locked onto this element (overrides the global locale). */
199
227
  readonly locale?: string;
228
+ /** Raw `data-payload-format`; the date and number renderers read the vocabulary. */
229
+ readonly format?: string;
200
230
  /** The document this binding belongs to, from the nearest `data-payload-owner`. */
201
231
  readonly owner?: string;
232
+ /**
233
+ * The value an auto-binding matched on (`data-payload-guessed`), for a
234
+ * binding the runtime found by value rather than one the template declared.
235
+ * Absent for a declared binding.
236
+ */
237
+ readonly guessed?: string;
202
238
  }
203
239
  /** What a renderer is given; `allFields` lets it resolve a sibling field. */
204
240
  interface RenderContext {
@@ -210,6 +246,20 @@ interface RenderContext {
210
246
  readonly schema: PayloadFieldSchema | undefined;
211
247
  /** The project's rich-text renderer, when the client was configured with one. */
212
248
  readonly renderRichText?: RichTextRenderer;
249
+ /**
250
+ * This instance's sanitizer policy, for every HTML write the renderer makes.
251
+ * Absent, the process default set by `setSanitizerPolicy()` applies.
252
+ */
253
+ readonly sanitizerPolicy?: SanitizerPolicyMode;
254
+ /**
255
+ * Say that this write cannot reproduce what the server drew, so
256
+ * `onUnfaithfulPatch` can have a strategy render the region instead of
257
+ * leaving a degraded patch on the page. The built-in rich-text renderer
258
+ * calls it for a Lexical block whose markup it had to drop; a project
259
+ * renderer may call it for any value it can only approximate. `reason`
260
+ * completes the sentence 'field "x" …' in LP0411.
261
+ */
262
+ readonly reportUnfaithful?: (target: CachedElement, reason: string) => void;
213
263
  }
214
264
  /**
215
265
  * A renderer writes one value into its element. It must not throw: one bad
@@ -310,7 +360,15 @@ interface LivePreviewEventMap {
310
360
  readonly documentSave: {
311
361
  readonly timestamp: number;
312
362
  };
313
- /** A data update carried `externallyUpdatedRelationship`: a related document changed in an admin drawer, so the update re-renders unconditionally. */
363
+ /**
364
+ * A save in another document reached the page through
365
+ * `externallyUpdatedRelationship` — an admin-drawer edit. Fires once per
366
+ * such save, not once per message: the panel repeats its last document
367
+ * event in every later message, including its own saves of the previewed
368
+ * document, and neither of those is news. That update re-renders every
369
+ * bound field even under `skipUnchanged`, because a drawer edit changes
370
+ * populated values while the form values stay put.
371
+ */
314
372
  readonly relationshipUpdate: {
315
373
  readonly detail: PayloadDocumentEventDetail;
316
374
  readonly timestamp: number;
@@ -506,4 +564,51 @@ interface DocumentSavePluginOptions {
506
564
  }
507
565
  declare function documentSavePlugin(options?: DocumentSavePluginOptions): LivePreviewPlugin;
508
566
 
509
- 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 Unsubscribe, type UpdateSource, createAnalyticsPlugin, debugPlugin, documentSavePlugin, highlightPlugin };
567
+ /**
568
+ * `unbound-fields` plugin: a development overlay listing the fields an update
569
+ * carried that the page has nowhere to put.
570
+ *
571
+ * Annotating a template is the work this package asks for, and the hardest part
572
+ * of it is knowing what is still missing — `inspect().bindings.orphanFields`
573
+ * answers that in the console, which is the wrong place while you are editing
574
+ * markup. This puts the same answer in the preview, with the attribute to paste
575
+ * one click away.
576
+ *
577
+ * Since ADR 0014 it answers a second question the same way: which bindings the
578
+ * runtime *guessed* (`autoBind: 'unique'`) rather than read from the template.
579
+ * Those are listed apart, with the value each one matched on, so an element
580
+ * that changes without an attribute in the source is never a mystery — and
581
+ * the button offers the attribute that would make the guess a declaration.
582
+ *
583
+ * It is a plugin, not part of the runtime: the inline artifact every page
584
+ * carries must not grow by a development tool (the budget in
585
+ * `scripts/bundle-budgets.ts` is the proof). Register it on a client you build
586
+ * yourself, and only in development.
587
+ */
588
+
589
+ interface UnboundFieldsOverlayOptions {
590
+ /**
591
+ * Mount only when the client runs with `debug: true`. Default `true`: the
592
+ * overlay is a development tool, and a production preview should not grow one
593
+ * because a plugin list was copied between environments.
594
+ */
595
+ readonly onlyWithDebug?: boolean;
596
+ /** Where to look for bindings and where to mount. Default `document`. */
597
+ readonly root?: Document | Element;
598
+ /** Corner of the preview to sit in. Default `'bottom-right'`. */
599
+ readonly position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
600
+ }
601
+ /** The document this update named, minus everything the page can already show. @internal */
602
+ declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, boundNames: Iterable<string>, locale?: string): readonly string[];
603
+ /**
604
+ * ```ts
605
+ * client.use(createUnboundFieldsOverlayPlugin());
606
+ * ```
607
+ *
608
+ * Every update recomputes the list from the message's own fields and the
609
+ * bindings currently in the DOM, so annotating the template makes entries
610
+ * disappear as you save the file.
611
+ */
612
+ declare function createUnboundFieldsOverlayPlugin(options?: UnboundFieldsOverlayOptions): LivePreviewPlugin;
613
+
614
+ 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 };
package/dist/plugins.d.ts CHANGED
@@ -40,6 +40,12 @@ type PayloadFieldType = 'text' | 'textarea' | 'richText' | 'email' | 'number' |
40
40
  /** `admin.condition` is a function in source and cannot cross `postMessage`; modelled, not consumed. */
41
41
  type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
42
42
 
43
+ /**
44
+ * `'strict'` (default) strips `id`, `name` and `data-payload-*` and passes
45
+ * other `data-*` only via `allowedDataAttributes`; `'compat'` keeps them.
46
+ */
47
+ type SanitizerPolicyMode = 'compat' | 'strict';
48
+
43
49
  /**
44
50
  * Every diagnostic code the runtime and tools emit, so a consumer can branch
45
51
  * on `e.code` instead of matching message text. A code is never reused for a
@@ -47,7 +53,9 @@ type PayloadFieldCondition = (data: unknown, siblingData: unknown) => boolean;
47
53
  *
48
54
  * Browser-side reporting sites write the literal (`code: 'LP0603'`) rather than
49
55
  * reading it from this record: the frozen table would then ship in the inline
50
- * runtime for the sake of six characters. Server-side tools may import it.
56
+ * runtime for the sake of six characters — it did, 1 287 B in every page, for
57
+ * the one read Z6 left in the strategy runner, and `diagnostic-codes.test.ts`
58
+ * now holds the artifact free of it. Server-side tools may import it.
51
59
  */
52
60
  /**
53
61
  * Every diagnostic code the runtime can report, by name.
@@ -65,6 +73,8 @@ declare const DIAGNOSTIC_CODES: Readonly<{
65
73
  readonly ReferrerOnlyTrust: "LP0102";
66
74
  /** A plugin declares a runtime range this runtime does not satisfy; it was refused. */
67
75
  readonly PluginIncompatible: "LP0103";
76
+ /** The page carries the lean runtime and needs a feature that profile leaves out. */
77
+ readonly ProfileFeatureOmitted: "LP0104";
68
78
  /** An update named a field with no binding anchor on the page. */
69
79
  readonly OrphanField: "LP0201";
70
80
  /** Owner scoping is on and the update names no document it could belong to. */
@@ -85,10 +95,24 @@ declare const DIAGNOSTIC_CODES: Readonly<{
85
95
  readonly StructuralUnstableKeys: "LP0406";
86
96
  /** A binding asks for a delivery strategy this release does not have; it is left unchanged. */
87
97
  readonly UnsupportedStrategy: "LP0407";
98
+ /** `data-payload-format` names a format the vocabulary does not contain; the default formatting was used instead. */
99
+ readonly UnknownValueFormat: "LP0408";
100
+ /** The strict sanitizer removed an attribute the 1.x `'compat'` policy kept. */
101
+ readonly SanitizerDroppedAttribute: "LP0409";
102
+ /** A Lexical block has no renderer; the markup the server rendered for it is kept instead. */
103
+ readonly UnrenderedBlockKept: "LP0410";
104
+ /** A patch cannot reach what the server would have drawn; `onUnfaithfulPatch` decided what happens next. */
105
+ readonly UnfaithfulPatch: "LP0411";
106
+ /** The first write to a date, number or checkbox binding replaced a different reading of the same value. */
107
+ readonly ServerFormatReplaced: "LP0412";
108
+ /** A Lexical block has no renderer, and the write could not keep the markup the server rendered for it; it is gone. */
109
+ readonly UnrenderedBlockLost: "LP0413";
88
110
  /** A message was rejected before it reached the update pipeline. */
89
111
  readonly MessageRejected: "LP0501";
90
112
  /** A preview token was rejected. */
91
113
  readonly TokenRejected: "LP0502";
114
+ /** A trusted origin sent a message this protocol version does not recognise. */
115
+ readonly ProtocolShapeUnknown: "LP0503";
92
116
  /** A consumer event handler threw. */
93
117
  readonly HandlerThrew: "LP0601";
94
118
  /** A consumer transform threw; the original value was kept. */
@@ -99,11 +123,13 @@ declare const DIAGNOSTIC_CODES: Readonly<{
99
123
  readonly StartupFailed: "LP0605";
100
124
  /** Sending the ready handshake failed. */
101
125
  readonly ReadyFailed: "LP0606";
126
+ /** The page declared hydration, but no React commit or Vue mount came within the cap; the runtime started without waiting. */
127
+ readonly HydrationWaitTimedOut: "LP0607";
102
128
  /** The audit found no runtime in a response that carried preview intent. */
103
129
  readonly AuditRuntimeMissing: "LP0701";
104
130
  /** The preview response declares no `frame-ancestors`. */
105
131
  readonly AuditNoFrameAncestors: "LP0702";
106
- /** `X-Frame-Options` forbids framing, which no CSP can undo. */
132
+ /** `X-Frame-Options` forbids framing, which no CSP can undo; `SAMEORIGIN` forbids it from another origin only. */
107
133
  readonly AuditFrameOptionsBlocks: "LP0703";
108
134
  /** Binding attributes are served to anonymous visitors. */
109
135
  readonly AuditBindingsExposed: "LP0704";
@@ -123,10 +149,12 @@ declare const DIAGNOSTIC_CODES: Readonly<{
123
149
  readonly FragmentUnauthorized: "LP0803";
124
150
  /** A fragment response arrived for a revision that was already superseded and was discarded. */
125
151
  readonly FragmentSuperseded: "LP0804";
126
- /** A route refresh was requested again for the same revision; the loop guard stopped it. */
152
+ /** A route refresh was refused: the loop guard, or the strategy's minimum interval. */
127
153
  readonly RouteRefreshLoop: "LP0805";
128
154
  /** A boundary asks for the fragment strategy but no fragment handler is configured; it is patched. */
129
155
  readonly FragmentStrategyUnavailable: "LP0806";
156
+ /** A revision changed a field with no binding; `onUnfaithfulPatch` refreshed the route. */
157
+ readonly UnboundChangeRefresh: "LP0807";
130
158
  /** A readiness row is not yet at its 2.0 value; `pll doctor --v2` reports it. */
131
159
  readonly V2ReadinessGap: "LP0709";
132
160
  /** The preview runtime is served to anonymous visitors, not only inside the admin frame. */
@@ -182,7 +210,7 @@ interface CachedElement {
182
210
  /** Nearest enclosing `data-payload-fragment` boundary. Resolved by the cache. */
183
211
  readonly fragmentBoundary?: Element;
184
212
  /** `data-payload-boundary`: an anchor that hides itself while its field is empty. */
185
- readonly boundary?: boolean;
213
+ readonly hidesWhenEmpty?: boolean;
186
214
  /** Write the value into this attribute instead of the content; policed writes. */
187
215
  readonly targetAttribute?: string;
188
216
  /** Optional sibling-field path bound to the element's `href` attribute. */
@@ -197,8 +225,16 @@ interface CachedElement {
197
225
  readonly arraySeparator?: string;
198
226
  /** Optional locale code locked onto this element (overrides the global locale). */
199
227
  readonly locale?: string;
228
+ /** Raw `data-payload-format`; the date and number renderers read the vocabulary. */
229
+ readonly format?: string;
200
230
  /** The document this binding belongs to, from the nearest `data-payload-owner`. */
201
231
  readonly owner?: string;
232
+ /**
233
+ * The value an auto-binding matched on (`data-payload-guessed`), for a
234
+ * binding the runtime found by value rather than one the template declared.
235
+ * Absent for a declared binding.
236
+ */
237
+ readonly guessed?: string;
202
238
  }
203
239
  /** What a renderer is given; `allFields` lets it resolve a sibling field. */
204
240
  interface RenderContext {
@@ -210,6 +246,20 @@ interface RenderContext {
210
246
  readonly schema: PayloadFieldSchema | undefined;
211
247
  /** The project's rich-text renderer, when the client was configured with one. */
212
248
  readonly renderRichText?: RichTextRenderer;
249
+ /**
250
+ * This instance's sanitizer policy, for every HTML write the renderer makes.
251
+ * Absent, the process default set by `setSanitizerPolicy()` applies.
252
+ */
253
+ readonly sanitizerPolicy?: SanitizerPolicyMode;
254
+ /**
255
+ * Say that this write cannot reproduce what the server drew, so
256
+ * `onUnfaithfulPatch` can have a strategy render the region instead of
257
+ * leaving a degraded patch on the page. The built-in rich-text renderer
258
+ * calls it for a Lexical block whose markup it had to drop; a project
259
+ * renderer may call it for any value it can only approximate. `reason`
260
+ * completes the sentence 'field "x" …' in LP0411.
261
+ */
262
+ readonly reportUnfaithful?: (target: CachedElement, reason: string) => void;
213
263
  }
214
264
  /**
215
265
  * A renderer writes one value into its element. It must not throw: one bad
@@ -310,7 +360,15 @@ interface LivePreviewEventMap {
310
360
  readonly documentSave: {
311
361
  readonly timestamp: number;
312
362
  };
313
- /** A data update carried `externallyUpdatedRelationship`: a related document changed in an admin drawer, so the update re-renders unconditionally. */
363
+ /**
364
+ * A save in another document reached the page through
365
+ * `externallyUpdatedRelationship` — an admin-drawer edit. Fires once per
366
+ * such save, not once per message: the panel repeats its last document
367
+ * event in every later message, including its own saves of the previewed
368
+ * document, and neither of those is news. That update re-renders every
369
+ * bound field even under `skipUnchanged`, because a drawer edit changes
370
+ * populated values while the form values stay put.
371
+ */
314
372
  readonly relationshipUpdate: {
315
373
  readonly detail: PayloadDocumentEventDetail;
316
374
  readonly timestamp: number;
@@ -506,4 +564,51 @@ interface DocumentSavePluginOptions {
506
564
  }
507
565
  declare function documentSavePlugin(options?: DocumentSavePluginOptions): LivePreviewPlugin;
508
566
 
509
- 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 Unsubscribe, type UpdateSource, createAnalyticsPlugin, debugPlugin, documentSavePlugin, highlightPlugin };
567
+ /**
568
+ * `unbound-fields` plugin: a development overlay listing the fields an update
569
+ * carried that the page has nowhere to put.
570
+ *
571
+ * Annotating a template is the work this package asks for, and the hardest part
572
+ * of it is knowing what is still missing — `inspect().bindings.orphanFields`
573
+ * answers that in the console, which is the wrong place while you are editing
574
+ * markup. This puts the same answer in the preview, with the attribute to paste
575
+ * one click away.
576
+ *
577
+ * Since ADR 0014 it answers a second question the same way: which bindings the
578
+ * runtime *guessed* (`autoBind: 'unique'`) rather than read from the template.
579
+ * Those are listed apart, with the value each one matched on, so an element
580
+ * that changes without an attribute in the source is never a mystery — and
581
+ * the button offers the attribute that would make the guess a declaration.
582
+ *
583
+ * It is a plugin, not part of the runtime: the inline artifact every page
584
+ * carries must not grow by a development tool (the budget in
585
+ * `scripts/bundle-budgets.ts` is the proof). Register it on a client you build
586
+ * yourself, and only in development.
587
+ */
588
+
589
+ interface UnboundFieldsOverlayOptions {
590
+ /**
591
+ * Mount only when the client runs with `debug: true`. Default `true`: the
592
+ * overlay is a development tool, and a production preview should not grow one
593
+ * because a plugin list was copied between environments.
594
+ */
595
+ readonly onlyWithDebug?: boolean;
596
+ /** Where to look for bindings and where to mount. Default `document`. */
597
+ readonly root?: Document | Element;
598
+ /** Corner of the preview to sit in. Default `'bottom-right'`. */
599
+ readonly position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
600
+ }
601
+ /** The document this update named, minus everything the page can already show. @internal */
602
+ declare function unboundFieldNames(fields: Readonly<Record<string, unknown>>, boundNames: Iterable<string>, locale?: string): readonly string[];
603
+ /**
604
+ * ```ts
605
+ * client.use(createUnboundFieldsOverlayPlugin());
606
+ * ```
607
+ *
608
+ * Every update recomputes the list from the message's own fields and the
609
+ * bindings currently in the DOM, so annotating the template makes entries
610
+ * disappear as you save the file.
611
+ */
612
+ declare function createUnboundFieldsOverlayPlugin(options?: UnboundFieldsOverlayOptions): LivePreviewPlugin;
613
+
614
+ 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 };
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=()=>{},s=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.#s({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},s=this.#s(i);if("active"===this.#i)try{this.#r(i)}catch(e){throw this.#o(i),e}return s}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.#r(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.#o(e);this.#n.clear()}}#s(e){return this.#n.add(e),()=>{this.#o(e)}}#r(e){if(e.disposed||void 0!==e.cleanup||void 0===e.acquire)return;const t=e.acquire();e.cleanup=t??i}#o(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)}}},r=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 s=n,r=[...this.#l].find(n=>n.kind===e&&n.event===t&&n.handler===s);if(void 0!==r)return r.dispose;let o=i,a=!0;const c=async t=>{this.#c.active&&a&&("once"===e&&o(),await n(t))},l={kind:e,event:t,handler:s,dispose:i};return o=this.#c.stage("subscription",()=>this.#a[e](t,c),()=>{a=!1,this.#l.delete(l)}),l.dispose=o,this.#l.add(l),o}},o=class{#a;#d;#h;#f;#t;#g=/* @__PURE__ */new Map;#p=/* @__PURE__ */new Map;#m=/* @__PURE__ */new Map;#v=/* @__PURE__ */new Set;#w=/* @__PURE__ */new Map;#y=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.#k(!1):this.#S(async()=>{await this.#k(!0)})}applyTransforms(t,n,i,s){const r=this.#w.get(t);if(void 0===r||0===r.length)return n;let o=n;for(const a of[...r]){if(!a.active)continue;const{transform:r}=a;if(!1===s?.())return n;try{o=r(o,{fieldName:t,element:i.element,allFields:i.allFields});const a=e(o);if(!1===s?.())return n;if(a)throw new TypeError(`Transform for "${t}" returned a Promise/thenable; transforms must be synchronous`)}catch(e){if(!1===s?.())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 o}list(){return[...this.#g.keys()]}snapshot(){const e=[],t=(e,t,n,i)=>{const s=i.counts();return{name:e,version:t,state:n,registrations:{transforms:s.transform,renderers:s.renderer,subscriptions:s.subscription,cleanups:s.cleanup}}};for(const[n,i]of this.#p)e.push(t(n,void 0,"initializing",i.scope));for(const[n,i]of this.#g)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.#g.size}async#P(e,t){if(this.#g.has(e.name)||this.#p.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 s=i[1]??"=",r=[Number(i[2]),Number(i[3]),Number(i[4])],o=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,r);switch(s){case"=":return 0===o;case">":return o>0;case">=":return o>=0;case"<":return o<0;case"<=":return o<=0;case"~":return o>=0&&e[0]===r[0]&&e[1]===r[1];case"^":return!(o<0)&&(r[0]>0?e[0]===r[0]:r[1]>0?0===e[0]&&e[1]===r[1]:0===e[0]&&0===e[1]&&e[2]===r[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.0-beta.0");if(void 0!==n)return void this.#N(e.name,n);const i=new s(e.name,this.#t),r=this.#x(e.name,i),o={scope:i,cancelled:!1};this.#p.set(e.name,o);try{if(await this.#T(()=>e.init(r),t),o.cancelled)return;i.commit()}catch(t){return i.close(),void(o.cancelled||this.#t(`plugin "${e.name}" init failed:`,t))}finally{this.#p.get(e.name)===o&&this.#p.delete(e.name)}this.#g.set(e.name,{plugin:e,scope:i}),this.#t(`plugin "${e.name}" registered`)}#N(e,t){const n=`plugin "${e}" refused: ${t}`;this.#t(n),this.#a.emit("error",{error:new Error(n),context:"plugin",code:"LP0103"})}#x(e,t){return{events:new r(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.#w.get(e);return void 0===t?this.#w.set(e,[i]):t.push(i),()=>{i.active=!1;const t=this.#w.get(e);if(void 0===t)return;const n=t.indexOf(i);n>=0&&t.splice(n,1),0===t.length&&this.#w.delete(e)}})},registerCleanup:e=>{t.own(e)},getConfig:()=>this.#d,log:(...t)=>{this.#t(`[${e}]`,...t)}}}#L(e,t){const n=this.#p.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.#A(i):i;const s=this.#g.get(e);if(void 0===s)return Promise.resolve();this.#g.delete(e),s.scope.close();const r=Promise.resolve().then(()=>this.#C(e,s.plugin,t));return this.#m.set(e,r),r.then(()=>{this.#m.get(e)===r&&this.#m.delete(e)}),r}async#C(e,t,n){if(void 0!==t.destroy){this.#v.add(e);try{await this.#T(()=>t.destroy?.(),n)}catch(t){this.#t(`plugin "${e}" destroy failed:`,t)}finally{this.#v.delete(e)}}}async#k(e){for(const e of this.#p.values())e.cancelled=!0,e.scope.close();const t=[...this.#g.keys()];for(const n of t)await this.#L(n,e)}async#T(e,t){t?await this.#A(Promise.resolve().then(e)):await e()}async#A(e){this.#b+=1;try{await e}finally{this.#b-=1}}#S(e){const t=this.#y.then(e);return this.#y=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 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 s=e.createElement("style");return s.id=a,s.textContent=t,e.head.appendChild(s),{pluginOwned:!0,connected:()=>s.isConnected,remove:()=>{s.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 i=n;i.owners+=1;let s=!0;return()=>{s&&(s=!1,i.owners-=1,i.owners>0||(c.get(e)===i&&c.delete(e),i.pluginOwned&&i.remove()))}}(document,t),i=t?1e3:600,s=/* @__PURE__ */new WeakMap,r=/* @__PURE__ */new Set;e.registerCleanup?.(()=>{for(const e of[...r])e();n()}),e.events.on("elementUpdate",e=>{const t=e.element;s.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 i=!0;return()=>{i&&(i=!1,n.owners-=1,n.owners>0||(l.delete(e),n.pluginAdded&&e.classList.remove("lp-highlight")))}}(t);let o=!1;const a=()=>{o||(o=!0,window.clearTimeout(c),s.get(t)===a&&s.delete(t),r.delete(a),n())},c=window.setTimeout(a,i);r.add(a),s.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 g(){"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 p(e={}){const t=e.strategy??"silent";return{name:"document-save",version:"1.1.0",init:n=>{let i=!0;const s=/* @__PURE__ */new Set;n.registerCleanup?.(()=>{i=!1;for(const e of s)e.abort();s.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 g();const r=new AbortController;s.add(r);const o="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,r.signal):async function(e,t,n,i){if("undefined"==typeof fetch)return void t("document-save: revalidate strategy needs fetch — not available");const s=e.revalidateUrl??"/api/revalidate";let r=!1;try{const o=await fetch(s,{method:"POST",signal:n,headers:{"Content-Type":"application/json",...e.revalidateHeaders??{}},body:JSON.stringify({source:"payload-live-preview"})});if(!i()||n.aborted)return;r=o.ok,r||t("document-save revalidate non-2xx:",o.status)}catch(e){if(!i()||n.aborted)return;t("document-save revalidate failed:",e)}r||"reload"!==e.onRevalidateFailure||g()}(e,n.log,r.signal,()=>i);o.finally(()=>{s.delete(r)})})}}}var EventEmitter=class{#O=/* @__PURE__ */new Map;#z=/* @__PURE__ */new Map;on(e,t){return this.#R(this.#O,e,t)}once(e,t){return this.#R(this.#z,e,t)}off(e,t){this.#$(this.#O,e,t),this.#$(this.#z,e,t)}async emit(e,t){await this.#M(e,t)}async emitWhile(e,t,n){return this.#M(e,t,n)}async#M(e,t,n){const i=()=>n?.()??!0;if(!i())return!1;const s=this.#O.get(e);if(s)for(const n of[...s]){if(!i())return!1;if(await this.#q(n,t,e),!i())return!1}if(!i())return!1;const r=this.#z.get(e);if(r&&r.size>0){const n=[...r];this.#z.delete(e);for(const s of n){if(!i())return!1;if(await this.#q(s,t,e),!i())return!1}}return i()}listenerCount(e){return(this.#O.get(e)?.size??0)+(this.#z.get(e)?.size??0)}removeAllListeners(e){if(void 0===e)return this.#O.clear(),void this.#z.clear();this.#O.delete(e),this.#z.delete(e)}eventNames(){const e=/* @__PURE__ */new Set;for(const t of this.#O.keys())e.add(t);for(const t of this.#z.keys())e.add(t);return[...e]}#R(e,t,n){let i=e.get(t);return i||(i=/* @__PURE__ */new Set,e.set(t,i)),i.add(n),()=>{this.#$(e,t,n)}}#$(e,t,n){const i=e.get(t);void 0!==i&&(i.delete(n),0===i.size&&e.delete(t))}async#q(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)}}},m=Object.freeze({NoTrustedOrigin:"LP0101",ReferrerOnlyTrust:"LP0102",PluginIncompatible:"LP0103",OrphanField:"LP0201",UnattributableUpdate:"LP0202",VisibilityGateDeferred:"LP0301",UnsafeAttributeWrite:"LP0401",TextTargetHasChildren:"LP0402",MissingArrayTemplate:"LP0403",StructuralItemUnkeyed:"LP0404",StructuralDuplicateKey:"LP0405",StructuralUnstableKeys:"LP0406",UnsupportedStrategy:"LP0407",MessageRejected:"LP0501",TokenRejected:"LP0502",HandlerThrew:"LP0601",TransformThrew:"LP0602",RendererThrew:"LP0603",StartupFailed:"LP0605",ReadyFailed:"LP0606",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",V2ReadinessGap:"LP0709",RuntimeOnPublicPage:"LP0710"});export{m as DIAGNOSTIC_CODES,EventEmitter,o as PluginManager,h as createAnalyticsPlugin,d as debugPlugin,p as documentSavePlugin,u as highlightPlugin};
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.#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,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.0");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)}}}#x(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#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#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 x(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 L(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=>x(n,e,e))),a.hidden=0===t.length,l.replaceChildren(...t.map(({field:e,matched:t})=>x(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.#E(this.#T,e,t)}once(e,t){return this.#E(this.#O,e,t)}off(e,t){this.#U(this.#T,e,t),this.#U(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]}#E(e,t,n){let i=e.get(t);return i||(i=/* @__PURE__ */new Set,e.set(t,i)),i.add(n),()=>{this.#U(e,t,n)}}#U(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",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",V2ReadinessGap:"LP0709",RuntimeOnPublicPage:"LP0710"});export{k as DIAGNOSTIC_CODES,EventEmitter,s as PluginManager,h as createAnalyticsPlugin,L as createUnboundFieldsOverlayPlugin,d as debugPlugin,g as documentSavePlugin,u as highlightPlugin,P as unboundFieldNames};
2
2
  //# sourceMappingURL=plugins.js.map