@preprio/toolkit 0.5.0-rc.1 → 0.6.0-alpha.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.
- package/README.md +300 -19
- package/dist/astro/chunk-3UVUDDNY.js +173 -0
- package/dist/astro/graphql.cjs +983 -0
- package/dist/astro/graphql.d.cts +231 -0
- package/dist/astro/graphql.d.ts +231 -0
- package/dist/astro/graphql.js +893 -0
- package/dist/astro/index-XT_z-RYT.d.cts +130 -0
- package/dist/astro/index-XT_z-RYT.d.ts +130 -0
- package/dist/astro/index.cjs +14 -1
- package/dist/astro/index.d.cts +1 -120
- package/dist/astro/index.d.ts +1 -120
- package/dist/astro/index.js +15 -153
- package/dist/{chunk-4JNKYIEV.js → chunk-BJ2LBLWO.js} +69 -268
- package/dist/chunk-DGZA7KX7.js +172 -0
- package/dist/chunk-YR7P4IWE.js +187 -0
- package/dist/graphql.cjs +894 -0
- package/dist/graphql.d.cts +231 -0
- package/dist/graphql.d.ts +231 -0
- package/dist/graphql.js +787 -0
- package/dist/index.cjs +74 -111
- package/dist/index.d.cts +11 -62
- package/dist/index.d.ts +11 -62
- package/dist/index.js +23 -167
- package/dist/nextjs/chunk-U4HXENF7.js +231 -0
- package/dist/nextjs/components.cjs +188 -114
- package/dist/nextjs/components.d.cts +33 -2
- package/dist/nextjs/components.d.ts +33 -2
- package/dist/nextjs/components.js +132 -4
- package/dist/nextjs/graphql.cjs +1315 -0
- package/dist/nextjs/graphql.d.cts +361 -0
- package/dist/nextjs/graphql.d.ts +361 -0
- package/dist/nextjs/graphql.js +1218 -0
- package/dist/nextjs/index.cjs +126 -6
- package/dist/nextjs/index.d.cts +53 -141
- package/dist/nextjs/index.d.ts +53 -141
- package/dist/nextjs/index.js +113 -203
- package/dist/nextjs/server-CjpELYvq.d.cts +156 -0
- package/dist/nextjs/server-CjpELYvq.d.ts +156 -0
- package/dist/nuxt/chunk-P6ENNAEE.js +417 -0
- package/dist/nuxt/graphql.cjs +990 -0
- package/dist/nuxt/graphql.d.cts +228 -0
- package/dist/nuxt/graphql.d.ts +228 -0
- package/dist/nuxt/graphql.js +894 -0
- package/dist/nuxt/index.cjs +14 -1
- package/dist/nuxt/index.d.cts +3 -148
- package/dist/nuxt/index.d.ts +3 -148
- package/dist/nuxt/index.js +15 -391
- package/dist/nuxt/server-8v6OHbsw.d.cts +158 -0
- package/dist/nuxt/server-8v6OHbsw.d.ts +158 -0
- package/dist/pixel-DwW7cXJm.d.cts +49 -0
- package/dist/pixel-DwW7cXJm.d.ts +49 -0
- package/dist/react/components.cjs +86 -112
- package/dist/react/components.js +86 -112
- package/dist/server-Brr1UgtW.d.ts +59 -0
- package/dist/server-DJuS3YU0.d.cts +59 -0
- package/dist/sveltekit/chunk-FSARVMG5.js +413 -0
- package/dist/sveltekit/graphql.cjs +996 -0
- package/dist/sveltekit/graphql.d.cts +233 -0
- package/dist/sveltekit/graphql.d.ts +233 -0
- package/dist/sveltekit/graphql.js +900 -0
- package/dist/sveltekit/index.cjs +14 -1
- package/dist/sveltekit/index.d.cts +3 -88
- package/dist/sveltekit/index.d.ts +3 -88
- package/dist/sveltekit/index.js +15 -387
- package/dist/sveltekit/server-CO847mEV.d.cts +98 -0
- package/dist/sveltekit/server-CO847mEV.d.ts +98 -0
- package/dist/{pixel-e1fUWl2Y.d.cts → types-BYH9XqmN.d.cts} +2 -50
- package/dist/{pixel-e1fUWl2Y.d.ts → types-BYH9XqmN.d.ts} +2 -50
- package/package.json +31 -1
package/dist/react/components.js
CHANGED
|
@@ -267,7 +267,6 @@ function createElementCache(query, ttl = 1e3) {
|
|
|
267
267
|
}
|
|
268
268
|
|
|
269
269
|
// src/core/iframe-bridge.ts
|
|
270
|
-
var debug = createScopedLogger("iframe-bridge");
|
|
271
270
|
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
272
271
|
function isAllowedEditorOrigin(origin, allowed) {
|
|
273
272
|
if (allowed) return allowed.includes(origin);
|
|
@@ -285,7 +284,6 @@ function isAllowedEditorOrigin(origin, allowed) {
|
|
|
285
284
|
}
|
|
286
285
|
function createIframeBridge(store, options = {}) {
|
|
287
286
|
const allowedOrigins = options.allowedEditorOrigins;
|
|
288
|
-
const onScrollToField = options.onScrollToField;
|
|
289
287
|
let parentOrigin = null;
|
|
290
288
|
const onKeyDown = (event) => {
|
|
291
289
|
const key = event.key.toLowerCase();
|
|
@@ -309,15 +307,6 @@ function createIframeBridge(store, options = {}) {
|
|
|
309
307
|
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
310
308
|
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
311
309
|
}
|
|
312
|
-
if (data?.event === "prepr:scrollToField") {
|
|
313
|
-
if (typeof data.field !== "string" || !data.field) return;
|
|
314
|
-
if (data.id !== void 0 && typeof data.id !== "string") return;
|
|
315
|
-
try {
|
|
316
|
-
onScrollToField?.({ field: data.field, id: data.id });
|
|
317
|
-
} catch (error) {
|
|
318
|
-
debug.warn("scrollToField handler failed", error);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
310
|
};
|
|
322
311
|
return {
|
|
323
312
|
start() {
|
|
@@ -342,7 +331,7 @@ import { vercelStegaSplit } from "@vercel/stega";
|
|
|
342
331
|
|
|
343
332
|
// src/core/stega/clean.ts
|
|
344
333
|
import { vercelStegaClean, vercelStegaDecode } from "@vercel/stega";
|
|
345
|
-
var
|
|
334
|
+
var debug = createScopedLogger("stega:clean");
|
|
346
335
|
function decodeStega(str) {
|
|
347
336
|
if (!str) return null;
|
|
348
337
|
try {
|
|
@@ -351,7 +340,7 @@ function decodeStega(str) {
|
|
|
351
340
|
return decoded;
|
|
352
341
|
}
|
|
353
342
|
} catch (error) {
|
|
354
|
-
|
|
343
|
+
debug.log("error decoding stega data", error);
|
|
355
344
|
const match = str.match(/{"origin.*?}/);
|
|
356
345
|
if (match) {
|
|
357
346
|
try {
|
|
@@ -360,7 +349,7 @@ function decodeStega(str) {
|
|
|
360
349
|
return decodedMatch;
|
|
361
350
|
}
|
|
362
351
|
} catch (innerError) {
|
|
363
|
-
|
|
352
|
+
debug.log("error decoding stega regex match", innerError);
|
|
364
353
|
}
|
|
365
354
|
}
|
|
366
355
|
}
|
|
@@ -396,37 +385,15 @@ function isRenderedElement(element) {
|
|
|
396
385
|
if (!style) return true;
|
|
397
386
|
return style.visibility !== "hidden" && style.display !== "none";
|
|
398
387
|
}
|
|
399
|
-
function parseEditHref(href) {
|
|
400
|
-
try {
|
|
401
|
-
const url = new URL(href, window.location.origin);
|
|
402
|
-
return {
|
|
403
|
-
id: url.pathname.split("/").pop() || void 0,
|
|
404
|
-
field: url.searchParams.get("field") || void 0,
|
|
405
|
-
locale: url.searchParams.get("locale") || void 0
|
|
406
|
-
};
|
|
407
|
-
} catch {
|
|
408
|
-
return {};
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
function setOrRemove(element, name, value) {
|
|
412
|
-
if (value) {
|
|
413
|
-
element.setAttribute(name, value);
|
|
414
|
-
} else {
|
|
415
|
-
element.removeAttribute(name);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
388
|
function tagEncodedElement(element, decoded) {
|
|
419
389
|
element.setAttribute("data-prepr-encoded", "");
|
|
420
390
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
421
391
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
422
|
-
const { id, field, locale } = parseEditHref(decoded.href);
|
|
423
|
-
setOrRemove(element, "data-prepr-id", id);
|
|
424
|
-
setOrRemove(element, "data-prepr-field", field);
|
|
425
|
-
setOrRemove(element, "data-prepr-locale", locale);
|
|
426
392
|
}
|
|
427
393
|
|
|
428
394
|
// src/core/stega/auto-clean.ts
|
|
429
|
-
var
|
|
395
|
+
var debug2 = createScopedLogger("stega:auto-clean");
|
|
396
|
+
var HYDRATION_RETRY_MS = 100;
|
|
430
397
|
function createStegaAutoClean(options) {
|
|
431
398
|
const stripText = options?.enabled ?? true;
|
|
432
399
|
let observer = null;
|
|
@@ -435,8 +402,29 @@ function createStegaAutoClean(options) {
|
|
|
435
402
|
let pendingHidden = /* @__PURE__ */ new Set();
|
|
436
403
|
let pendingDirty = /* @__PURE__ */ new Set();
|
|
437
404
|
let debounceTimeout = null;
|
|
405
|
+
const isHydrated = options?.isHydrated;
|
|
406
|
+
let pendingHydration = /* @__PURE__ */ new Set();
|
|
407
|
+
let hydrationTimeout = null;
|
|
408
|
+
function retryPendingHydration() {
|
|
409
|
+
hydrationTimeout = null;
|
|
410
|
+
processing = true;
|
|
411
|
+
const batch = [...pendingHydration];
|
|
412
|
+
pendingHydration.clear();
|
|
413
|
+
batch.forEach((textNode) => {
|
|
414
|
+
if (textNode.isConnected) cleanTextNode(textNode);
|
|
415
|
+
});
|
|
416
|
+
processing = false;
|
|
417
|
+
}
|
|
438
418
|
function cleanTextNode(textNode) {
|
|
439
419
|
if (isIgnoredTextNode(textNode)) return false;
|
|
420
|
+
if (isHydrated && !isHydrated(textNode)) {
|
|
421
|
+
pendingHydration.add(textNode);
|
|
422
|
+
hydrationTimeout ?? (hydrationTimeout = setTimeout(
|
|
423
|
+
retryPendingHydration,
|
|
424
|
+
HYDRATION_RETRY_MS
|
|
425
|
+
));
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
440
428
|
const textContent = textNode.textContent;
|
|
441
429
|
const info = cleaned.get(textNode);
|
|
442
430
|
const settled = stripText ? info?.cleaned : info?.original;
|
|
@@ -469,7 +457,7 @@ function createStegaAutoClean(options) {
|
|
|
469
457
|
}
|
|
470
458
|
pendingHidden.add(textNode);
|
|
471
459
|
} catch (error) {
|
|
472
|
-
|
|
460
|
+
debug2.log("error cleaning text node", error);
|
|
473
461
|
}
|
|
474
462
|
return false;
|
|
475
463
|
}
|
|
@@ -555,13 +543,17 @@ function createStegaAutoClean(options) {
|
|
|
555
543
|
if (observer || typeof window === "undefined") return;
|
|
556
544
|
scanAndClean();
|
|
557
545
|
setupObserver();
|
|
558
|
-
|
|
546
|
+
debug2.log("stega auto-clean started");
|
|
559
547
|
}
|
|
560
548
|
function stop() {
|
|
561
549
|
if (debounceTimeout) {
|
|
562
550
|
clearTimeout(debounceTimeout);
|
|
563
551
|
debounceTimeout = null;
|
|
564
552
|
}
|
|
553
|
+
if (hydrationTimeout) {
|
|
554
|
+
clearTimeout(hydrationTimeout);
|
|
555
|
+
hydrationTimeout = null;
|
|
556
|
+
}
|
|
565
557
|
if (observer) {
|
|
566
558
|
observer.disconnect();
|
|
567
559
|
observer = null;
|
|
@@ -569,13 +561,14 @@ function createStegaAutoClean(options) {
|
|
|
569
561
|
cleaned = /* @__PURE__ */ new WeakMap();
|
|
570
562
|
pendingHidden = /* @__PURE__ */ new Set();
|
|
571
563
|
pendingDirty = /* @__PURE__ */ new Set();
|
|
572
|
-
|
|
564
|
+
pendingHydration = /* @__PURE__ */ new Set();
|
|
565
|
+
debug2.log("stega auto-clean stopped");
|
|
573
566
|
}
|
|
574
567
|
return { start, stop };
|
|
575
568
|
}
|
|
576
569
|
|
|
577
570
|
// src/core/stega/elements.ts
|
|
578
|
-
var
|
|
571
|
+
var debug3 = createScopedLogger("stega:elements");
|
|
579
572
|
var StegaElements = class {
|
|
580
573
|
constructor(decode = decodeStega) {
|
|
581
574
|
this.observer = null;
|
|
@@ -620,7 +613,7 @@ var StegaElements = class {
|
|
|
620
613
|
walkTextNodes(document.body, (textNode) => {
|
|
621
614
|
if (this.tagFromTextNode(textNode)) encodedCount++;
|
|
622
615
|
});
|
|
623
|
-
|
|
616
|
+
debug3.log("document scan complete, encoded", encodedCount, "elements");
|
|
624
617
|
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
625
618
|
}
|
|
626
619
|
/** `onUpdate` fires after each debounced batch, for refreshing derived state. */
|
|
@@ -676,9 +669,6 @@ var StegaElements = class {
|
|
|
676
669
|
element.removeAttribute("data-prepr-encoded");
|
|
677
670
|
element.removeAttribute("data-prepr-href");
|
|
678
671
|
element.removeAttribute("data-prepr-origin");
|
|
679
|
-
element.removeAttribute("data-prepr-id");
|
|
680
|
-
element.removeAttribute("data-prepr-field");
|
|
681
|
-
element.removeAttribute("data-prepr-locale");
|
|
682
672
|
element.classList.remove("prepr-overlay-active");
|
|
683
673
|
});
|
|
684
674
|
this.elements = void 0;
|
|
@@ -686,7 +676,7 @@ var StegaElements = class {
|
|
|
686
676
|
};
|
|
687
677
|
|
|
688
678
|
// src/core/stega/overlay.ts
|
|
689
|
-
var
|
|
679
|
+
var debug4 = createScopedLogger("stega:overlay");
|
|
690
680
|
var StegaOverlay = class {
|
|
691
681
|
constructor(onEdit) {
|
|
692
682
|
this.overlay = null;
|
|
@@ -731,8 +721,7 @@ var StegaOverlay = class {
|
|
|
731
721
|
const origin = element.getAttribute("data-prepr-origin");
|
|
732
722
|
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
733
723
|
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
734
|
-
|
|
735
|
-
debug5.log("showing overlay", { href, origin });
|
|
724
|
+
debug4.log("showing overlay", { href, origin });
|
|
736
725
|
const overlay = this.overlay;
|
|
737
726
|
overlay.style.display = "block";
|
|
738
727
|
overlay.style.top = `${rect.top + window.scrollY - 2}px`;
|
|
@@ -764,7 +753,7 @@ var StegaOverlay = class {
|
|
|
764
753
|
tooltip.style.left = `${left}px`;
|
|
765
754
|
});
|
|
766
755
|
tooltip.onclick = () => {
|
|
767
|
-
this.onEdit({ href, origin, id, field
|
|
756
|
+
this.onEdit({ href, origin, id, field });
|
|
768
757
|
};
|
|
769
758
|
}
|
|
770
759
|
this.currentElement = element;
|
|
@@ -804,7 +793,7 @@ var StegaOverlay = class {
|
|
|
804
793
|
};
|
|
805
794
|
|
|
806
795
|
// src/core/stega/proximity.ts
|
|
807
|
-
var
|
|
796
|
+
var debug5 = createScopedLogger("stega:proximity");
|
|
808
797
|
var StegaProximity = class {
|
|
809
798
|
constructor() {
|
|
810
799
|
this.highlighted = /* @__PURE__ */ new Set();
|
|
@@ -839,9 +828,9 @@ var StegaProximity = class {
|
|
|
839
828
|
);
|
|
840
829
|
const nodes = this.getEncodedElements();
|
|
841
830
|
nodes.forEach((el) => this.observer.observe(el));
|
|
842
|
-
|
|
831
|
+
debug5.log("observing", nodes.length, "encoded elements");
|
|
843
832
|
} catch (error) {
|
|
844
|
-
|
|
833
|
+
debug5.log("error setting up IntersectionObserver", error);
|
|
845
834
|
}
|
|
846
835
|
}
|
|
847
836
|
stopObserving() {
|
|
@@ -911,7 +900,7 @@ function removeStegaStyles() {
|
|
|
911
900
|
}
|
|
912
901
|
|
|
913
902
|
// src/core/stega/scan.ts
|
|
914
|
-
var
|
|
903
|
+
var debug6 = createScopedLogger("stega:scan");
|
|
915
904
|
var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
|
|
916
905
|
function createStegaController(opts) {
|
|
917
906
|
const tooltipEnabled = opts.tooltip ?? true;
|
|
@@ -944,13 +933,12 @@ function createStegaController(opts) {
|
|
|
944
933
|
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
945
934
|
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
946
935
|
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
947
|
-
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
948
|
-
locale: encoded.getAttribute("data-prepr-locale") ?? void 0
|
|
936
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
949
937
|
});
|
|
950
938
|
};
|
|
951
939
|
const start = () => {
|
|
952
940
|
if (initialized) {
|
|
953
|
-
|
|
941
|
+
debug6.log("already initialized, skipping setup");
|
|
954
942
|
return;
|
|
955
943
|
}
|
|
956
944
|
if (!tooltipEnabled) {
|
|
@@ -960,7 +948,7 @@ function createStegaController(opts) {
|
|
|
960
948
|
});
|
|
961
949
|
document.addEventListener("click", handleClick, { capture: true });
|
|
962
950
|
initialized = true;
|
|
963
|
-
|
|
951
|
+
debug6.log("stega controller started (editor mode)");
|
|
964
952
|
return;
|
|
965
953
|
}
|
|
966
954
|
injectStegaStyles();
|
|
@@ -991,7 +979,7 @@ function createStegaController(opts) {
|
|
|
991
979
|
passive: true
|
|
992
980
|
});
|
|
993
981
|
initialized = true;
|
|
994
|
-
|
|
982
|
+
debug6.log("stega controller started");
|
|
995
983
|
};
|
|
996
984
|
const stop = () => {
|
|
997
985
|
if (!initialized) return;
|
|
@@ -1000,7 +988,7 @@ function createStegaController(opts) {
|
|
|
1000
988
|
elements.cleanup();
|
|
1001
989
|
removeStegaStyles();
|
|
1002
990
|
initialized = false;
|
|
1003
|
-
|
|
991
|
+
debug6.log("stega controller stopped (editor mode)");
|
|
1004
992
|
return;
|
|
1005
993
|
}
|
|
1006
994
|
if (throttledMouseMove) {
|
|
@@ -1020,43 +1008,11 @@ function createStegaController(opts) {
|
|
|
1020
1008
|
elements.cleanup();
|
|
1021
1009
|
removeStegaStyles();
|
|
1022
1010
|
initialized = false;
|
|
1023
|
-
|
|
1011
|
+
debug6.log("stega controller stopped");
|
|
1024
1012
|
};
|
|
1025
1013
|
return { start, stop };
|
|
1026
1014
|
}
|
|
1027
1015
|
|
|
1028
|
-
// src/core/stega/scroll-to-field.ts
|
|
1029
|
-
var debug8 = createScopedLogger("stega:scroll");
|
|
1030
|
-
var FLASH_DURATION_MS = 1200;
|
|
1031
|
-
var flashTimeout = null;
|
|
1032
|
-
function scrollToField(request) {
|
|
1033
|
-
const { field, id } = request;
|
|
1034
|
-
if (!field) return false;
|
|
1035
|
-
const candidates = document.querySelectorAll(
|
|
1036
|
-
"[data-prepr-encoded]"
|
|
1037
|
-
);
|
|
1038
|
-
let target = null;
|
|
1039
|
-
for (const candidate of candidates) {
|
|
1040
|
-
if (candidate.getAttribute("data-prepr-field") !== field) continue;
|
|
1041
|
-
if (id && candidate.getAttribute("data-prepr-id") !== id) continue;
|
|
1042
|
-
target = candidate;
|
|
1043
|
-
break;
|
|
1044
|
-
}
|
|
1045
|
-
if (!target) {
|
|
1046
|
-
debug8.log("no element found for field", field);
|
|
1047
|
-
return false;
|
|
1048
|
-
}
|
|
1049
|
-
target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1050
|
-
if (flashTimeout) clearTimeout(flashTimeout);
|
|
1051
|
-
document.querySelectorAll(".prepr-overlay-active").forEach((el) => el.classList.remove("prepr-overlay-active"));
|
|
1052
|
-
target.classList.add("prepr-overlay-active");
|
|
1053
|
-
flashTimeout = setTimeout(() => {
|
|
1054
|
-
target.classList.remove("prepr-overlay-active");
|
|
1055
|
-
flashTimeout = null;
|
|
1056
|
-
}, FLASH_DURATION_MS);
|
|
1057
|
-
return true;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
1016
|
// src/core/store.ts
|
|
1061
1017
|
var DEFAULT_STATE = {
|
|
1062
1018
|
locale: "en",
|
|
@@ -2169,7 +2125,7 @@ function definePreprToolbar() {
|
|
|
2169
2125
|
}
|
|
2170
2126
|
|
|
2171
2127
|
// src/core/create-preview.ts
|
|
2172
|
-
var
|
|
2128
|
+
var debug7 = createScopedLogger("create-preview");
|
|
2173
2129
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2174
2130
|
function defaultNavigation() {
|
|
2175
2131
|
return {
|
|
@@ -2211,7 +2167,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2211
2167
|
const search = new URLSearchParams(window.location.search);
|
|
2212
2168
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2213
2169
|
if (hideBar) {
|
|
2214
|
-
|
|
2170
|
+
debug7.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2215
2171
|
}
|
|
2216
2172
|
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2217
2173
|
const locale = resolveLocale(options);
|
|
@@ -2247,17 +2203,18 @@ function createPreprPreview(opts = {}) {
|
|
|
2247
2203
|
tooltip: mountUi,
|
|
2248
2204
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2249
2205
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2250
|
-
onEdit: ({ href, id, field
|
|
2206
|
+
onEdit: ({ href, origin, id, field }) => {
|
|
2251
2207
|
const safeHref = href ? safeEditUrl(href) : null;
|
|
2252
2208
|
if (href && !safeHref) {
|
|
2253
|
-
|
|
2209
|
+
debug7.warn("ignored edit request with unsupported href scheme");
|
|
2254
2210
|
return;
|
|
2255
2211
|
}
|
|
2256
2212
|
if (isIframe) {
|
|
2257
2213
|
sendPreprEvent("field_edit_requested", {
|
|
2214
|
+
href: safeHref ?? void 0,
|
|
2215
|
+
origin,
|
|
2258
2216
|
id,
|
|
2259
|
-
field
|
|
2260
|
-
locale: contentLocale
|
|
2217
|
+
field
|
|
2261
2218
|
});
|
|
2262
2219
|
} else if (safeHref) {
|
|
2263
2220
|
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
@@ -2265,7 +2222,8 @@ function createPreprPreview(opts = {}) {
|
|
|
2265
2222
|
}
|
|
2266
2223
|
});
|
|
2267
2224
|
const autoClean = createStegaAutoClean({
|
|
2268
|
-
enabled: options?.autoClean
|
|
2225
|
+
enabled: options?.autoClean,
|
|
2226
|
+
isHydrated: opts.isHydrated
|
|
2269
2227
|
});
|
|
2270
2228
|
autoClean.start();
|
|
2271
2229
|
const handleChange = createChangeHandler({
|
|
@@ -2284,15 +2242,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2284
2242
|
handleChange(before, state);
|
|
2285
2243
|
});
|
|
2286
2244
|
const bridge = createIframeBridge(store, {
|
|
2287
|
-
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2288
|
-
// The editor selecting a field scrolls the matching element into view. The
|
|
2289
|
-
// lookup relies on the attributes the stega scan writes, so it finds
|
|
2290
|
-
// nothing until encoded content has been tagged.
|
|
2291
|
-
onScrollToField: ({ field, id }) => {
|
|
2292
|
-
if (!scrollToField({ field, id })) {
|
|
2293
|
-
debug9.log("no element on this page renders field", field);
|
|
2294
|
-
}
|
|
2295
|
-
}
|
|
2245
|
+
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2296
2246
|
});
|
|
2297
2247
|
sendPreprEvent(
|
|
2298
2248
|
"getScrollPosition",
|
|
@@ -2312,15 +2262,34 @@ function createPreprPreview(opts = {}) {
|
|
|
2312
2262
|
bridge.stop();
|
|
2313
2263
|
}
|
|
2314
2264
|
el?.remove();
|
|
2315
|
-
|
|
2265
|
+
debug7.log("preview destroyed");
|
|
2316
2266
|
}
|
|
2317
2267
|
const controller = { destroy };
|
|
2318
2268
|
controllerStores.set(controller, store);
|
|
2319
2269
|
return controller;
|
|
2320
2270
|
}
|
|
2321
2271
|
|
|
2272
|
+
// src/react/hydration.ts
|
|
2273
|
+
var PROPS_KEY_PREFIX = "__reactProps$";
|
|
2274
|
+
function reactProps(element) {
|
|
2275
|
+
for (const key of Object.keys(element)) {
|
|
2276
|
+
if (key.startsWith(PROPS_KEY_PREFIX)) {
|
|
2277
|
+
return element[key];
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
return void 0;
|
|
2281
|
+
}
|
|
2282
|
+
function isReactHydrated(text) {
|
|
2283
|
+
for (let el = text.parentElement; el; el = el.parentElement) {
|
|
2284
|
+
const props = reactProps(el);
|
|
2285
|
+
if (!props) continue;
|
|
2286
|
+
return el === text.parentElement || props.dangerouslySetInnerHTML != null;
|
|
2287
|
+
}
|
|
2288
|
+
return true;
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2322
2291
|
// src/version.ts
|
|
2323
|
-
var VERSION = "0.
|
|
2292
|
+
var VERSION = "0.6.0-alpha.0";
|
|
2324
2293
|
|
|
2325
2294
|
// src/core/pixel.ts
|
|
2326
2295
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|
|
@@ -2368,7 +2337,12 @@ function PreprPreview({
|
|
|
2368
2337
|
...props
|
|
2369
2338
|
}) {
|
|
2370
2339
|
useEffect(() => {
|
|
2371
|
-
const preview = createPreprPreview({
|
|
2340
|
+
const preview = createPreprPreview({
|
|
2341
|
+
props,
|
|
2342
|
+
options,
|
|
2343
|
+
navigation,
|
|
2344
|
+
isHydrated: isReactHydrated
|
|
2345
|
+
});
|
|
2372
2346
|
return () => preview.destroy();
|
|
2373
2347
|
}, []);
|
|
2374
2348
|
return null;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { a as PreprErrorCode, c as PreprSegment, P as PreprHeaders, b as PreprFeatures, e as PreprToolbarProps } from './types-BYH9XqmN.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether a Prepr GraphQL response differs per visitor, read from its `Vary`
|
|
5
|
+
* header. Use it when fetching with your own GraphQL client; the toolkit's
|
|
6
|
+
* `createPreprClient` already returns it as `personalized`.
|
|
7
|
+
*
|
|
8
|
+
* Never throws; a response without `Vary` is not personalized.
|
|
9
|
+
*/
|
|
10
|
+
declare function isPersonalizedResponse(source: Response | Headers): boolean;
|
|
11
|
+
|
|
12
|
+
/** Error thrown by the token helpers and the segments fetch. */
|
|
13
|
+
declare class PreprError extends Error {
|
|
14
|
+
readonly code: PreprErrorCode;
|
|
15
|
+
readonly context?: string | undefined;
|
|
16
|
+
readonly originalError?: Error | undefined;
|
|
17
|
+
constructor(message: string, code: PreprErrorCode, context?: string | undefined, originalError?: Error | undefined);
|
|
18
|
+
}
|
|
19
|
+
/** Prepr Customer ID, or null if the middleware did not run for this request. */
|
|
20
|
+
declare function getPreprUUIDFromHeaders(headers: Headers): string | null;
|
|
21
|
+
/** Active segment ID, or null when no segment is selected. */
|
|
22
|
+
declare function getActiveSegmentFromHeaders(headers: Headers): string | null;
|
|
23
|
+
/** Active A/B variant (`'A'`/`'B'`), or null when no test is running. */
|
|
24
|
+
declare function getActiveVariantFromHeaders(headers: Headers): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Collect the Prepr headers into a `PreprHeaders`. Lookups are case-insensitive
|
|
27
|
+
* per the Fetch spec, but the returned keys use the declared casing.
|
|
28
|
+
*/
|
|
29
|
+
declare function getPreprHeadersFromHeaders(headers: Headers): PreprHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* Asserts `token` is the full `https://graphql.prepr.io/<token>` URL.
|
|
32
|
+
* @throws PreprError if the token is missing or not an HTTPS URL.
|
|
33
|
+
*/
|
|
34
|
+
declare function validatePreprToken(token: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Pulls the access token out of a GraphQL URL: `https://graphql.prepr.io/abc123`
|
|
37
|
+
* -> `abc123`.
|
|
38
|
+
* @throws PreprError if the URL is not a valid `graphql.prepr.io` URL.
|
|
39
|
+
*/
|
|
40
|
+
declare function extractAccessToken(graphqlUrl: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Fetches the environment's segments from the Prepr API.
|
|
43
|
+
*
|
|
44
|
+
* `token` must be a Prepr GraphQL URL with scope 'segments'.
|
|
45
|
+
* @throws PreprError if the token is invalid or the request fails.
|
|
46
|
+
*/
|
|
47
|
+
declare function getPreprEnvironmentSegments(token: string): Promise<PreprSegment[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Never throws: a failed segments fetch yields an empty list so the toolbar
|
|
50
|
+
* still renders. The list is returned under both `segments` and the deprecated
|
|
51
|
+
* `data` alias.
|
|
52
|
+
*
|
|
53
|
+
* Pass the same `features` object you give the toolbar and the middleware: with
|
|
54
|
+
* segments disabled the `_Segments` request is skipped entirely, saving a
|
|
55
|
+
* round-trip per page.
|
|
56
|
+
*/
|
|
57
|
+
declare function getToolbarPropsFromHeaders(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
58
|
+
|
|
59
|
+
export { PreprError as P, getActiveVariantFromHeaders as a, getPreprEnvironmentSegments as b, getPreprHeadersFromHeaders as c, getPreprUUIDFromHeaders as d, extractAccessToken as e, getToolbarPropsFromHeaders as f, getActiveSegmentFromHeaders as g, isPersonalizedResponse as i, validatePreprToken as v };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { a as PreprErrorCode, c as PreprSegment, P as PreprHeaders, b as PreprFeatures, e as PreprToolbarProps } from './types-BYH9XqmN.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether a Prepr GraphQL response differs per visitor, read from its `Vary`
|
|
5
|
+
* header. Use it when fetching with your own GraphQL client; the toolkit's
|
|
6
|
+
* `createPreprClient` already returns it as `personalized`.
|
|
7
|
+
*
|
|
8
|
+
* Never throws; a response without `Vary` is not personalized.
|
|
9
|
+
*/
|
|
10
|
+
declare function isPersonalizedResponse(source: Response | Headers): boolean;
|
|
11
|
+
|
|
12
|
+
/** Error thrown by the token helpers and the segments fetch. */
|
|
13
|
+
declare class PreprError extends Error {
|
|
14
|
+
readonly code: PreprErrorCode;
|
|
15
|
+
readonly context?: string | undefined;
|
|
16
|
+
readonly originalError?: Error | undefined;
|
|
17
|
+
constructor(message: string, code: PreprErrorCode, context?: string | undefined, originalError?: Error | undefined);
|
|
18
|
+
}
|
|
19
|
+
/** Prepr Customer ID, or null if the middleware did not run for this request. */
|
|
20
|
+
declare function getPreprUUIDFromHeaders(headers: Headers): string | null;
|
|
21
|
+
/** Active segment ID, or null when no segment is selected. */
|
|
22
|
+
declare function getActiveSegmentFromHeaders(headers: Headers): string | null;
|
|
23
|
+
/** Active A/B variant (`'A'`/`'B'`), or null when no test is running. */
|
|
24
|
+
declare function getActiveVariantFromHeaders(headers: Headers): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Collect the Prepr headers into a `PreprHeaders`. Lookups are case-insensitive
|
|
27
|
+
* per the Fetch spec, but the returned keys use the declared casing.
|
|
28
|
+
*/
|
|
29
|
+
declare function getPreprHeadersFromHeaders(headers: Headers): PreprHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* Asserts `token` is the full `https://graphql.prepr.io/<token>` URL.
|
|
32
|
+
* @throws PreprError if the token is missing or not an HTTPS URL.
|
|
33
|
+
*/
|
|
34
|
+
declare function validatePreprToken(token: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Pulls the access token out of a GraphQL URL: `https://graphql.prepr.io/abc123`
|
|
37
|
+
* -> `abc123`.
|
|
38
|
+
* @throws PreprError if the URL is not a valid `graphql.prepr.io` URL.
|
|
39
|
+
*/
|
|
40
|
+
declare function extractAccessToken(graphqlUrl: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Fetches the environment's segments from the Prepr API.
|
|
43
|
+
*
|
|
44
|
+
* `token` must be a Prepr GraphQL URL with scope 'segments'.
|
|
45
|
+
* @throws PreprError if the token is invalid or the request fails.
|
|
46
|
+
*/
|
|
47
|
+
declare function getPreprEnvironmentSegments(token: string): Promise<PreprSegment[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Never throws: a failed segments fetch yields an empty list so the toolbar
|
|
50
|
+
* still renders. The list is returned under both `segments` and the deprecated
|
|
51
|
+
* `data` alias.
|
|
52
|
+
*
|
|
53
|
+
* Pass the same `features` object you give the toolbar and the middleware: with
|
|
54
|
+
* segments disabled the `_Segments` request is skipped entirely, saving a
|
|
55
|
+
* round-trip per page.
|
|
56
|
+
*/
|
|
57
|
+
declare function getToolbarPropsFromHeaders(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
58
|
+
|
|
59
|
+
export { PreprError as P, getActiveVariantFromHeaders as a, getPreprEnvironmentSegments as b, getPreprHeadersFromHeaders as c, getPreprUUIDFromHeaders as d, extractAccessToken as e, getToolbarPropsFromHeaders as f, getActiveSegmentFromHeaders as g, isPersonalizedResponse as i, validatePreprToken as v };
|