@preprio/toolkit 0.4.3 → 0.5.0-rc.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/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/{chunk-H7VA7NGY.js → chunk-4JNKYIEV.js} +90 -12
- package/dist/index.cjs +110 -32
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +1 -1
- package/dist/nextjs/components.cjs +110 -32
- package/dist/nextjs/components.js +1 -1
- package/dist/nextjs/index.cjs +1 -1
- package/dist/nextjs/index.js +1 -1
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/react/components.cjs +110 -32
- package/dist/react/components.js +110 -32
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +1 -1
|
@@ -291,6 +291,7 @@ function createElementCache(query, ttl = 1e3) {
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
// src/core/iframe-bridge.ts
|
|
294
|
+
var debug = createScopedLogger("iframe-bridge");
|
|
294
295
|
var EDITOR_BASE_DOMAIN = "prepr.io";
|
|
295
296
|
function isAllowedEditorOrigin(origin, allowed) {
|
|
296
297
|
if (allowed) return allowed.includes(origin);
|
|
@@ -308,6 +309,7 @@ function isAllowedEditorOrigin(origin, allowed) {
|
|
|
308
309
|
}
|
|
309
310
|
function createIframeBridge(store, options = {}) {
|
|
310
311
|
const allowedOrigins = options.allowedEditorOrigins;
|
|
312
|
+
const onScrollToField = options.onScrollToField;
|
|
311
313
|
let parentOrigin = null;
|
|
312
314
|
const onKeyDown = (event) => {
|
|
313
315
|
const key = event.key.toLowerCase();
|
|
@@ -331,6 +333,15 @@ function createIframeBridge(store, options = {}) {
|
|
|
331
333
|
const currentScrollY = window.scrollY || document.documentElement.scrollTop;
|
|
332
334
|
sendPreprEvent("getScrollPosition", { value: currentScrollY });
|
|
333
335
|
}
|
|
336
|
+
if (data?.event === "prepr:scrollToField") {
|
|
337
|
+
if (typeof data.field !== "string" || !data.field) return;
|
|
338
|
+
if (data.id !== void 0 && typeof data.id !== "string") return;
|
|
339
|
+
try {
|
|
340
|
+
onScrollToField?.({ field: data.field, id: data.id });
|
|
341
|
+
} catch (error) {
|
|
342
|
+
debug.warn("scrollToField handler failed", error);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
334
345
|
};
|
|
335
346
|
return {
|
|
336
347
|
start() {
|
|
@@ -355,7 +366,7 @@ var import_stega2 = require("@vercel/stega");
|
|
|
355
366
|
|
|
356
367
|
// src/core/stega/clean.ts
|
|
357
368
|
var import_stega = require("@vercel/stega");
|
|
358
|
-
var
|
|
369
|
+
var debug2 = createScopedLogger("stega:clean");
|
|
359
370
|
function decodeStega(str) {
|
|
360
371
|
if (!str) return null;
|
|
361
372
|
try {
|
|
@@ -364,7 +375,7 @@ function decodeStega(str) {
|
|
|
364
375
|
return decoded;
|
|
365
376
|
}
|
|
366
377
|
} catch (error) {
|
|
367
|
-
|
|
378
|
+
debug2.log("error decoding stega data", error);
|
|
368
379
|
const match = str.match(/{"origin.*?}/);
|
|
369
380
|
if (match) {
|
|
370
381
|
try {
|
|
@@ -373,7 +384,7 @@ function decodeStega(str) {
|
|
|
373
384
|
return decodedMatch;
|
|
374
385
|
}
|
|
375
386
|
} catch (innerError) {
|
|
376
|
-
|
|
387
|
+
debug2.log("error decoding stega regex match", innerError);
|
|
377
388
|
}
|
|
378
389
|
}
|
|
379
390
|
}
|
|
@@ -409,14 +420,37 @@ function isRenderedElement(element) {
|
|
|
409
420
|
if (!style) return true;
|
|
410
421
|
return style.visibility !== "hidden" && style.display !== "none";
|
|
411
422
|
}
|
|
423
|
+
function parseEditHref(href) {
|
|
424
|
+
try {
|
|
425
|
+
const url = new URL(href, window.location.origin);
|
|
426
|
+
return {
|
|
427
|
+
id: url.pathname.split("/").pop() || void 0,
|
|
428
|
+
field: url.searchParams.get("field") || void 0,
|
|
429
|
+
locale: url.searchParams.get("locale") || void 0
|
|
430
|
+
};
|
|
431
|
+
} catch {
|
|
432
|
+
return {};
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function setOrRemove(element, name, value) {
|
|
436
|
+
if (value) {
|
|
437
|
+
element.setAttribute(name, value);
|
|
438
|
+
} else {
|
|
439
|
+
element.removeAttribute(name);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
412
442
|
function tagEncodedElement(element, decoded) {
|
|
413
443
|
element.setAttribute("data-prepr-encoded", "");
|
|
414
444
|
element.setAttribute("data-prepr-href", decoded.href);
|
|
415
445
|
element.setAttribute("data-prepr-origin", decoded.origin);
|
|
446
|
+
const { id, field, locale } = parseEditHref(decoded.href);
|
|
447
|
+
setOrRemove(element, "data-prepr-id", id);
|
|
448
|
+
setOrRemove(element, "data-prepr-field", field);
|
|
449
|
+
setOrRemove(element, "data-prepr-locale", locale);
|
|
416
450
|
}
|
|
417
451
|
|
|
418
452
|
// src/core/stega/auto-clean.ts
|
|
419
|
-
var
|
|
453
|
+
var debug3 = createScopedLogger("stega:auto-clean");
|
|
420
454
|
function createStegaAutoClean(options) {
|
|
421
455
|
const stripText = options?.enabled ?? true;
|
|
422
456
|
let observer = null;
|
|
@@ -459,7 +493,7 @@ function createStegaAutoClean(options) {
|
|
|
459
493
|
}
|
|
460
494
|
pendingHidden.add(textNode);
|
|
461
495
|
} catch (error) {
|
|
462
|
-
|
|
496
|
+
debug3.log("error cleaning text node", error);
|
|
463
497
|
}
|
|
464
498
|
return false;
|
|
465
499
|
}
|
|
@@ -545,7 +579,7 @@ function createStegaAutoClean(options) {
|
|
|
545
579
|
if (observer || typeof window === "undefined") return;
|
|
546
580
|
scanAndClean();
|
|
547
581
|
setupObserver();
|
|
548
|
-
|
|
582
|
+
debug3.log("stega auto-clean started");
|
|
549
583
|
}
|
|
550
584
|
function stop() {
|
|
551
585
|
if (debounceTimeout) {
|
|
@@ -559,13 +593,13 @@ function createStegaAutoClean(options) {
|
|
|
559
593
|
cleaned = /* @__PURE__ */ new WeakMap();
|
|
560
594
|
pendingHidden = /* @__PURE__ */ new Set();
|
|
561
595
|
pendingDirty = /* @__PURE__ */ new Set();
|
|
562
|
-
|
|
596
|
+
debug3.log("stega auto-clean stopped");
|
|
563
597
|
}
|
|
564
598
|
return { start, stop };
|
|
565
599
|
}
|
|
566
600
|
|
|
567
601
|
// src/core/stega/elements.ts
|
|
568
|
-
var
|
|
602
|
+
var debug4 = createScopedLogger("stega:elements");
|
|
569
603
|
var StegaElements = class {
|
|
570
604
|
constructor(decode = decodeStega) {
|
|
571
605
|
this.observer = null;
|
|
@@ -610,7 +644,7 @@ var StegaElements = class {
|
|
|
610
644
|
walkTextNodes(document.body, (textNode) => {
|
|
611
645
|
if (this.tagFromTextNode(textNode)) encodedCount++;
|
|
612
646
|
});
|
|
613
|
-
|
|
647
|
+
debug4.log("document scan complete, encoded", encodedCount, "elements");
|
|
614
648
|
this.elements = document.querySelectorAll("[data-prepr-encoded]");
|
|
615
649
|
}
|
|
616
650
|
/** `onUpdate` fires after each debounced batch, for refreshing derived state. */
|
|
@@ -666,6 +700,9 @@ var StegaElements = class {
|
|
|
666
700
|
element.removeAttribute("data-prepr-encoded");
|
|
667
701
|
element.removeAttribute("data-prepr-href");
|
|
668
702
|
element.removeAttribute("data-prepr-origin");
|
|
703
|
+
element.removeAttribute("data-prepr-id");
|
|
704
|
+
element.removeAttribute("data-prepr-field");
|
|
705
|
+
element.removeAttribute("data-prepr-locale");
|
|
669
706
|
element.classList.remove("prepr-overlay-active");
|
|
670
707
|
});
|
|
671
708
|
this.elements = void 0;
|
|
@@ -673,7 +710,7 @@ var StegaElements = class {
|
|
|
673
710
|
};
|
|
674
711
|
|
|
675
712
|
// src/core/stega/overlay.ts
|
|
676
|
-
var
|
|
713
|
+
var debug5 = createScopedLogger("stega:overlay");
|
|
677
714
|
var StegaOverlay = class {
|
|
678
715
|
constructor(onEdit) {
|
|
679
716
|
this.overlay = null;
|
|
@@ -718,7 +755,8 @@ var StegaOverlay = class {
|
|
|
718
755
|
const origin = element.getAttribute("data-prepr-origin");
|
|
719
756
|
const id = element.getAttribute("data-prepr-id") ?? void 0;
|
|
720
757
|
const field = element.getAttribute("data-prepr-field") ?? void 0;
|
|
721
|
-
|
|
758
|
+
const locale = element.getAttribute("data-prepr-locale") ?? void 0;
|
|
759
|
+
debug5.log("showing overlay", { href, origin });
|
|
722
760
|
const overlay = this.overlay;
|
|
723
761
|
overlay.style.display = "block";
|
|
724
762
|
overlay.style.top = `${rect.top + window.scrollY - 2}px`;
|
|
@@ -750,7 +788,7 @@ var StegaOverlay = class {
|
|
|
750
788
|
tooltip.style.left = `${left}px`;
|
|
751
789
|
});
|
|
752
790
|
tooltip.onclick = () => {
|
|
753
|
-
this.onEdit({ href, origin, id, field });
|
|
791
|
+
this.onEdit({ href, origin, id, field, locale });
|
|
754
792
|
};
|
|
755
793
|
}
|
|
756
794
|
this.currentElement = element;
|
|
@@ -790,7 +828,7 @@ var StegaOverlay = class {
|
|
|
790
828
|
};
|
|
791
829
|
|
|
792
830
|
// src/core/stega/proximity.ts
|
|
793
|
-
var
|
|
831
|
+
var debug6 = createScopedLogger("stega:proximity");
|
|
794
832
|
var StegaProximity = class {
|
|
795
833
|
constructor() {
|
|
796
834
|
this.highlighted = /* @__PURE__ */ new Set();
|
|
@@ -825,9 +863,9 @@ var StegaProximity = class {
|
|
|
825
863
|
);
|
|
826
864
|
const nodes = this.getEncodedElements();
|
|
827
865
|
nodes.forEach((el) => this.observer.observe(el));
|
|
828
|
-
|
|
866
|
+
debug6.log("observing", nodes.length, "encoded elements");
|
|
829
867
|
} catch (error) {
|
|
830
|
-
|
|
868
|
+
debug6.log("error setting up IntersectionObserver", error);
|
|
831
869
|
}
|
|
832
870
|
}
|
|
833
871
|
stopObserving() {
|
|
@@ -897,7 +935,7 @@ function removeStegaStyles() {
|
|
|
897
935
|
}
|
|
898
936
|
|
|
899
937
|
// src/core/stega/scan.ts
|
|
900
|
-
var
|
|
938
|
+
var debug7 = createScopedLogger("stega:scan");
|
|
901
939
|
var EDITOR_MODE_STYLES = "[data-prepr-encoded]{cursor:pointer}";
|
|
902
940
|
function createStegaController(opts) {
|
|
903
941
|
const tooltipEnabled = opts.tooltip ?? true;
|
|
@@ -930,12 +968,13 @@ function createStegaController(opts) {
|
|
|
930
968
|
href: encoded.getAttribute("data-prepr-href") ?? "",
|
|
931
969
|
origin: encoded.getAttribute("data-prepr-origin") ?? "",
|
|
932
970
|
id: encoded.getAttribute("data-prepr-id") ?? void 0,
|
|
933
|
-
field: encoded.getAttribute("data-prepr-field") ?? void 0
|
|
971
|
+
field: encoded.getAttribute("data-prepr-field") ?? void 0,
|
|
972
|
+
locale: encoded.getAttribute("data-prepr-locale") ?? void 0
|
|
934
973
|
});
|
|
935
974
|
};
|
|
936
975
|
const start = () => {
|
|
937
976
|
if (initialized) {
|
|
938
|
-
|
|
977
|
+
debug7.log("already initialized, skipping setup");
|
|
939
978
|
return;
|
|
940
979
|
}
|
|
941
980
|
if (!tooltipEnabled) {
|
|
@@ -945,7 +984,7 @@ function createStegaController(opts) {
|
|
|
945
984
|
});
|
|
946
985
|
document.addEventListener("click", handleClick, { capture: true });
|
|
947
986
|
initialized = true;
|
|
948
|
-
|
|
987
|
+
debug7.log("stega controller started (editor mode)");
|
|
949
988
|
return;
|
|
950
989
|
}
|
|
951
990
|
injectStegaStyles();
|
|
@@ -976,7 +1015,7 @@ function createStegaController(opts) {
|
|
|
976
1015
|
passive: true
|
|
977
1016
|
});
|
|
978
1017
|
initialized = true;
|
|
979
|
-
|
|
1018
|
+
debug7.log("stega controller started");
|
|
980
1019
|
};
|
|
981
1020
|
const stop = () => {
|
|
982
1021
|
if (!initialized) return;
|
|
@@ -985,7 +1024,7 @@ function createStegaController(opts) {
|
|
|
985
1024
|
elements.cleanup();
|
|
986
1025
|
removeStegaStyles();
|
|
987
1026
|
initialized = false;
|
|
988
|
-
|
|
1027
|
+
debug7.log("stega controller stopped (editor mode)");
|
|
989
1028
|
return;
|
|
990
1029
|
}
|
|
991
1030
|
if (throttledMouseMove) {
|
|
@@ -1005,11 +1044,43 @@ function createStegaController(opts) {
|
|
|
1005
1044
|
elements.cleanup();
|
|
1006
1045
|
removeStegaStyles();
|
|
1007
1046
|
initialized = false;
|
|
1008
|
-
|
|
1047
|
+
debug7.log("stega controller stopped");
|
|
1009
1048
|
};
|
|
1010
1049
|
return { start, stop };
|
|
1011
1050
|
}
|
|
1012
1051
|
|
|
1052
|
+
// src/core/stega/scroll-to-field.ts
|
|
1053
|
+
var debug8 = createScopedLogger("stega:scroll");
|
|
1054
|
+
var FLASH_DURATION_MS = 1200;
|
|
1055
|
+
var flashTimeout = null;
|
|
1056
|
+
function scrollToField(request) {
|
|
1057
|
+
const { field, id } = request;
|
|
1058
|
+
if (!field) return false;
|
|
1059
|
+
const candidates = document.querySelectorAll(
|
|
1060
|
+
"[data-prepr-encoded]"
|
|
1061
|
+
);
|
|
1062
|
+
let target = null;
|
|
1063
|
+
for (const candidate of candidates) {
|
|
1064
|
+
if (candidate.getAttribute("data-prepr-field") !== field) continue;
|
|
1065
|
+
if (id && candidate.getAttribute("data-prepr-id") !== id) continue;
|
|
1066
|
+
target = candidate;
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
if (!target) {
|
|
1070
|
+
debug8.log("no element found for field", field);
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
target.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
1074
|
+
if (flashTimeout) clearTimeout(flashTimeout);
|
|
1075
|
+
document.querySelectorAll(".prepr-overlay-active").forEach((el) => el.classList.remove("prepr-overlay-active"));
|
|
1076
|
+
target.classList.add("prepr-overlay-active");
|
|
1077
|
+
flashTimeout = setTimeout(() => {
|
|
1078
|
+
target.classList.remove("prepr-overlay-active");
|
|
1079
|
+
flashTimeout = null;
|
|
1080
|
+
}, FLASH_DURATION_MS);
|
|
1081
|
+
return true;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1013
1084
|
// src/core/store.ts
|
|
1014
1085
|
var DEFAULT_STATE = {
|
|
1015
1086
|
locale: "en",
|
|
@@ -2122,7 +2193,7 @@ function definePreprToolbar() {
|
|
|
2122
2193
|
}
|
|
2123
2194
|
|
|
2124
2195
|
// src/core/create-preview.ts
|
|
2125
|
-
var
|
|
2196
|
+
var debug9 = createScopedLogger("create-preview");
|
|
2126
2197
|
var controllerStores = /* @__PURE__ */ new WeakMap();
|
|
2127
2198
|
function defaultNavigation() {
|
|
2128
2199
|
return {
|
|
@@ -2164,7 +2235,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2164
2235
|
const search = new URLSearchParams(window.location.search);
|
|
2165
2236
|
const hideBar = search.get(PARAM_HIDE_BAR) === "true";
|
|
2166
2237
|
if (hideBar) {
|
|
2167
|
-
|
|
2238
|
+
debug9.log(`${PARAM_HIDE_BAR}=true \u2014 no visible toolbar`);
|
|
2168
2239
|
}
|
|
2169
2240
|
const mountUi = (options?.ui ?? true) && !isIframe && !hideBar;
|
|
2170
2241
|
const locale = resolveLocale(options);
|
|
@@ -2200,18 +2271,17 @@ function createPreprPreview(opts = {}) {
|
|
|
2200
2271
|
tooltip: mountUi,
|
|
2201
2272
|
// In the editor, ask the parent to focus the field instead of opening a new
|
|
2202
2273
|
// tab. Standalone previews keep the window.open behaviour.
|
|
2203
|
-
onEdit: ({ href,
|
|
2274
|
+
onEdit: ({ href, id, field, locale: contentLocale }) => {
|
|
2204
2275
|
const safeHref = href ? safeEditUrl(href) : null;
|
|
2205
2276
|
if (href && !safeHref) {
|
|
2206
|
-
|
|
2277
|
+
debug9.warn("ignored edit request with unsupported href scheme");
|
|
2207
2278
|
return;
|
|
2208
2279
|
}
|
|
2209
2280
|
if (isIframe) {
|
|
2210
2281
|
sendPreprEvent("field_edit_requested", {
|
|
2211
|
-
href: safeHref ?? void 0,
|
|
2212
|
-
origin,
|
|
2213
2282
|
id,
|
|
2214
|
-
field
|
|
2283
|
+
field,
|
|
2284
|
+
locale: contentLocale
|
|
2215
2285
|
});
|
|
2216
2286
|
} else if (safeHref) {
|
|
2217
2287
|
window.open(safeHref, "_blank", "noopener,noreferrer");
|
|
@@ -2238,7 +2308,15 @@ function createPreprPreview(opts = {}) {
|
|
|
2238
2308
|
handleChange(before, state);
|
|
2239
2309
|
});
|
|
2240
2310
|
const bridge = createIframeBridge(store, {
|
|
2241
|
-
allowedEditorOrigins: options?.allowedEditorOrigins
|
|
2311
|
+
allowedEditorOrigins: options?.allowedEditorOrigins,
|
|
2312
|
+
// The editor selecting a field scrolls the matching element into view. The
|
|
2313
|
+
// lookup relies on the attributes the stega scan writes, so it finds
|
|
2314
|
+
// nothing until encoded content has been tagged.
|
|
2315
|
+
onScrollToField: ({ field, id }) => {
|
|
2316
|
+
if (!scrollToField({ field, id })) {
|
|
2317
|
+
debug9.log("no element on this page renders field", field);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2242
2320
|
});
|
|
2243
2321
|
sendPreprEvent(
|
|
2244
2322
|
"getScrollPosition",
|
|
@@ -2258,7 +2336,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2258
2336
|
bridge.stop();
|
|
2259
2337
|
}
|
|
2260
2338
|
el?.remove();
|
|
2261
|
-
|
|
2339
|
+
debug9.log("preview destroyed");
|
|
2262
2340
|
}
|
|
2263
2341
|
const controller = { destroy };
|
|
2264
2342
|
controllerStores.set(controller, store);
|
|
@@ -2266,7 +2344,7 @@ function createPreprPreview(opts = {}) {
|
|
|
2266
2344
|
}
|
|
2267
2345
|
|
|
2268
2346
|
// src/version.ts
|
|
2269
|
-
var VERSION = "0.
|
|
2347
|
+
var VERSION = "0.5.0-rc.1";
|
|
2270
2348
|
|
|
2271
2349
|
// src/core/pixel.ts
|
|
2272
2350
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|