@preprio/toolkit 0.5.0-rc.2 → 0.6.0-alpha.1

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 (78) hide show
  1. package/README.md +415 -27
  2. package/dist/astro/chunk-O7N6GPAH.js +173 -0
  3. package/dist/astro/graphql.cjs +1030 -0
  4. package/dist/astro/graphql.d.cts +305 -0
  5. package/dist/astro/graphql.d.ts +305 -0
  6. package/dist/astro/graphql.js +936 -0
  7. package/dist/astro/index-XT_z-RYT.d.cts +130 -0
  8. package/dist/astro/index-XT_z-RYT.d.ts +130 -0
  9. package/dist/astro/index.cjs +14 -1
  10. package/dist/astro/index.d.cts +1 -120
  11. package/dist/astro/index.d.ts +1 -120
  12. package/dist/astro/index.js +15 -153
  13. package/dist/chunk-3JLWZQ37.js +179 -0
  14. package/dist/chunk-3NCEVJJ3.js +10 -0
  15. package/dist/chunk-S5RWVMDJ.js +148 -0
  16. package/dist/chunk-TBKSBXGH.js +452 -0
  17. package/dist/{chunk-FLPNN3CV.js → chunk-VI6QZTBM.js} +73 -276
  18. package/dist/chunk-YWIKKWBR.js +26 -0
  19. package/dist/graphql/codegen.cjs +510 -0
  20. package/dist/graphql/codegen.d.cts +23 -0
  21. package/dist/graphql/codegen.d.ts +23 -0
  22. package/dist/graphql/codegen.js +99 -0
  23. package/dist/graphql.cjs +941 -0
  24. package/dist/graphql.d.cts +305 -0
  25. package/dist/graphql.d.ts +305 -0
  26. package/dist/graphql.js +419 -0
  27. package/dist/index.cjs +76 -119
  28. package/dist/index.d.cts +12 -64
  29. package/dist/index.d.ts +12 -64
  30. package/dist/index.js +27 -167
  31. package/dist/nextjs/chunk-BQ6IGSH6.js +231 -0
  32. package/dist/nextjs/components.cjs +190 -122
  33. package/dist/nextjs/components.d.cts +33 -2
  34. package/dist/nextjs/components.d.ts +33 -2
  35. package/dist/nextjs/components.js +133 -4
  36. package/dist/nextjs/graphql.cjs +1362 -0
  37. package/dist/nextjs/graphql.d.cts +435 -0
  38. package/dist/nextjs/graphql.d.ts +435 -0
  39. package/dist/nextjs/graphql.js +1261 -0
  40. package/dist/nextjs/index.cjs +126 -6
  41. package/dist/nextjs/index.d.cts +53 -147
  42. package/dist/nextjs/index.d.ts +53 -147
  43. package/dist/nextjs/index.js +113 -203
  44. package/dist/nextjs/server-CjpELYvq.d.cts +156 -0
  45. package/dist/nextjs/server-CjpELYvq.d.ts +156 -0
  46. package/dist/nuxt/chunk-IQDSBPDN.js +417 -0
  47. package/dist/nuxt/graphql.cjs +1037 -0
  48. package/dist/nuxt/graphql.d.cts +302 -0
  49. package/dist/nuxt/graphql.d.ts +302 -0
  50. package/dist/nuxt/graphql.js +937 -0
  51. package/dist/nuxt/index.cjs +14 -1
  52. package/dist/nuxt/index.d.cts +3 -148
  53. package/dist/nuxt/index.d.ts +3 -148
  54. package/dist/nuxt/index.js +15 -391
  55. package/dist/nuxt/server-8v6OHbsw.d.cts +158 -0
  56. package/dist/nuxt/server-8v6OHbsw.d.ts +158 -0
  57. package/dist/pixel-DwW7cXJm.d.cts +49 -0
  58. package/dist/pixel-DwW7cXJm.d.ts +49 -0
  59. package/dist/react/components.cjs +88 -120
  60. package/dist/react/components.d.cts +2 -8
  61. package/dist/react/components.d.ts +2 -8
  62. package/dist/react/components.js +88 -120
  63. package/dist/server-Brr1UgtW.d.ts +59 -0
  64. package/dist/server-DJuS3YU0.d.cts +59 -0
  65. package/dist/sveltekit/chunk-OKYZ6HPH.js +413 -0
  66. package/dist/sveltekit/graphql.cjs +1043 -0
  67. package/dist/sveltekit/graphql.d.cts +307 -0
  68. package/dist/sveltekit/graphql.d.ts +307 -0
  69. package/dist/sveltekit/graphql.js +943 -0
  70. package/dist/sveltekit/index.cjs +14 -1
  71. package/dist/sveltekit/index.d.cts +3 -88
  72. package/dist/sveltekit/index.d.ts +3 -88
  73. package/dist/sveltekit/index.js +15 -387
  74. package/dist/sveltekit/server-CO847mEV.d.cts +98 -0
  75. package/dist/sveltekit/server-CO847mEV.d.ts +98 -0
  76. package/dist/{pixel-B3oQNbZ3.d.cts → types-BYH9XqmN.d.cts} +4 -58
  77. package/dist/{pixel-B3oQNbZ3.d.ts → types-BYH9XqmN.d.ts} +4 -58
  78. package/package.json +36 -1
@@ -291,13 +291,9 @@ function createElementCache(query, ttl = 1e3) {
291
291
  }
292
292
 
293
293
  // src/core/iframe-bridge.ts
294
- var debug = createScopedLogger("iframe-bridge");
295
294
  var EDITOR_BASE_DOMAIN = "prepr.io";
296
295
  function isAllowedEditorOrigin(origin, allowed) {
297
- if (allowed) {
298
- if (allowed.includes("*")) return origin !== "null";
299
- return allowed.includes(origin);
300
- }
296
+ if (allowed) return allowed.includes(origin);
301
297
  let url;
302
298
  try {
303
299
  url = new URL(origin);
@@ -312,7 +308,6 @@ function isAllowedEditorOrigin(origin, allowed) {
312
308
  }
313
309
  function createIframeBridge(store, options = {}) {
314
310
  const allowedOrigins = options.allowedEditorOrigins;
315
- const onScrollToField = options.onScrollToField;
316
311
  let parentOrigin = null;
317
312
  const onKeyDown = (event) => {
318
313
  const key = event.key.toLowerCase();
@@ -322,10 +317,7 @@ function createIframeBridge(store, options = {}) {
322
317
  const onMessage = (evt) => {
323
318
  const data = evt?.data;
324
319
  if (data?.event === "prepr:initVE" && !parentOrigin) {
325
- if (!isAllowedEditorOrigin(evt.origin, allowedOrigins)) {
326
- debug.warn("ignored editor handshake from origin", evt.origin);
327
- return;
328
- }
320
+ if (!isAllowedEditorOrigin(evt.origin, allowedOrigins)) return;
329
321
  parentOrigin = evt.origin;
330
322
  setTrustedParentOrigin(parentOrigin);
331
323
  if (data.scrollPosition != null) {
@@ -339,15 +331,6 @@ function createIframeBridge(store, options = {}) {
339
331
  const currentScrollY = window.scrollY || document.documentElement.scrollTop;
340
332
  sendPreprEvent("getScrollPosition", { value: currentScrollY });
341
333
  }
342
- if (data?.event === "prepr:scrollToField") {
343
- if (typeof data.field !== "string" || !data.field) return;
344
- if (data.id !== void 0 && typeof data.id !== "string") return;
345
- try {
346
- onScrollToField?.({ field: data.field, id: data.id });
347
- } catch (error) {
348
- debug.warn("scrollToField handler failed", error);
349
- }
350
- }
351
334
  };
352
335
  return {
353
336
  start() {
@@ -372,7 +355,7 @@ var import_stega2 = require("@vercel/stega");
372
355
 
373
356
  // src/core/stega/clean.ts
374
357
  var import_stega = require("@vercel/stega");
375
- var debug2 = createScopedLogger("stega:clean");
358
+ var debug = createScopedLogger("stega:clean");
376
359
  function decodeStega(str) {
377
360
  if (!str) return null;
378
361
  try {
@@ -381,7 +364,7 @@ function decodeStega(str) {
381
364
  return decoded;
382
365
  }
383
366
  } catch (error) {
384
- debug2.log("error decoding stega data", error);
367
+ debug.log("error decoding stega data", error);
385
368
  const match = str.match(/{"origin.*?}/);
386
369
  if (match) {
387
370
  try {
@@ -390,7 +373,7 @@ function decodeStega(str) {
390
373
  return decodedMatch;
391
374
  }
392
375
  } catch (innerError) {
393
- debug2.log("error decoding stega regex match", innerError);
376
+ debug.log("error decoding stega regex match", innerError);
394
377
  }
395
378
  }
396
379
  }
@@ -426,37 +409,15 @@ function isRenderedElement(element) {
426
409
  if (!style) return true;
427
410
  return style.visibility !== "hidden" && style.display !== "none";
428
411
  }
429
- function parseEditHref(href) {
430
- try {
431
- const url = new URL(href, window.location.origin);
432
- return {
433
- id: url.pathname.split("/").pop() || void 0,
434
- field: url.searchParams.get("field") || void 0,
435
- locale: url.searchParams.get("locale") || void 0
436
- };
437
- } catch {
438
- return {};
439
- }
440
- }
441
- function setOrRemove(element, name, value) {
442
- if (value) {
443
- element.setAttribute(name, value);
444
- } else {
445
- element.removeAttribute(name);
446
- }
447
- }
448
412
  function tagEncodedElement(element, decoded) {
449
413
  element.setAttribute("data-prepr-encoded", "");
450
414
  element.setAttribute("data-prepr-href", decoded.href);
451
415
  element.setAttribute("data-prepr-origin", decoded.origin);
452
- const { id, field, locale } = parseEditHref(decoded.href);
453
- setOrRemove(element, "data-prepr-id", id);
454
- setOrRemove(element, "data-prepr-field", field);
455
- setOrRemove(element, "data-prepr-locale", locale);
456
416
  }
457
417
 
458
418
  // src/core/stega/auto-clean.ts
459
- var debug3 = createScopedLogger("stega:auto-clean");
419
+ var debug2 = createScopedLogger("stega:auto-clean");
420
+ var HYDRATION_RETRY_MS = 100;
460
421
  function createStegaAutoClean(options) {
461
422
  const stripText = options?.enabled ?? true;
462
423
  let observer = null;
@@ -465,8 +426,29 @@ function createStegaAutoClean(options) {
465
426
  let pendingHidden = /* @__PURE__ */ new Set();
466
427
  let pendingDirty = /* @__PURE__ */ new Set();
467
428
  let debounceTimeout = null;
429
+ const isHydrated = options?.isHydrated;
430
+ let pendingHydration = /* @__PURE__ */ new Set();
431
+ let hydrationTimeout = null;
432
+ function retryPendingHydration() {
433
+ hydrationTimeout = null;
434
+ processing = true;
435
+ const batch = [...pendingHydration];
436
+ pendingHydration.clear();
437
+ batch.forEach((textNode) => {
438
+ if (textNode.isConnected) cleanTextNode(textNode);
439
+ });
440
+ processing = false;
441
+ }
468
442
  function cleanTextNode(textNode) {
469
443
  if (isIgnoredTextNode(textNode)) return false;
444
+ if (isHydrated && !isHydrated(textNode)) {
445
+ pendingHydration.add(textNode);
446
+ hydrationTimeout ?? (hydrationTimeout = setTimeout(
447
+ retryPendingHydration,
448
+ HYDRATION_RETRY_MS
449
+ ));
450
+ return false;
451
+ }
470
452
  const textContent = textNode.textContent;
471
453
  const info = cleaned.get(textNode);
472
454
  const settled = stripText ? info?.cleaned : info?.original;
@@ -499,7 +481,7 @@ function createStegaAutoClean(options) {
499
481
  }
500
482
  pendingHidden.add(textNode);
501
483
  } catch (error) {
502
- debug3.log("error cleaning text node", error);
484
+ debug2.log("error cleaning text node", error);
503
485
  }
504
486
  return false;
505
487
  }
@@ -585,13 +567,17 @@ function createStegaAutoClean(options) {
585
567
  if (observer || typeof window === "undefined") return;
586
568
  scanAndClean();
587
569
  setupObserver();
588
- debug3.log("stega auto-clean started");
570
+ debug2.log("stega auto-clean started");
589
571
  }
590
572
  function stop() {
591
573
  if (debounceTimeout) {
592
574
  clearTimeout(debounceTimeout);
593
575
  debounceTimeout = null;
594
576
  }
577
+ if (hydrationTimeout) {
578
+ clearTimeout(hydrationTimeout);
579
+ hydrationTimeout = null;
580
+ }
595
581
  if (observer) {
596
582
  observer.disconnect();
597
583
  observer = null;
@@ -599,13 +585,14 @@ function createStegaAutoClean(options) {
599
585
  cleaned = /* @__PURE__ */ new WeakMap();
600
586
  pendingHidden = /* @__PURE__ */ new Set();
601
587
  pendingDirty = /* @__PURE__ */ new Set();
602
- debug3.log("stega auto-clean stopped");
588
+ pendingHydration = /* @__PURE__ */ new Set();
589
+ debug2.log("stega auto-clean stopped");
603
590
  }
604
591
  return { start, stop };
605
592
  }
606
593
 
607
594
  // src/core/stega/elements.ts
608
- var debug4 = createScopedLogger("stega:elements");
595
+ var debug3 = createScopedLogger("stega:elements");
609
596
  var StegaElements = class {
610
597
  constructor(decode = decodeStega) {
611
598
  this.observer = null;
@@ -650,7 +637,7 @@ var StegaElements = class {
650
637
  walkTextNodes(document.body, (textNode) => {
651
638
  if (this.tagFromTextNode(textNode)) encodedCount++;
652
639
  });
653
- debug4.log("document scan complete, encoded", encodedCount, "elements");
640
+ debug3.log("document scan complete, encoded", encodedCount, "elements");
654
641
  this.elements = document.querySelectorAll("[data-prepr-encoded]");
655
642
  }
656
643
  /** `onUpdate` fires after each debounced batch, for refreshing derived state. */
@@ -706,9 +693,6 @@ var StegaElements = class {
706
693
  element.removeAttribute("data-prepr-encoded");
707
694
  element.removeAttribute("data-prepr-href");
708
695
  element.removeAttribute("data-prepr-origin");
709
- element.removeAttribute("data-prepr-id");
710
- element.removeAttribute("data-prepr-field");
711
- element.removeAttribute("data-prepr-locale");
712
696
  element.classList.remove("prepr-overlay-active");
713
697
  });
714
698
  this.elements = void 0;
@@ -716,7 +700,7 @@ var StegaElements = class {
716
700
  };
717
701
 
718
702
  // src/core/stega/overlay.ts
719
- var debug5 = createScopedLogger("stega:overlay");
703
+ var debug4 = createScopedLogger("stega:overlay");
720
704
  var StegaOverlay = class {
721
705
  constructor(onEdit) {
722
706
  this.overlay = null;
@@ -761,8 +745,7 @@ var StegaOverlay = class {
761
745
  const origin = element.getAttribute("data-prepr-origin");
762
746
  const id = element.getAttribute("data-prepr-id") ?? void 0;
763
747
  const field = element.getAttribute("data-prepr-field") ?? void 0;
764
- const locale = element.getAttribute("data-prepr-locale") ?? void 0;
765
- debug5.log("showing overlay", { href, origin });
748
+ debug4.log("showing overlay", { href, origin });
766
749
  const overlay = this.overlay;
767
750
  overlay.style.display = "block";
768
751
  overlay.style.top = `${rect.top + window.scrollY - 2}px`;
@@ -794,7 +777,7 @@ var StegaOverlay = class {
794
777
  tooltip.style.left = `${left}px`;
795
778
  });
796
779
  tooltip.onclick = () => {
797
- this.onEdit({ href, origin, id, field, locale });
780
+ this.onEdit({ href, origin, id, field });
798
781
  };
799
782
  }
800
783
  this.currentElement = element;
@@ -834,7 +817,7 @@ var StegaOverlay = class {
834
817
  };
835
818
 
836
819
  // src/core/stega/proximity.ts
837
- var debug6 = createScopedLogger("stega:proximity");
820
+ var debug5 = createScopedLogger("stega:proximity");
838
821
  var StegaProximity = class {
839
822
  constructor() {
840
823
  this.highlighted = /* @__PURE__ */ new Set();
@@ -869,9 +852,9 @@ var StegaProximity = class {
869
852
  );
870
853
  const nodes = this.getEncodedElements();
871
854
  nodes.forEach((el) => this.observer.observe(el));
872
- debug6.log("observing", nodes.length, "encoded elements");
855
+ debug5.log("observing", nodes.length, "encoded elements");
873
856
  } catch (error) {
874
- debug6.log("error setting up IntersectionObserver", error);
857
+ debug5.log("error setting up IntersectionObserver", error);
875
858
  }
876
859
  }
877
860
  stopObserving() {
@@ -941,7 +924,7 @@ function removeStegaStyles() {
941
924
  }
942
925
 
943
926
  // src/core/stega/scan.ts
944
- var debug7 = createScopedLogger("stega:scan");
927
+ var debug6 = createScopedLogger("stega:scan");
945
928
  var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
946
929
  function createStegaController(opts) {
947
930
  const tooltipEnabled = opts.tooltip ?? true;
@@ -974,13 +957,12 @@ function createStegaController(opts) {
974
957
  href: encoded.getAttribute("data-prepr-href") ?? "",
975
958
  origin: encoded.getAttribute("data-prepr-origin") ?? "",
976
959
  id: encoded.getAttribute("data-prepr-id") ?? void 0,
977
- field: encoded.getAttribute("data-prepr-field") ?? void 0,
978
- locale: encoded.getAttribute("data-prepr-locale") ?? void 0
960
+ field: encoded.getAttribute("data-prepr-field") ?? void 0
979
961
  });
980
962
  };
981
963
  const start = () => {
982
964
  if (initialized) {
983
- debug7.log("already initialized, skipping setup");
965
+ debug6.log("already initialized, skipping setup");
984
966
  return;
985
967
  }
986
968
  if (!tooltipEnabled) {
@@ -990,7 +972,7 @@ function createStegaController(opts) {
990
972
  });
991
973
  document.addEventListener("click", handleClick, { capture: true });
992
974
  initialized = true;
993
- debug7.log("stega controller started (editor mode)");
975
+ debug6.log("stega controller started (editor mode)");
994
976
  return;
995
977
  }
996
978
  injectStegaStyles();
@@ -1021,7 +1003,7 @@ function createStegaController(opts) {
1021
1003
  passive: true
1022
1004
  });
1023
1005
  initialized = true;
1024
- debug7.log("stega controller started");
1006
+ debug6.log("stega controller started");
1025
1007
  };
1026
1008
  const stop = () => {
1027
1009
  if (!initialized) return;
@@ -1030,7 +1012,7 @@ function createStegaController(opts) {
1030
1012
  elements.cleanup();
1031
1013
  removeStegaStyles();
1032
1014
  initialized = false;
1033
- debug7.log("stega controller stopped (editor mode)");
1015
+ debug6.log("stega controller stopped (editor mode)");
1034
1016
  return;
1035
1017
  }
1036
1018
  if (throttledMouseMove) {
@@ -1050,43 +1032,11 @@ function createStegaController(opts) {
1050
1032
  elements.cleanup();
1051
1033
  removeStegaStyles();
1052
1034
  initialized = false;
1053
- debug7.log("stega controller stopped");
1035
+ debug6.log("stega controller stopped");
1054
1036
  };
1055
1037
  return { start, stop };
1056
1038
  }
1057
1039
 
1058
- // src/core/stega/scroll-to-field.ts
1059
- var debug8 = createScopedLogger("stega:scroll");
1060
- var FLASH_DURATION_MS = 1200;
1061
- var flashTimeout = null;
1062
- function scrollToField(request) {
1063
- const { field, id } = request;
1064
- if (!field) return false;
1065
- const candidates = document.querySelectorAll(
1066
- "[data-prepr-encoded]"
1067
- );
1068
- let target = null;
1069
- for (const candidate of candidates) {
1070
- if (candidate.getAttribute("data-prepr-field") !== field) continue;
1071
- if (id && candidate.getAttribute("data-prepr-id") !== id) continue;
1072
- target = candidate;
1073
- break;
1074
- }
1075
- if (!target) {
1076
- debug8.log("no element found for field", field);
1077
- return false;
1078
- }
1079
- target.scrollIntoView({ behavior: "smooth", block: "center" });
1080
- if (flashTimeout) clearTimeout(flashTimeout);
1081
- document.querySelectorAll(".prepr-overlay-active").forEach((el) => el.classList.remove("prepr-overlay-active"));
1082
- target.classList.add("prepr-overlay-active");
1083
- flashTimeout = setTimeout(() => {
1084
- target.classList.remove("prepr-overlay-active");
1085
- flashTimeout = null;
1086
- }, FLASH_DURATION_MS);
1087
- return true;
1088
- }
1089
-
1090
1040
  // src/core/store.ts
1091
1041
  var DEFAULT_STATE = {
1092
1042
  locale: "en",
@@ -2199,7 +2149,7 @@ function definePreprToolbar() {
2199
2149
  }
2200
2150
 
2201
2151
  // src/core/create-preview.ts
2202
- var debug9 = createScopedLogger("create-preview");
2152
+ var debug7 = createScopedLogger("create-preview");
2203
2153
  var controllerStores = /* @__PURE__ */ new WeakMap();
2204
2154
  function defaultNavigation() {
2205
2155
  return {
@@ -2241,7 +2191,7 @@ function createPreprPreview(opts = {}) {
2241
2191
  const search = new URLSearchParams(window.location.search);
2242
2192
  const hideBar = search.get(PARAM_HIDE_BAR) === "true";
2243
2193
  if (hideBar) {
2244
- debug9.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
2194
+ debug7.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
2245
2195
  }
2246
2196
  const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
2247
2197
  const locale = resolveLocale(options);
@@ -2277,17 +2227,18 @@ function createPreprPreview(opts = {}) {
2277
2227
  tooltip: mountUi,
2278
2228
  // In the editor, ask the parent to focus the field instead of opening a new
2279
2229
  // tab. Standalone previews keep the window.open behaviour.
2280
- onEdit: ({ href, id, field, locale: contentLocale }) => {
2230
+ onEdit: ({ href, origin, id, field }) => {
2281
2231
  const safeHref = href ? safeEditUrl(href) : null;
2282
2232
  if (href && !safeHref) {
2283
- debug9.warn("ignored edit request with unsupported href scheme");
2233
+ debug7.warn("ignored edit request with unsupported href scheme");
2284
2234
  return;
2285
2235
  }
2286
2236
  if (isIframe) {
2287
2237
  sendPreprEvent("field_edit_requested", {
2238
+ href: safeHref ?? void 0,
2239
+ origin,
2288
2240
  id,
2289
- field,
2290
- locale: contentLocale
2241
+ field
2291
2242
  });
2292
2243
  } else if (safeHref) {
2293
2244
  window.open(safeHref, "_blank", "noopener,noreferrer");
@@ -2295,7 +2246,8 @@ function createPreprPreview(opts = {}) {
2295
2246
  }
2296
2247
  });
2297
2248
  const autoClean = createStegaAutoClean({
2298
- enabled: options?.autoClean
2249
+ enabled: options?.autoClean,
2250
+ isHydrated: opts.isHydrated
2299
2251
  });
2300
2252
  autoClean.start();
2301
2253
  const handleChange = createChangeHandler({
@@ -2314,15 +2266,7 @@ function createPreprPreview(opts = {}) {
2314
2266
  handleChange(before, state);
2315
2267
  });
2316
2268
  const bridge = createIframeBridge(store, {
2317
- allowedEditorOrigins: options?.allowedEditorOrigins,
2318
- // The editor selecting a field scrolls the matching element into view. The
2319
- // lookup relies on the attributes the stega scan writes, so it finds
2320
- // nothing until encoded content has been tagged.
2321
- onScrollToField: ({ field, id }) => {
2322
- if (!scrollToField({ field, id })) {
2323
- debug9.log("no element on this page renders field", field);
2324
- }
2325
- }
2269
+ allowedEditorOrigins: options?.allowedEditorOrigins
2326
2270
  });
2327
2271
  sendPreprEvent(
2328
2272
  "getScrollPosition",
@@ -2342,15 +2286,34 @@ function createPreprPreview(opts = {}) {
2342
2286
  bridge.stop();
2343
2287
  }
2344
2288
  el?.remove();
2345
- debug9.log("preview destroyed");
2289
+ debug7.log("preview destroyed");
2346
2290
  }
2347
2291
  const controller = { destroy };
2348
2292
  controllerStores.set(controller, store);
2349
2293
  return controller;
2350
2294
  }
2351
2295
 
2296
+ // src/react/hydration.ts
2297
+ var PROPS_KEY_PREFIX = "__reactProps$";
2298
+ function reactProps(element) {
2299
+ for (const key of Object.keys(element)) {
2300
+ if (key.startsWith(PROPS_KEY_PREFIX)) {
2301
+ return element[key];
2302
+ }
2303
+ }
2304
+ return void 0;
2305
+ }
2306
+ function isReactHydrated(text) {
2307
+ for (let el = text.parentElement; el; el = el.parentElement) {
2308
+ const props = reactProps(el);
2309
+ if (!props) continue;
2310
+ return el === text.parentElement || props.dangerouslySetInnerHTML != null;
2311
+ }
2312
+ return true;
2313
+ }
2314
+
2352
2315
  // src/version.ts
2353
- var VERSION = "0.5.0-rc.2";
2316
+ var VERSION = "0.6.0-alpha.1";
2354
2317
 
2355
2318
  // src/core/pixel.ts
2356
2319
  var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
@@ -2398,7 +2361,12 @@ function PreprPreview({
2398
2361
  ...props
2399
2362
  }) {
2400
2363
  (0, import_react.useEffect)(() => {
2401
- const preview = createPreprPreview({ props, options, navigation });
2364
+ const preview = createPreprPreview({
2365
+ props,
2366
+ options,
2367
+ navigation,
2368
+ isHydrated: isReactHydrated
2369
+ });
2402
2370
  return () => preview.destroy();
2403
2371
  }, []);
2404
2372
  return null;
@@ -58,14 +58,8 @@ interface PreprPreviewOptions extends PreprToolbarOptions {
58
58
  */
59
59
  ui?: boolean;
60
60
  /**
61
- * Replace the `*.prepr.io` editor-origin wildcard with an exact list, e.g.
62
- * `['http://acme.localhost:8000']`. Intended for self-hosted or locally run
63
- * editors; when set, the wildcard no longer applies. Entries are compared to
64
- * the editor's origin exactly: scheme, host and port.
65
- *
66
- * `['*']` accepts any editor origin. Use it for development only: any page
67
- * that frames the preview can then switch on preview and edit mode and
68
- * receives the field-edit events, which carry content item ids.
61
+ * Replace the `*.prepr.io` editor-origin wildcard with an exact list.
62
+ * Intended for self-hosted editors; when set, the wildcard no longer applies.
69
63
  */
70
64
  allowedEditorOrigins?: string[];
71
65
  /**
@@ -58,14 +58,8 @@ interface PreprPreviewOptions extends PreprToolbarOptions {
58
58
  */
59
59
  ui?: boolean;
60
60
  /**
61
- * Replace the `*.prepr.io` editor-origin wildcard with an exact list, e.g.
62
- * `['http://acme.localhost:8000']`. Intended for self-hosted or locally run
63
- * editors; when set, the wildcard no longer applies. Entries are compared to
64
- * the editor's origin exactly: scheme, host and port.
65
- *
66
- * `['*']` accepts any editor origin. Use it for development only: any page
67
- * that frames the preview can then switch on preview and edit mode and
68
- * receives the field-edit events, which carry content item ids.
61
+ * Replace the `*.prepr.io` editor-origin wildcard with an exact list.
62
+ * Intended for self-hosted editors; when set, the wildcard no longer applies.
69
63
  */
70
64
  allowedEditorOrigins?: string[];
71
65
  /**