@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.
- package/README.md +415 -27
- package/dist/astro/chunk-O7N6GPAH.js +173 -0
- package/dist/astro/graphql.cjs +1030 -0
- package/dist/astro/graphql.d.cts +305 -0
- package/dist/astro/graphql.d.ts +305 -0
- package/dist/astro/graphql.js +936 -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-3JLWZQ37.js +179 -0
- package/dist/chunk-3NCEVJJ3.js +10 -0
- package/dist/chunk-S5RWVMDJ.js +148 -0
- package/dist/chunk-TBKSBXGH.js +452 -0
- package/dist/{chunk-FLPNN3CV.js → chunk-VI6QZTBM.js} +73 -276
- package/dist/chunk-YWIKKWBR.js +26 -0
- package/dist/graphql/codegen.cjs +510 -0
- package/dist/graphql/codegen.d.cts +23 -0
- package/dist/graphql/codegen.d.ts +23 -0
- package/dist/graphql/codegen.js +99 -0
- package/dist/graphql.cjs +941 -0
- package/dist/graphql.d.cts +305 -0
- package/dist/graphql.d.ts +305 -0
- package/dist/graphql.js +419 -0
- package/dist/index.cjs +76 -119
- package/dist/index.d.cts +12 -64
- package/dist/index.d.ts +12 -64
- package/dist/index.js +27 -167
- package/dist/nextjs/chunk-BQ6IGSH6.js +231 -0
- package/dist/nextjs/components.cjs +190 -122
- package/dist/nextjs/components.d.cts +33 -2
- package/dist/nextjs/components.d.ts +33 -2
- package/dist/nextjs/components.js +133 -4
- package/dist/nextjs/graphql.cjs +1362 -0
- package/dist/nextjs/graphql.d.cts +435 -0
- package/dist/nextjs/graphql.d.ts +435 -0
- package/dist/nextjs/graphql.js +1261 -0
- package/dist/nextjs/index.cjs +126 -6
- package/dist/nextjs/index.d.cts +53 -147
- package/dist/nextjs/index.d.ts +53 -147
- 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-IQDSBPDN.js +417 -0
- package/dist/nuxt/graphql.cjs +1037 -0
- package/dist/nuxt/graphql.d.cts +302 -0
- package/dist/nuxt/graphql.d.ts +302 -0
- package/dist/nuxt/graphql.js +937 -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 +88 -120
- package/dist/react/components.d.cts +2 -8
- package/dist/react/components.d.ts +2 -8
- package/dist/react/components.js +88 -120
- package/dist/server-Brr1UgtW.d.ts +59 -0
- package/dist/server-DJuS3YU0.d.cts +59 -0
- package/dist/sveltekit/chunk-OKYZ6HPH.js +413 -0
- package/dist/sveltekit/graphql.cjs +1043 -0
- package/dist/sveltekit/graphql.d.cts +307 -0
- package/dist/sveltekit/graphql.d.ts +307 -0
- package/dist/sveltekit/graphql.js +943 -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-B3oQNbZ3.d.cts → types-BYH9XqmN.d.cts} +4 -58
- package/dist/{pixel-B3oQNbZ3.d.ts → types-BYH9XqmN.d.ts} +4 -58
- package/package.json +36 -1
package/dist/react/components.js
CHANGED
|
@@ -267,13 +267,9 @@ 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
|
-
if (allowed)
|
|
274
|
-
if (allowed.includes("*")) return origin !== "null";
|
|
275
|
-
return allowed.includes(origin);
|
|
276
|
-
}
|
|
272
|
+
if (allowed) return allowed.includes(origin);
|
|
277
273
|
let url;
|
|
278
274
|
try {
|
|
279
275
|
url = new URL(origin);
|
|
@@ -288,7 +284,6 @@ function isAllowedEditorOrigin(origin, allowed) {
|
|
|
288
284
|
}
|
|
289
285
|
function createIframeBridge(store, options = {}) {
|
|
290
286
|
const allowedOrigins = options.allowedEditorOrigins;
|
|
291
|
-
const onScrollToField = options.onScrollToField;
|
|
292
287
|
let parentOrigin = null;
|
|
293
288
|
const onKeyDown = (event) => {
|
|
294
289
|
const key = event.key.toLowerCase();
|
|
@@ -298,10 +293,7 @@ function createIframeBridge(store, options = {}) {
|
|
|
298
293
|
const onMessage = (evt) => {
|
|
299
294
|
const data = evt?.data;
|
|
300
295
|
if (data?.event === "prepr:initVE" && !parentOrigin) {
|
|
301
|
-
if (!isAllowedEditorOrigin(evt.origin, allowedOrigins))
|
|
302
|
-
debug.warn("ignored editor handshake from origin", evt.origin);
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
296
|
+
if (!isAllowedEditorOrigin(evt.origin, allowedOrigins)) return;
|
|
305
297
|
parentOrigin = evt.origin;
|
|
306
298
|
setTrustedParentOrigin(parentOrigin);
|
|
307
299
|
if (data.scrollPosition != null) {
|
|
@@ -315,15 +307,6 @@ function createIframeBridge(store, options = {}) {
|
|
|
315
307
|
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
316
308
|
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
317
309
|
}
|
|
318
|
-
if (data?.event === "prepr:scrollToField") {
|
|
319
|
-
if (typeof data.field !== "string" || !data.field) return;
|
|
320
|
-
if (data.id !== void 0 && typeof data.id !== "string") return;
|
|
321
|
-
try {
|
|
322
|
-
onScrollToField?.({ field: data.field, id: data.id });
|
|
323
|
-
} catch (error) {
|
|
324
|
-
debug.warn("scrollToField handler failed", error);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
310
|
};
|
|
328
311
|
return {
|
|
329
312
|
start() {
|
|
@@ -348,7 +331,7 @@ import { vercelStegaSplit } from "@vercel/stega";
|
|
|
348
331
|
|
|
349
332
|
// src/core/stega/clean.ts
|
|
350
333
|
import { vercelStegaClean, vercelStegaDecode } from "@vercel/stega";
|
|
351
|
-
var
|
|
334
|
+
var debug = createScopedLogger("stega:clean");
|
|
352
335
|
function decodeStega(str) {
|
|
353
336
|
if (!str) return null;
|
|
354
337
|
try {
|
|
@@ -357,7 +340,7 @@ function decodeStega(str) {
|
|
|
357
340
|
return decoded;
|
|
358
341
|
}
|
|
359
342
|
} catch (error) {
|
|
360
|
-
|
|
343
|
+
debug.log("error decoding stega data", error);
|
|
361
344
|
const match = str.match(/{"origin.*?}/);
|
|
362
345
|
if (match) {
|
|
363
346
|
try {
|
|
@@ -366,7 +349,7 @@ function decodeStega(str) {
|
|
|
366
349
|
return decodedMatch;
|
|
367
350
|
}
|
|
368
351
|
} catch (innerError) {
|
|
369
|
-
|
|
352
|
+
debug.log("error decoding stega regex match", innerError);
|
|
370
353
|
}
|
|
371
354
|
}
|
|
372
355
|
}
|
|
@@ -402,37 +385,15 @@ function isRenderedElement(element) {
|
|
|
402
385
|
if (!style) return true;
|
|
403
386
|
return style.visibility !== "hidden" && style.display !== "none";
|
|
404
387
|
}
|
|
405
|
-
function parseEditHref(href) {
|
|
406
|
-
try {
|
|
407
|
-
const url = new URL(href, window.location.origin);
|
|
408
|
-
return {
|
|
409
|
-
id: url.pathname.split("/").pop() || void 0,
|
|
410
|
-
field: url.searchParams.get("field") || void 0,
|
|
411
|
-
locale: url.searchParams.get("locale") || void 0
|
|
412
|
-
};
|
|
413
|
-
} catch {
|
|
414
|
-
return {};
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
function setOrRemove(element, name, value) {
|
|
418
|
-
if (value) {
|
|
419
|
-
element.setAttribute(name, value);
|
|
420
|
-
} else {
|
|
421
|
-
element.removeAttribute(name);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
388
|
function tagEncodedElement(element, decoded) {
|
|
425
389
|
element.setAttribute("data-prepr-encoded", "");
|
|
426
390
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
427
391
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
428
|
-
const { id, field, locale } = parseEditHref(decoded.href);
|
|
429
|
-
setOrRemove(element, "data-prepr-id", id);
|
|
430
|
-
setOrRemove(element, "data-prepr-field", field);
|
|
431
|
-
setOrRemove(element, "data-prepr-locale", locale);
|
|
432
392
|
}
|
|
433
393
|
|
|
434
394
|
// src/core/stega/auto-clean.ts
|
|
435
|
-
var
|
|
395
|
+
var debug2 = createScopedLogger("stega:auto-clean");
|
|
396
|
+
var HYDRATION_RETRY_MS = 100;
|
|
436
397
|
function createStegaAutoClean(options) {
|
|
437
398
|
const stripText = options?.enabled ?? true;
|
|
438
399
|
let observer = null;
|
|
@@ -441,8 +402,29 @@ function createStegaAutoClean(options) {
|
|
|
441
402
|
let pendingHidden = /* @__PURE__ */ new Set();
|
|
442
403
|
let pendingDirty = /* @__PURE__ */ new Set();
|
|
443
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
|
+
}
|
|
444
418
|
function cleanTextNode(textNode) {
|
|
445
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
|
+
}
|
|
446
428
|
const textContent = textNode.textContent;
|
|
447
429
|
const info = cleaned.get(textNode);
|
|
448
430
|
const settled = stripText ? info?.cleaned : info?.original;
|
|
@@ -475,7 +457,7 @@ function createStegaAutoClean(options) {
|
|
|
475
457
|
}
|
|
476
458
|
pendingHidden.add(textNode);
|
|
477
459
|
} catch (error) {
|
|
478
|
-
|
|
460
|
+
debug2.log("error cleaning text node", error);
|
|
479
461
|
}
|
|
480
462
|
return false;
|
|
481
463
|
}
|
|
@@ -561,13 +543,17 @@ function createStegaAutoClean(options) {
|
|
|
561
543
|
if (observer || typeof window === "undefined") return;
|
|
562
544
|
scanAndClean();
|
|
563
545
|
setupObserver();
|
|
564
|
-
|
|
546
|
+
debug2.log("stega auto-clean started");
|
|
565
547
|
}
|
|
566
548
|
function stop() {
|
|
567
549
|
if (debounceTimeout) {
|
|
568
550
|
clearTimeout(debounceTimeout);
|
|
569
551
|
debounceTimeout = null;
|
|
570
552
|
}
|
|
553
|
+
if (hydrationTimeout) {
|
|
554
|
+
clearTimeout(hydrationTimeout);
|
|
555
|
+
hydrationTimeout = null;
|
|
556
|
+
}
|
|
571
557
|
if (observer) {
|
|
572
558
|
observer.disconnect();
|
|
573
559
|
observer = null;
|
|
@@ -575,13 +561,14 @@ function createStegaAutoClean(options) {
|
|
|
575
561
|
cleaned = /* @__PURE__ */ new WeakMap();
|
|
576
562
|
pendingHidden = /* @__PURE__ */ new Set();
|
|
577
563
|
pendingDirty = /* @__PURE__ */ new Set();
|
|
578
|
-
|
|
564
|
+
pendingHydration = /* @__PURE__ */ new Set();
|
|
565
|
+
debug2.log("stega auto-clean stopped");
|
|
579
566
|
}
|
|
580
567
|
return { start, stop };
|
|
581
568
|
}
|
|
582
569
|
|
|
583
570
|
// src/core/stega/elements.ts
|
|
584
|
-
var
|
|
571
|
+
var debug3 = createScopedLogger("stega:elements");
|
|
585
572
|
var StegaElements = class {
|
|
586
573
|
constructor(decode = decodeStega) {
|
|
587
574
|
this.observer = null;
|
|
@@ -626,7 +613,7 @@ var StegaElements = class {
|
|
|
626
613
|
walkTextNodes(document.body, (textNode) => {
|
|
627
614
|
if (this.tagFromTextNode(textNode)) encodedCount++;
|
|
628
615
|
});
|
|
629
|
-
|
|
616
|
+
debug3.log("document scan complete, encoded", encodedCount, "elements");
|
|
630
617
|
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
631
618
|
}
|
|
632
619
|
/** `onUpdate` fires after each debounced batch, for refreshing derived state. */
|
|
@@ -682,9 +669,6 @@ var StegaElements = class {
|
|
|
682
669
|
element.removeAttribute("data-prepr-encoded");
|
|
683
670
|
element.removeAttribute("data-prepr-href");
|
|
684
671
|
element.removeAttribute("data-prepr-origin");
|
|
685
|
-
element.removeAttribute("data-prepr-id");
|
|
686
|
-
element.removeAttribute("data-prepr-field");
|
|
687
|
-
element.removeAttribute("data-prepr-locale");
|
|
688
672
|
element.classList.remove("prepr-overlay-active");
|
|
689
673
|
});
|
|
690
674
|
this.elements = void 0;
|
|
@@ -692,7 +676,7 @@ var StegaElements = class {
|
|
|
692
676
|
};
|
|
693
677
|
|
|
694
678
|
// src/core/stega/overlay.ts
|
|
695
|
-
var
|
|
679
|
+
var debug4 = createScopedLogger("stega:overlay");
|
|
696
680
|
var StegaOverlay = class {
|
|
697
681
|
constructor(onEdit) {
|
|
698
682
|
this.overlay = null;
|
|
@@ -737,8 +721,7 @@ var StegaOverlay = class {
|
|
|
737
721
|
const origin = element.getAttribute("data-prepr-origin");
|
|
738
722
|
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
739
723
|
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
740
|
-
|
|
741
|
-
debug5.log("showing overlay", { href, origin });
|
|
724
|
+
debug4.log("showing overlay", { href, origin });
|
|
742
725
|
const overlay = this.overlay;
|
|
743
726
|
overlay.style.display = "block";
|
|
744
727
|
overlay.style.top = `${rect.top + window.scrollY - 2}px`;
|
|
@@ -770,7 +753,7 @@ var StegaOverlay = class {
|
|
|
770
753
|
tooltip.style.left = `${left}px`;
|
|
771
754
|
});
|
|
772
755
|
tooltip.onclick = () => {
|
|
773
|
-
this.onEdit({ href, origin, id, field
|
|
756
|
+
this.onEdit({ href, origin, id, field });
|
|
774
757
|
};
|
|
775
758
|
}
|
|
776
759
|
this.currentElement = element;
|
|
@@ -810,7 +793,7 @@ var StegaOverlay = class {
|
|
|
810
793
|
};
|
|
811
794
|
|
|
812
795
|
// src/core/stega/proximity.ts
|
|
813
|
-
var
|
|
796
|
+
var debug5 = createScopedLogger("stega:proximity");
|
|
814
797
|
var StegaProximity = class {
|
|
815
798
|
constructor() {
|
|
816
799
|
this.highlighted = /* @__PURE__ */ new Set();
|
|
@@ -845,9 +828,9 @@ var StegaProximity = class {
|
|
|
845
828
|
);
|
|
846
829
|
const nodes = this.getEncodedElements();
|
|
847
830
|
nodes.forEach((el) => this.observer.observe(el));
|
|
848
|
-
|
|
831
|
+
debug5.log("observing", nodes.length, "encoded elements");
|
|
849
832
|
} catch (error) {
|
|
850
|
-
|
|
833
|
+
debug5.log("error setting up IntersectionObserver", error);
|
|
851
834
|
}
|
|
852
835
|
}
|
|
853
836
|
stopObserving() {
|
|
@@ -917,7 +900,7 @@ function removeStegaStyles() {
|
|
|
917
900
|
}
|
|
918
901
|
|
|
919
902
|
// src/core/stega/scan.ts
|
|
920
|
-
var
|
|
903
|
+
var debug6 = createScopedLogger("stega:scan");
|
|
921
904
|
var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
|
|
922
905
|
function createStegaController(opts) {
|
|
923
906
|
const tooltipEnabled = opts.tooltip ?? true;
|
|
@@ -950,13 +933,12 @@ function createStegaController(opts) {
|
|
|
950
933
|
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
951
934
|
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
952
935
|
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
953
|
-
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
954
|
-
locale: encoded.getAttribute("data-prepr-locale") ?? void 0
|
|
936
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
955
937
|
});
|
|
956
938
|
};
|
|
957
939
|
const start = () => {
|
|
958
940
|
if (initialized) {
|
|
959
|
-
|
|
941
|
+
debug6.log("already initialized, skipping setup");
|
|
960
942
|
return;
|
|
961
943
|
}
|
|
962
944
|
if (!tooltipEnabled) {
|
|
@@ -966,7 +948,7 @@ function createStegaController(opts) {
|
|
|
966
948
|
});
|
|
967
949
|
document.addEventListener("click", handleClick, { capture: true });
|
|
968
950
|
initialized = true;
|
|
969
|
-
|
|
951
|
+
debug6.log("stega controller started (editor mode)");
|
|
970
952
|
return;
|
|
971
953
|
}
|
|
972
954
|
injectStegaStyles();
|
|
@@ -997,7 +979,7 @@ function createStegaController(opts) {
|
|
|
997
979
|
passive: true
|
|
998
980
|
});
|
|
999
981
|
initialized = true;
|
|
1000
|
-
|
|
982
|
+
debug6.log("stega controller started");
|
|
1001
983
|
};
|
|
1002
984
|
const stop = () => {
|
|
1003
985
|
if (!initialized) return;
|
|
@@ -1006,7 +988,7 @@ function createStegaController(opts) {
|
|
|
1006
988
|
elements.cleanup();
|
|
1007
989
|
removeStegaStyles();
|
|
1008
990
|
initialized = false;
|
|
1009
|
-
|
|
991
|
+
debug6.log("stega controller stopped (editor mode)");
|
|
1010
992
|
return;
|
|
1011
993
|
}
|
|
1012
994
|
if (throttledMouseMove) {
|
|
@@ -1026,43 +1008,11 @@ function createStegaController(opts) {
|
|
|
1026
1008
|
elements.cleanup();
|
|
1027
1009
|
removeStegaStyles();
|
|
1028
1010
|
initialized = false;
|
|
1029
|
-
|
|
1011
|
+
debug6.log("stega controller stopped");
|
|
1030
1012
|
};
|
|
1031
1013
|
return { start, stop };
|
|
1032
1014
|
}
|
|
1033
1015
|
|
|
1034
|
-
// src/core/stega/scroll-to-field.ts
|
|
1035
|
-
var debug8 = createScopedLogger("stega:scroll");
|
|
1036
|
-
var FLASH_DURATION_MS = 1200;
|
|
1037
|
-
var flashTimeout = null;
|
|
1038
|
-
function scrollToField(request) {
|
|
1039
|
-
const { field, id } = request;
|
|
1040
|
-
if (!field) return false;
|
|
1041
|
-
const candidates = document.querySelectorAll(
|
|
1042
|
-
"[data-prepr-encoded]"
|
|
1043
|
-
);
|
|
1044
|
-
let target = null;
|
|
1045
|
-
for (const candidate of candidates) {
|
|
1046
|
-
if (candidate.getAttribute("data-prepr-field") !== field) continue;
|
|
1047
|
-
if (id && candidate.getAttribute("data-prepr-id") !== id) continue;
|
|
1048
|
-
target = candidate;
|
|
1049
|
-
break;
|
|
1050
|
-
}
|
|
1051
|
-
if (!target) {
|
|
1052
|
-
debug8.log("no element found for field", field);
|
|
1053
|
-
return false;
|
|
1054
|
-
}
|
|
1055
|
-
target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1056
|
-
if (flashTimeout) clearTimeout(flashTimeout);
|
|
1057
|
-
document.querySelectorAll(".prepr-overlay-active").forEach((el) => el.classList.remove("prepr-overlay-active"));
|
|
1058
|
-
target.classList.add("prepr-overlay-active");
|
|
1059
|
-
flashTimeout = setTimeout(() => {
|
|
1060
|
-
target.classList.remove("prepr-overlay-active");
|
|
1061
|
-
flashTimeout = null;
|
|
1062
|
-
}, FLASH_DURATION_MS);
|
|
1063
|
-
return true;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
1016
|
// src/core/store.ts
|
|
1067
1017
|
var DEFAULT_STATE = {
|
|
1068
1018
|
locale: "en",
|
|
@@ -2175,7 +2125,7 @@ function definePreprToolbar() {
|
|
|
2175
2125
|
}
|
|
2176
2126
|
|
|
2177
2127
|
// src/core/create-preview.ts
|
|
2178
|
-
var
|
|
2128
|
+
var debug7 = createScopedLogger("create-preview");
|
|
2179
2129
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2180
2130
|
function defaultNavigation() {
|
|
2181
2131
|
return {
|
|
@@ -2217,7 +2167,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2217
2167
|
const search = new URLSearchParams(window.location.search);
|
|
2218
2168
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2219
2169
|
if (hideBar) {
|
|
2220
|
-
|
|
2170
|
+
debug7.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2221
2171
|
}
|
|
2222
2172
|
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2223
2173
|
const locale = resolveLocale(options);
|
|
@@ -2253,17 +2203,18 @@ function createPreprPreview(opts = {}) {
|
|
|
2253
2203
|
tooltip: mountUi,
|
|
2254
2204
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2255
2205
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2256
|
-
onEdit: ({ href, id, field
|
|
2206
|
+
onEdit: ({ href, origin, id, field }) => {
|
|
2257
2207
|
const safeHref = href ? safeEditUrl(href) : null;
|
|
2258
2208
|
if (href && !safeHref) {
|
|
2259
|
-
|
|
2209
|
+
debug7.warn("ignored edit request with unsupported href scheme");
|
|
2260
2210
|
return;
|
|
2261
2211
|
}
|
|
2262
2212
|
if (isIframe) {
|
|
2263
2213
|
sendPreprEvent("field_edit_requested", {
|
|
2214
|
+
href: safeHref ?? void 0,
|
|
2215
|
+
origin,
|
|
2264
2216
|
id,
|
|
2265
|
-
field
|
|
2266
|
-
locale: contentLocale
|
|
2217
|
+
field
|
|
2267
2218
|
});
|
|
2268
2219
|
} else if (safeHref) {
|
|
2269
2220
|
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
@@ -2271,7 +2222,8 @@ function createPreprPreview(opts = {}) {
|
|
|
2271
2222
|
}
|
|
2272
2223
|
});
|
|
2273
2224
|
const autoClean = createStegaAutoClean({
|
|
2274
|
-
enabled: options?.autoClean
|
|
2225
|
+
enabled: options?.autoClean,
|
|
2226
|
+
isHydrated: opts.isHydrated
|
|
2275
2227
|
});
|
|
2276
2228
|
autoClean.start();
|
|
2277
2229
|
const handleChange = createChangeHandler({
|
|
@@ -2290,15 +2242,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2290
2242
|
handleChange(before, state);
|
|
2291
2243
|
});
|
|
2292
2244
|
const bridge = createIframeBridge(store, {
|
|
2293
|
-
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2294
|
-
// The editor selecting a field scrolls the matching element into view. The
|
|
2295
|
-
// lookup relies on the attributes the stega scan writes, so it finds
|
|
2296
|
-
// nothing until encoded content has been tagged.
|
|
2297
|
-
onScrollToField: ({ field, id }) => {
|
|
2298
|
-
if (!scrollToField({ field, id })) {
|
|
2299
|
-
debug9.log("no element on this page renders field", field);
|
|
2300
|
-
}
|
|
2301
|
-
}
|
|
2245
|
+
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2302
2246
|
});
|
|
2303
2247
|
sendPreprEvent(
|
|
2304
2248
|
"getScrollPosition",
|
|
@@ -2318,15 +2262,34 @@ function createPreprPreview(opts = {}) {
|
|
|
2318
2262
|
bridge.stop();
|
|
2319
2263
|
}
|
|
2320
2264
|
el?.remove();
|
|
2321
|
-
|
|
2265
|
+
debug7.log("preview destroyed");
|
|
2322
2266
|
}
|
|
2323
2267
|
const controller = { destroy };
|
|
2324
2268
|
controllerStores.set(controller, store);
|
|
2325
2269
|
return controller;
|
|
2326
2270
|
}
|
|
2327
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
|
+
|
|
2328
2291
|
// src/version.ts
|
|
2329
|
-
var VERSION = "0.
|
|
2292
|
+
var VERSION = "0.6.0-alpha.1";
|
|
2330
2293
|
|
|
2331
2294
|
// src/core/pixel.ts
|
|
2332
2295
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|
|
@@ -2374,7 +2337,12 @@ function PreprPreview({
|
|
|
2374
2337
|
...props
|
|
2375
2338
|
}) {
|
|
2376
2339
|
useEffect(() => {
|
|
2377
|
-
const preview = createPreprPreview({
|
|
2340
|
+
const preview = createPreprPreview({
|
|
2341
|
+
props,
|
|
2342
|
+
options,
|
|
2343
|
+
navigation,
|
|
2344
|
+
isHydrated: isReactHydrated
|
|
2345
|
+
});
|
|
2378
2346
|
return () => preview.destroy();
|
|
2379
2347
|
}, []);
|
|
2380
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 };
|