@preprio/toolkit 0.6.0-alpha.6 → 0.6.0-alpha.8
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 +138 -52
- package/dist/astro/{chunk-MWRA3732.js → chunk-R2YPGDVU.js} +1 -1
- package/dist/astro/graphql.cjs +58 -10
- package/dist/astro/graphql.d.cts +33 -38
- package/dist/astro/graphql.d.ts +33 -38
- package/dist/astro/graphql.js +59 -11
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/{chunk-Y7DWVOOY.js → chunk-2QGUP7VQ.js} +1 -1
- package/dist/{chunk-NSQOGI5K.js → chunk-ATPB7GEC.js} +1 -1
- package/dist/{chunk-W6AVX6FI.js → chunk-OY7OKO6Q.js} +52 -5
- package/dist/{chunk-OQGEL4TV.js → chunk-T7ESBVBI.js} +1 -1
- package/dist/graphql/codegen.cjs +51 -4
- package/dist/graphql/codegen.js +3 -3
- package/dist/graphql.cjs +89 -10
- package/dist/graphql.d.cts +69 -39
- package/dist/graphql.d.ts +69 -39
- package/dist/graphql.js +38 -9
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/nextjs/{chunk-PIQF5ZI5.js → chunk-O2SBSBDG.js} +58 -53
- package/dist/nextjs/components.cjs +205 -236
- package/dist/nextjs/components.d.cts +27 -22
- package/dist/nextjs/components.d.ts +27 -22
- package/dist/nextjs/components.js +198 -231
- package/dist/nextjs/graphql.cjs +418 -508
- package/dist/nextjs/graphql.d.cts +131 -135
- package/dist/nextjs/graphql.d.ts +131 -135
- package/dist/nextjs/graphql.js +353 -455
- package/dist/nextjs/index.cjs +114 -54
- package/dist/nextjs/index.d.cts +59 -33
- package/dist/nextjs/index.d.ts +59 -33
- package/dist/nextjs/index.js +108 -5
- package/dist/nuxt/{chunk-PF6GVWHV.js → chunk-SX3MSVPK.js} +1 -1
- package/dist/nuxt/graphql.cjs +58 -10
- package/dist/nuxt/graphql.d.cts +33 -38
- package/dist/nuxt/graphql.d.ts +33 -38
- package/dist/nuxt/graphql.js +59 -11
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/react/components.cjs +1 -1
- package/dist/react/components.js +1 -1
- package/dist/sveltekit/{chunk-5K7HWMIF.js → chunk-UOASSHZO.js} +1 -1
- package/dist/sveltekit/graphql.cjs +58 -10
- package/dist/sveltekit/graphql.d.cts +33 -38
- package/dist/sveltekit/graphql.d.ts +33 -38
- package/dist/sveltekit/graphql.js +59 -11
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { NextResponse } from "next/server";
|
|
3
3
|
|
|
4
4
|
// src/version.ts
|
|
5
|
-
var VERSION = "0.6.0-alpha.
|
|
5
|
+
var VERSION = "0.6.0-alpha.8";
|
|
6
6
|
|
|
7
7
|
// src/core/constants.ts
|
|
8
8
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -426,55 +426,6 @@ function isPersonalizedResponse(source) {
|
|
|
426
426
|
return PERSONALIZED_VARY.test(headers2.get("vary") ?? "");
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
// src/nextjs/bucket.ts
|
|
430
|
-
var PREPR_BUCKET_COOKIE = "prepr_ab_bucket";
|
|
431
|
-
var isBucket = (value) => value === "A" || value === "B";
|
|
432
|
-
function setBucketCookie(request, response, bucket) {
|
|
433
|
-
response.cookies.set(PREPR_BUCKET_COOKIE, bucket, {
|
|
434
|
-
path: "/",
|
|
435
|
-
sameSite: "lax",
|
|
436
|
-
// Readable on purpose: PreprStack's inline switch reads it before first
|
|
437
|
-
// paint. It holds only "A" or "B".
|
|
438
|
-
httpOnly: false,
|
|
439
|
-
secure: request.nextUrl.protocol === "https:",
|
|
440
|
-
maxAge: 60 * 60 * 24 * 365
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
async function resolvePreprBucket(request, response, options) {
|
|
444
|
-
const stored = request.cookies.get(PREPR_BUCKET_COOKIE)?.value;
|
|
445
|
-
const forced = response.headers.get("x-middleware-request-prepr-abtesting") ?? request.cookies.get(COOKIE_VARIANT)?.value;
|
|
446
|
-
if (options.preview && isBucket(forced)) {
|
|
447
|
-
if (forced !== stored) setBucketCookie(request, response, forced);
|
|
448
|
-
return forced;
|
|
449
|
-
}
|
|
450
|
-
if (isBucket(stored)) return stored;
|
|
451
|
-
if (options.onlyIf) {
|
|
452
|
-
const needed = await Promise.resolve().then(options.onlyIf).catch(() => true);
|
|
453
|
-
if (!needed) return "A";
|
|
454
|
-
}
|
|
455
|
-
const customerId = request.cookies.get(COOKIE_UID)?.value ?? response.cookies.get(COOKIE_UID)?.value;
|
|
456
|
-
if (!customerId) return "A";
|
|
457
|
-
try {
|
|
458
|
-
const res = await fetch(options.url, {
|
|
459
|
-
method: "POST",
|
|
460
|
-
headers: {
|
|
461
|
-
"Content-Type": "application/json",
|
|
462
|
-
"Prepr-Customer-Id": customerId
|
|
463
|
-
},
|
|
464
|
-
body: JSON.stringify({ query: "{ __typename }" }),
|
|
465
|
-
cache: "no-store",
|
|
466
|
-
signal: AbortSignal.timeout(options.timeoutMs ?? 1500)
|
|
467
|
-
});
|
|
468
|
-
const bucket = res.headers.get("x-prepr-customer-bucket");
|
|
469
|
-
if (isBucket(bucket)) {
|
|
470
|
-
setBucketCookie(request, response, bucket);
|
|
471
|
-
return bucket;
|
|
472
|
-
}
|
|
473
|
-
} catch {
|
|
474
|
-
}
|
|
475
|
-
return "A";
|
|
476
|
-
}
|
|
477
|
-
|
|
478
429
|
// src/nextjs/draft.ts
|
|
479
430
|
import { cookies, draftMode } from "next/headers";
|
|
480
431
|
import { redirect } from "next/navigation";
|
|
@@ -525,6 +476,56 @@ function createPreprDraftRoute(options) {
|
|
|
525
476
|
};
|
|
526
477
|
}
|
|
527
478
|
|
|
479
|
+
// src/core/graphql/cache-tags.ts
|
|
480
|
+
var MAX_TAGS = 128;
|
|
481
|
+
var MAX_TAG_LENGTH = 256;
|
|
482
|
+
var PREPR_ANY_ITEM_TAG = "prepr:any";
|
|
483
|
+
var PREPR_SCHEMA_TAG = "prepr:schema";
|
|
484
|
+
var preprItemTag = (id) => `prepr:${id}`;
|
|
485
|
+
var NOT_ALPHANUMERIC = /[^a-z0-9]/g;
|
|
486
|
+
var preprModelTag = (model) => `prepr:model:${model.toLowerCase().replace(NOT_ALPHANUMERIC, "")}`;
|
|
487
|
+
function preprModelTagsFor(document, data, schema) {
|
|
488
|
+
const operation = document.definitions.find(
|
|
489
|
+
(definition) => definition.kind === "OperationDefinition" && definition.operation === "query"
|
|
490
|
+
);
|
|
491
|
+
const root = schema.types[schema.queryType];
|
|
492
|
+
if (!operation || !root) return [];
|
|
493
|
+
const models = (type) => {
|
|
494
|
+
const members = schema.types[type]?.possibleTypes ?? [];
|
|
495
|
+
return members.length > 0 ? members : [type];
|
|
496
|
+
};
|
|
497
|
+
const tags = /* @__PURE__ */ new Set();
|
|
498
|
+
for (const selection of operation.selectionSet.selections) {
|
|
499
|
+
if (selection.kind !== "Field") continue;
|
|
500
|
+
const type = root.fields[selection.name.value]?.type;
|
|
501
|
+
const info = type ? schema.types[type] : void 0;
|
|
502
|
+
if (!type || !info) continue;
|
|
503
|
+
const items = info.fields.items?.type;
|
|
504
|
+
const key = (selection.alias ?? selection.name).value;
|
|
505
|
+
const found = typeof data === "object" && data !== null && data[key] != null;
|
|
506
|
+
const affected = items ? models(items) : found ? [] : models(type);
|
|
507
|
+
for (const model of affected) tags.add(preprModelTag(model));
|
|
508
|
+
}
|
|
509
|
+
return [...tags];
|
|
510
|
+
}
|
|
511
|
+
function preprCacheTags(data) {
|
|
512
|
+
const tags = /* @__PURE__ */ new Set();
|
|
513
|
+
const stack = [data];
|
|
514
|
+
while (stack.length > 0) {
|
|
515
|
+
const value = stack.pop();
|
|
516
|
+
if (typeof value !== "object" || value === null) continue;
|
|
517
|
+
const id = value._id;
|
|
518
|
+
if (typeof id === "string" && id !== "") {
|
|
519
|
+
const tag = preprItemTag(id);
|
|
520
|
+
if (tag.length > MAX_TAG_LENGTH) return [PREPR_ANY_ITEM_TAG];
|
|
521
|
+
tags.add(tag);
|
|
522
|
+
if (tags.size > MAX_TAGS) return [PREPR_ANY_ITEM_TAG];
|
|
523
|
+
}
|
|
524
|
+
for (const child of Object.values(value)) stack.push(child);
|
|
525
|
+
}
|
|
526
|
+
return [...tags];
|
|
527
|
+
}
|
|
528
|
+
|
|
528
529
|
export {
|
|
529
530
|
createPreprMiddleware,
|
|
530
531
|
PreprError,
|
|
@@ -537,8 +538,12 @@ export {
|
|
|
537
538
|
getPreprHeaders,
|
|
538
539
|
getToolbarProps,
|
|
539
540
|
isPersonalizedResponse,
|
|
540
|
-
PREPR_BUCKET_COOKIE,
|
|
541
|
-
resolvePreprBucket,
|
|
542
541
|
preprDraftRedirect,
|
|
543
|
-
createPreprDraftRoute
|
|
542
|
+
createPreprDraftRoute,
|
|
543
|
+
PREPR_ANY_ITEM_TAG,
|
|
544
|
+
PREPR_SCHEMA_TAG,
|
|
545
|
+
preprItemTag,
|
|
546
|
+
preprModelTag,
|
|
547
|
+
preprModelTagsFor,
|
|
548
|
+
preprCacheTags
|
|
544
549
|
};
|
|
@@ -21,7 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/nextjs/components.ts
|
|
22
22
|
var components_exports = {};
|
|
23
23
|
__export(components_exports, {
|
|
24
|
-
|
|
24
|
+
PreprDecisionApplier: () => PreprDecisionApplier,
|
|
25
25
|
PreprPersonalizationSwitch: () => PreprPersonalizationSwitch,
|
|
26
26
|
PreprToolbar: () => PreprToolbar,
|
|
27
27
|
PreprTrackingPixel: () => PreprTrackingPixel,
|
|
@@ -458,11 +458,11 @@ function createStegaAutoClean(options) {
|
|
|
458
458
|
const settled = stripText ? info?.cleaned : info?.original;
|
|
459
459
|
if (info && textContent === settled) {
|
|
460
460
|
if (!info.decoded) return false;
|
|
461
|
-
const
|
|
462
|
-
if (!
|
|
461
|
+
const shown2 = resolveEditTarget(textNode);
|
|
462
|
+
if (!shown2) return false;
|
|
463
463
|
pendingHidden.delete(textNode);
|
|
464
|
-
if (
|
|
465
|
-
tagEncodedElement(
|
|
464
|
+
if (shown2.hasAttribute("data-prepr-encoded")) return false;
|
|
465
|
+
tagEncodedElement(shown2, info.decoded);
|
|
466
466
|
return true;
|
|
467
467
|
}
|
|
468
468
|
try {
|
|
@@ -1055,7 +1055,7 @@ var DEFAULT_STATE = {
|
|
|
1055
1055
|
};
|
|
1056
1056
|
function createToolbarStore(initial = {}) {
|
|
1057
1057
|
let state = { ...DEFAULT_STATE, ...initial };
|
|
1058
|
-
const
|
|
1058
|
+
const listeners2 = /* @__PURE__ */ new Set();
|
|
1059
1059
|
function get() {
|
|
1060
1060
|
return state;
|
|
1061
1061
|
}
|
|
@@ -1064,14 +1064,14 @@ function createToolbarStore(initial = {}) {
|
|
|
1064
1064
|
const hasChange = keys.some((key) => patch[key] !== state[key]);
|
|
1065
1065
|
if (!hasChange) return;
|
|
1066
1066
|
state = { ...state, ...patch };
|
|
1067
|
-
for (const listener of
|
|
1067
|
+
for (const listener of listeners2) {
|
|
1068
1068
|
listener(state);
|
|
1069
1069
|
}
|
|
1070
1070
|
}
|
|
1071
1071
|
function subscribe(fn) {
|
|
1072
|
-
|
|
1072
|
+
listeners2.add(fn);
|
|
1073
1073
|
return () => {
|
|
1074
|
-
|
|
1074
|
+
listeners2.delete(fn);
|
|
1075
1075
|
};
|
|
1076
1076
|
}
|
|
1077
1077
|
return { get, set, subscribe };
|
|
@@ -2316,204 +2316,106 @@ function isReactHydrated(text) {
|
|
|
2316
2316
|
return true;
|
|
2317
2317
|
}
|
|
2318
2318
|
|
|
2319
|
-
// src/
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
(raw ?? "").split("|").map((pair) => {
|
|
2344
|
-
const split = pair.lastIndexOf("~");
|
|
2345
|
-
const at = Number(split < 0 ? "" : pair.slice(split + 1));
|
|
2346
|
-
return {
|
|
2347
|
-
path: split < 0 ? pair : pair.slice(0, split),
|
|
2348
|
-
at: Number.isFinite(at) && at > 0 ? Math.floor(at) : 0
|
|
2349
|
-
};
|
|
2350
|
-
})
|
|
2351
|
-
);
|
|
2352
|
-
}
|
|
2353
|
-
|
|
2354
|
-
// src/core/refresh-scheduler.ts
|
|
2355
|
-
var VIEW_DELAYS_MS = [3e3, 1e4];
|
|
2356
|
-
var INTENT_MIN_AGE_MS = 2e3;
|
|
2357
|
-
var INTENT_EVENTS = ["pointerover", "focusin", "touchstart"];
|
|
2358
|
-
var LISTENER = { capture: true, passive: true };
|
|
2359
|
-
var COOKIE_PATTERN = new RegExp(`(?:^|; )${PREPR_REFRESH_COOKIE}=([^;]*)`);
|
|
2360
|
-
var UNSUPPORTED_KEY = "prepr_refresh_unsupported";
|
|
2361
|
-
function readEntries() {
|
|
2362
|
-
const match = document.cookie.match(COOKIE_PATTERN);
|
|
2363
|
-
try {
|
|
2364
|
-
return parseRefresh(match ? decodeURIComponent(match[1]) : void 0);
|
|
2365
|
-
} catch {
|
|
2366
|
-
return [];
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
function unsupported() {
|
|
2370
|
-
try {
|
|
2371
|
-
return sessionStorage.getItem(UNSUPPORTED_KEY) === "1";
|
|
2372
|
-
} catch {
|
|
2373
|
-
return false;
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
function createPreprRefreshScheduler(options = {}) {
|
|
2377
|
-
const freshFor = options.freshFor ?? 1e4;
|
|
2378
|
-
let timers = [];
|
|
2379
|
-
let inFlight = false;
|
|
2380
|
-
let stopped = unsupported();
|
|
2381
|
-
function refresh() {
|
|
2382
|
-
if (inFlight || stopped) return;
|
|
2383
|
-
const paths = readEntries().map((entry) => entry.path);
|
|
2384
|
-
if (paths.length === 0) return;
|
|
2385
|
-
inFlight = true;
|
|
2386
|
-
const controller = new AbortController();
|
|
2387
|
-
fetch(location.pathname, {
|
|
2388
|
-
headers: { [PREPR_REFRESH_HEADER]: paths.join("|") },
|
|
2389
|
-
cache: "no-store",
|
|
2390
|
-
credentials: "same-origin",
|
|
2391
|
-
signal: controller.signal
|
|
2392
|
-
}).then((response) => {
|
|
2393
|
-
if (response.status === 204) return;
|
|
2394
|
-
stopped = true;
|
|
2395
|
-
controller.abort();
|
|
2396
|
-
try {
|
|
2397
|
-
sessionStorage.setItem(UNSUPPORTED_KEY, "1");
|
|
2398
|
-
} catch {
|
|
2399
|
-
}
|
|
2400
|
-
}).catch(() => void 0).finally(() => {
|
|
2401
|
-
inFlight = false;
|
|
2319
|
+
// src/nextjs/decision-switch.ts
|
|
2320
|
+
function applyPreprDecisions(decision) {
|
|
2321
|
+
const state = window;
|
|
2322
|
+
const key = location.pathname + location.search;
|
|
2323
|
+
if (decision !== void 0) state.__preprDecision = { key, value: decision };
|
|
2324
|
+
const current = state.__preprDecision;
|
|
2325
|
+
if (!current || current.key !== key) return false;
|
|
2326
|
+
document.querySelectorAll("[data-prepr-decision]").forEach((marker) => {
|
|
2327
|
+
marker.setAttribute("data-prepr-decided", "");
|
|
2328
|
+
});
|
|
2329
|
+
const defaults = current.value === "*";
|
|
2330
|
+
const chosen = {};
|
|
2331
|
+
current.value.split("~").forEach((pair) => {
|
|
2332
|
+
const colon = pair.indexOf(":");
|
|
2333
|
+
if (colon > 0)
|
|
2334
|
+
chosen[pair.slice(0, colon)] = pair.slice(colon + 1).split("|");
|
|
2335
|
+
});
|
|
2336
|
+
document.querySelectorAll("[data-prepr-v]").forEach((element) => {
|
|
2337
|
+
const nested = element.hasAttribute("data-prepr-nested");
|
|
2338
|
+
const show = defaults ? element.hasAttribute("data-prepr-default") : (element.getAttribute("data-prepr-v") || "").split(" ").every((token) => {
|
|
2339
|
+
const colon = token.indexOf(":");
|
|
2340
|
+
const variant = token.slice(colon + 1);
|
|
2341
|
+
const variants = chosen[token.slice(0, colon)];
|
|
2342
|
+
return !!variants && (nested ? variants[0] === variant : variants.indexOf(variant) >= 0);
|
|
2402
2343
|
});
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2344
|
+
if (show) element.setAttribute("data-prepr-show", "");
|
|
2345
|
+
else element.removeAttribute("data-prepr-show");
|
|
2346
|
+
});
|
|
2347
|
+
return true;
|
|
2348
|
+
}
|
|
2349
|
+
function requestPreprDecision(key, options = {}) {
|
|
2350
|
+
const fresh = 1e4;
|
|
2351
|
+
const keep = 18e5;
|
|
2352
|
+
const keepStatic = 36e5;
|
|
2353
|
+
const state = window;
|
|
2354
|
+
const asking = state.__preprAsking = state.__preprAsking || {};
|
|
2355
|
+
const read = () => {
|
|
2408
2356
|
try {
|
|
2409
|
-
|
|
2357
|
+
const all = JSON.parse(sessionStorage.getItem("prepr_decisions") || "{}");
|
|
2358
|
+
return all && typeof all === "object" ? all : {};
|
|
2410
2359
|
} catch {
|
|
2411
|
-
return;
|
|
2412
|
-
}
|
|
2413
|
-
if (url.origin !== location.origin) return;
|
|
2414
|
-
const entry = readEntries().find((e2) => e2.path === url.pathname);
|
|
2415
|
-
if (entry && !isFresh(entry.at, INTENT_MIN_AGE_MS)) refresh();
|
|
2416
|
-
}
|
|
2417
|
-
function onVisibility() {
|
|
2418
|
-
if (document.visibilityState === "visible" && readEntries().some((entry) => !isFresh(entry.at, freshFor))) {
|
|
2419
|
-
refresh();
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
for (const type of INTENT_EVENTS) {
|
|
2423
|
-
document.addEventListener(type, onIntent, LISTENER);
|
|
2424
|
-
}
|
|
2425
|
-
document.addEventListener("visibilitychange", onVisibility, {
|
|
2426
|
-
passive: true
|
|
2427
|
-
});
|
|
2428
|
-
return {
|
|
2429
|
-
view() {
|
|
2430
|
-
timers.forEach(clearTimeout);
|
|
2431
|
-
timers = VIEW_DELAYS_MS.map((delay) => setTimeout(refresh, delay));
|
|
2432
|
-
},
|
|
2433
|
-
stop() {
|
|
2434
|
-
timers.forEach(clearTimeout);
|
|
2435
|
-
timers = [];
|
|
2436
|
-
for (const type of INTENT_EVENTS) {
|
|
2437
|
-
document.removeEventListener(type, onIntent, LISTENER);
|
|
2438
|
-
}
|
|
2439
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
2360
|
+
return {};
|
|
2440
2361
|
}
|
|
2441
2362
|
};
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2363
|
+
const ask = () => {
|
|
2364
|
+
if (!asking[key]) {
|
|
2365
|
+
asking[key] = fetch(key, {
|
|
2366
|
+
headers: { "Prepr-Decide": "1" },
|
|
2367
|
+
cache: "no-store",
|
|
2368
|
+
credentials: "same-origin",
|
|
2369
|
+
// The proxy gives up on Prepr after its own `timeoutMs`; this only
|
|
2370
|
+
// covers a proxy that never answers.
|
|
2371
|
+
signal: AbortSignal.timeout ? AbortSignal.timeout(6e3) : void 0
|
|
2372
|
+
}).then((response) => response.ok ? response.text() : "*").catch(() => "*").then((answer) => {
|
|
2373
|
+
delete asking[key];
|
|
2374
|
+
try {
|
|
2375
|
+
const all = read();
|
|
2376
|
+
const at = Date.now();
|
|
2377
|
+
Object.keys(all).forEach((stored) => {
|
|
2378
|
+
const entry = all[stored];
|
|
2379
|
+
if (!(entry && typeof entry.at === "number" && at - entry.at < keepStatic))
|
|
2380
|
+
delete all[stored];
|
|
2381
|
+
});
|
|
2382
|
+
const kept = all[key];
|
|
2383
|
+
if (answer !== "*" || !kept || kept.value === "*")
|
|
2384
|
+
all[key] = { value: answer, at };
|
|
2385
|
+
sessionStorage.setItem("prepr_decisions", JSON.stringify(all));
|
|
2386
|
+
} catch {
|
|
2387
|
+
}
|
|
2388
|
+
return answer;
|
|
2389
|
+
});
|
|
2457
2390
|
}
|
|
2458
|
-
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2391
|
+
return asking[key];
|
|
2392
|
+
};
|
|
2393
|
+
const last = read()[key];
|
|
2394
|
+
const age = last && typeof last.at === "number" ? Date.now() - last.at : -1;
|
|
2395
|
+
const value = last && typeof last.value === "string" ? last.value : null;
|
|
2396
|
+
if (value !== null && !(value === "" && options.personalized) && age >= 0 && age < (value === "*" ? fresh : value === "" ? keepStatic : keep)) {
|
|
2397
|
+
if (value !== "" && age >= fresh) {
|
|
2398
|
+
ask().then((answer) => {
|
|
2399
|
+
if (answer !== "*" && answer !== value && options.onChange)
|
|
2400
|
+
options.onChange(answer);
|
|
2401
|
+
});
|
|
2463
2402
|
}
|
|
2464
|
-
|
|
2465
|
-
}
|
|
2466
|
-
}
|
|
2467
|
-
function applyPreprDecisions(view) {
|
|
2468
|
-
const viewState = window;
|
|
2469
|
-
const current = view === void 0 ? location.pathname + location.search : view;
|
|
2470
|
-
if (viewState.__preprDecisionsView === current) return;
|
|
2471
|
-
viewState.__preprDecisionsView = current;
|
|
2472
|
-
const match = document.cookie.match(/(?:^|; )prepr_decisions=([^;]*)/);
|
|
2473
|
-
let raw;
|
|
2474
|
-
try {
|
|
2475
|
-
raw = match ? decodeURIComponent(match[1]) : "";
|
|
2476
|
-
} catch {
|
|
2477
|
-
raw = "";
|
|
2403
|
+
return { result: value, value: Promise.resolve(value) };
|
|
2478
2404
|
}
|
|
2479
|
-
const
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
raw.split("~").forEach((pair) => {
|
|
2485
|
-
const at = pair.indexOf(":");
|
|
2486
|
-
const group = pair.slice(0, at);
|
|
2487
|
-
if (at < 1 || !id.test(group)) return;
|
|
2488
|
-
const selector = '[data-prepr-group="' + group + '"]';
|
|
2489
|
-
css += selector + "{display:none!important}";
|
|
2490
|
-
pair.slice(at + 1).split("|").forEach((variant) => {
|
|
2491
|
-
if (id.test(variant)) {
|
|
2492
|
-
css += selector + '[data-prepr-variant="' + variant + '"]{display:contents!important}';
|
|
2493
|
-
}
|
|
2494
|
-
});
|
|
2405
|
+
const pending = {
|
|
2406
|
+
value: ask()
|
|
2407
|
+
};
|
|
2408
|
+
pending.value.then((answer) => {
|
|
2409
|
+
pending.result = answer;
|
|
2495
2410
|
});
|
|
2496
|
-
|
|
2497
|
-
if (!state.__preprDecisionSheet) {
|
|
2498
|
-
const sheet = new CSSStyleSheet();
|
|
2499
|
-
document.adoptedStyleSheets = document.adoptedStyleSheets.concat(sheet);
|
|
2500
|
-
state.__preprDecisionSheet = sheet;
|
|
2501
|
-
}
|
|
2502
|
-
state.__preprDecisionSheet.replaceSync(css);
|
|
2503
|
-
} catch {
|
|
2504
|
-
if (!state.__preprDecisionSheet) {
|
|
2505
|
-
state.__preprDecisionSheet = document.createElement("style");
|
|
2506
|
-
document.head.appendChild(state.__preprDecisionSheet);
|
|
2507
|
-
}
|
|
2508
|
-
state.__preprDecisionSheet.textContent = css;
|
|
2509
|
-
}
|
|
2411
|
+
return pending;
|
|
2510
2412
|
}
|
|
2511
2413
|
|
|
2512
2414
|
// src/react/components.ts
|
|
2513
2415
|
var import_react = require("react");
|
|
2514
2416
|
|
|
2515
2417
|
// src/version.ts
|
|
2516
|
-
var VERSION = "0.6.0-alpha.
|
|
2418
|
+
var VERSION = "0.6.0-alpha.8";
|
|
2517
2419
|
|
|
2518
2420
|
// src/core/pixel.ts
|
|
2519
2421
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|
|
@@ -2588,62 +2490,124 @@ function PreprToolbar({
|
|
|
2588
2490
|
}, []);
|
|
2589
2491
|
return null;
|
|
2590
2492
|
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2493
|
+
var shown = /* @__PURE__ */ new Map();
|
|
2494
|
+
var historyStep = false;
|
|
2495
|
+
var onPopState = () => {
|
|
2496
|
+
historyStep = true;
|
|
2497
|
+
};
|
|
2498
|
+
function requestDecision(key, personalized = false) {
|
|
2499
|
+
return requestPreprDecision(key, {
|
|
2500
|
+
personalized,
|
|
2501
|
+
onChange: (value) => {
|
|
2502
|
+
if (location.pathname + location.search !== key) return;
|
|
2503
|
+
applyPreprDecisions(value);
|
|
2504
|
+
shown.set(key, value);
|
|
2505
|
+
}
|
|
2594
2506
|
});
|
|
2507
|
+
}
|
|
2508
|
+
function linkTarget(event) {
|
|
2509
|
+
const anchor = event.target?.closest?.("a[href]");
|
|
2510
|
+
if (!(anchor instanceof HTMLAnchorElement)) return null;
|
|
2511
|
+
if (anchor.target && anchor.target !== "_self" || anchor.hasAttribute("download")) {
|
|
2512
|
+
return null;
|
|
2513
|
+
}
|
|
2514
|
+
const url = new URL(anchor.href, location.href);
|
|
2515
|
+
const key = url.pathname + url.search;
|
|
2516
|
+
if (url.origin !== location.origin || key === location.pathname + location.search) {
|
|
2517
|
+
return null;
|
|
2518
|
+
}
|
|
2519
|
+
return key;
|
|
2520
|
+
}
|
|
2521
|
+
var HOVER_DELAY_MS = 65;
|
|
2522
|
+
var hovering = null;
|
|
2523
|
+
function onPointerOver(event) {
|
|
2524
|
+
if (event.pointerType !== "mouse") return;
|
|
2525
|
+
const key = linkTarget(event);
|
|
2526
|
+
if (hovering?.key === key) return;
|
|
2527
|
+
if (hovering) clearTimeout(hovering.timer);
|
|
2528
|
+
hovering = key ? { key, timer: setTimeout(() => requestDecision(key), HOVER_DELAY_MS) } : null;
|
|
2529
|
+
}
|
|
2530
|
+
function onPointerDown(event) {
|
|
2531
|
+
if (event.button !== 0) return;
|
|
2532
|
+
const key = linkTarget(event);
|
|
2533
|
+
if (key) requestDecision(key);
|
|
2534
|
+
}
|
|
2535
|
+
var listeners = 0;
|
|
2536
|
+
function useDecisionRequests() {
|
|
2537
|
+
(0, import_react2.useEffect)(() => {
|
|
2538
|
+
if (listeners++ === 0) {
|
|
2539
|
+
window.addEventListener("pointerover", onPointerOver, { passive: true });
|
|
2540
|
+
window.addEventListener("pointerdown", onPointerDown, {
|
|
2541
|
+
capture: true,
|
|
2542
|
+
passive: true
|
|
2543
|
+
});
|
|
2544
|
+
window.addEventListener("popstate", onPopState);
|
|
2545
|
+
}
|
|
2546
|
+
return () => {
|
|
2547
|
+
if (--listeners === 0) {
|
|
2548
|
+
window.removeEventListener("pointerover", onPointerOver);
|
|
2549
|
+
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
2550
|
+
window.removeEventListener("popstate", onPopState);
|
|
2551
|
+
}
|
|
2552
|
+
};
|
|
2553
|
+
}, []);
|
|
2554
|
+
}
|
|
2555
|
+
function PreprPersonalizationSwitch() {
|
|
2556
|
+
useDecisionRequests();
|
|
2595
2557
|
return null;
|
|
2596
2558
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
refresh = true,
|
|
2600
|
-
freshFor
|
|
2601
|
-
}) {
|
|
2602
|
-
const [scheduler, setScheduler] = (0, import_react2.useState)(
|
|
2603
|
-
null
|
|
2604
|
-
);
|
|
2605
|
-
const viewUrl = (0, import_react2.useRef)(null);
|
|
2559
|
+
function PreprDecisionApplier() {
|
|
2560
|
+
useDecisionRequests();
|
|
2606
2561
|
(0, import_react2.useLayoutEffect)(() => {
|
|
2607
|
-
const
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2562
|
+
const key = location.pathname + location.search;
|
|
2563
|
+
const remember = () => {
|
|
2564
|
+
const state = window.__preprDecision;
|
|
2565
|
+
if (state) shown.set(key, state.value);
|
|
2566
|
+
};
|
|
2567
|
+
const previous = historyStep ? shown.get(key) : void 0;
|
|
2568
|
+
historyStep = false;
|
|
2569
|
+
if (applyPreprDecisions(previous)) {
|
|
2570
|
+
remember();
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
const pending = requestDecision(key, true);
|
|
2574
|
+
if (pending.result !== void 0) {
|
|
2575
|
+
applyPreprDecisions(pending.result);
|
|
2576
|
+
remember();
|
|
2577
|
+
return;
|
|
2578
|
+
}
|
|
2579
|
+
let live = true;
|
|
2580
|
+
void pending.value.then((value) => {
|
|
2581
|
+
if (live && location.pathname + location.search === key) {
|
|
2582
|
+
applyPreprDecisions(value);
|
|
2583
|
+
remember();
|
|
2584
|
+
}
|
|
2585
|
+
});
|
|
2616
2586
|
return () => {
|
|
2617
|
-
|
|
2618
|
-
setScheduler(null);
|
|
2587
|
+
live = false;
|
|
2619
2588
|
};
|
|
2620
|
-
}
|
|
2621
|
-
return scheduler ? (0, import_react2.createElement)(
|
|
2622
|
-
import_react2.Suspense,
|
|
2623
|
-
{ fallback: null },
|
|
2624
|
-
(0, import_react2.createElement)(ViewCounter, { scheduler })
|
|
2625
|
-
) : null;
|
|
2626
|
-
}
|
|
2627
|
-
function ViewCounter({
|
|
2628
|
-
scheduler
|
|
2629
|
-
}) {
|
|
2630
|
-
const pathname = (0, import_navigation.usePathname)();
|
|
2631
|
-
(0, import_react2.useEffect)(() => {
|
|
2632
|
-
scheduler.view();
|
|
2633
|
-
}, [pathname, scheduler]);
|
|
2589
|
+
});
|
|
2634
2590
|
return null;
|
|
2635
2591
|
}
|
|
2636
2592
|
var VARIANT_KEY_ATTRIBUTE = "data-prepr-variant-key";
|
|
2637
2593
|
function PreprVariantTracking({
|
|
2638
2594
|
variantKeys,
|
|
2639
|
-
ab,
|
|
2640
2595
|
children
|
|
2641
2596
|
}) {
|
|
2642
2597
|
const ref = (0, import_react2.useRef)(null);
|
|
2643
2598
|
const keys = variantKeys.join(" ");
|
|
2644
2599
|
(0, import_react2.useLayoutEffect)(() => {
|
|
2645
2600
|
let tagged = [];
|
|
2646
|
-
const
|
|
2601
|
+
const wrapper = ref.current?.closest("[data-prepr-v]");
|
|
2602
|
+
const shown2 = () => !wrapper || wrapper.hasAttribute("data-prepr-show");
|
|
2603
|
+
const untag = () => {
|
|
2604
|
+
for (const [element] of tagged)
|
|
2605
|
+
element.removeAttribute(VARIANT_KEY_ATTRIBUTE);
|
|
2606
|
+
tagged = [];
|
|
2607
|
+
};
|
|
2608
|
+
const tag = () => {
|
|
2609
|
+
if (!shown2()) return untag();
|
|
2610
|
+
if (tagged.length > 0) return;
|
|
2647
2611
|
const elements = [...ref.current?.children ?? []];
|
|
2648
2612
|
const list = keys.split(" ");
|
|
2649
2613
|
const pairs = elements.length === list.length ? elements.map((element, i2) => [element, list[i2]]) : elements.slice(0, 1).map((element) => [element, list[0]]);
|
|
@@ -2652,23 +2616,28 @@ function PreprVariantTracking({
|
|
|
2652
2616
|
element.setAttribute(VARIANT_KEY_ATTRIBUTE, key);
|
|
2653
2617
|
return true;
|
|
2654
2618
|
});
|
|
2619
|
+
};
|
|
2620
|
+
const timer = setTimeout(tag);
|
|
2621
|
+
const observer = wrapper && new MutationObserver(tag);
|
|
2622
|
+
observer?.observe(wrapper, {
|
|
2623
|
+
attributes: true,
|
|
2624
|
+
attributeFilter: ["data-prepr-show"]
|
|
2655
2625
|
});
|
|
2656
2626
|
return () => {
|
|
2657
2627
|
clearTimeout(timer);
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
}
|
|
2628
|
+
observer?.disconnect();
|
|
2629
|
+
untag();
|
|
2661
2630
|
};
|
|
2662
2631
|
}, [keys]);
|
|
2663
2632
|
return (0, import_react2.createElement)(
|
|
2664
2633
|
"div",
|
|
2665
|
-
|
|
2634
|
+
{ ref, style: { display: "contents" } },
|
|
2666
2635
|
children
|
|
2667
2636
|
);
|
|
2668
2637
|
}
|
|
2669
2638
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2670
2639
|
0 && (module.exports = {
|
|
2671
|
-
|
|
2640
|
+
PreprDecisionApplier,
|
|
2672
2641
|
PreprPersonalizationSwitch,
|
|
2673
2642
|
PreprToolbar,
|
|
2674
2643
|
PreprTrackingPixel,
|