@preprio/toolkit 0.6.0-alpha.7 → 0.6.0-alpha.9
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 +5 -5
- package/dist/astro/{chunk-3EXK2LHI.js → chunk-UN4JADNU.js} +1 -1
- package/dist/astro/graphql.js +1 -1
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/{chunk-VQIPTUN4.js → chunk-5QIWVDP2.js} +1 -1
- package/dist/{chunk-U7TRFVK7.js → chunk-J66UOCK6.js} +1 -1
- package/dist/{chunk-3QGWCYTL.js → chunk-WQBKQG4R.js} +1 -1
- package/dist/{chunk-PFJO4TYL.js → chunk-XL4Y7FGW.js} +1 -1
- package/dist/graphql/codegen.js +3 -3
- package/dist/graphql.js +3 -3
- 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-CZK7SMBD.js → chunk-CMV6ZP6E.js} +1 -1
- package/dist/nextjs/components.cjs +128 -67
- package/dist/nextjs/components.d.cts +14 -13
- package/dist/nextjs/components.d.ts +14 -13
- package/dist/nextjs/components.js +129 -68
- package/dist/nextjs/graphql.cjs +99 -27
- package/dist/nextjs/graphql.d.cts +5 -5
- package/dist/nextjs/graphql.d.ts +5 -5
- package/dist/nextjs/graphql.js +99 -27
- package/dist/nextjs/index.cjs +1 -1
- package/dist/nextjs/index.d.cts +9 -7
- package/dist/nextjs/index.d.ts +9 -7
- package/dist/nextjs/index.js +1 -1
- package/dist/nuxt/{chunk-JL33ENCM.js → chunk-XWOABVMW.js} +1 -1
- package/dist/nuxt/graphql.js +1 -1
- 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-S7S276V7.js → chunk-3S5RA6G5.js} +1 -1
- package/dist/sveltekit/graphql.js +1 -1
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -384,14 +384,14 @@ A/B tests go through the same decision as segment groups: both variants are in t
|
|
|
384
384
|
|
|
385
385
|
##### How each visitor gets their variant
|
|
386
386
|
|
|
387
|
-
Every page view is decided. Nothing is reused from a prefetch, the router cache or another page's view; the only
|
|
387
|
+
Every page view is decided. Nothing is reused from a prefetch, the router cache or another page's view; the browser only reuses a decision this tab already got for the same URL (see **Reuse** below).
|
|
388
388
|
|
|
389
389
|
- **Page loads.** The page is the same for every visitor and is sent at once, from the cache. An inline script at the start of each `PreprStack` asks the proxy for this view's decision as soon as it is parsed, so Prepr answers while the rest of the page, its styles and scripts (the tracking pixel included) still load. The personalized sections show the visitor's variant when the answer arrives; everything else never waits for it.
|
|
390
|
-
- **Client-side navigations.** When the visitor
|
|
390
|
+
- **Client-side navigations.** When the visitor hovers over a link (or presses it, on touch devices), `PreprPersonalizationSwitch` asks the proxy for the target page's decision. Clicks are never held: when the answer is in by the click, which hovering mostly ensures, the new page paints with the visitor's variants; otherwise its personalized sections show when the answer arrives. Prefetches still bring the page itself; only the decision is fetched.
|
|
391
391
|
- **Never the default first.** Until a view's decision is in, its personalized sections are not shown: the default variant keeps its space, invisible, so the page does not move when the visitor's variant appears (only by any difference in height). The default variant only shows when it is the decision: for visitors in none of the segments, for requests `onlyIf` skips, and when Prepr does not answer within `timeoutMs` (default 3000). Navigations started from code ask for a decision when the page opens; the personalized sections appear when it arrives.
|
|
392
|
-
- **
|
|
392
|
+
- **Reuse.** Back and Forward show a page as this tab last showed it, at once, without asking Prepr. Any other view of a URL this tab got a decision for (kept in `sessionStorage`) shows it at once too: under 10 seconds old without asking again, since Prepr needs a few seconds to process a visitor's activity anyway; up to 30 minutes old while a new decision is asked for in the background. When that one differs, it changes only the sections still below the screen; a section the visitor can see, or has scrolled past, keeps its variant for that view, so nothing they are reading is swapped or moves under them. The next view shows the new decision. A page without personalization answers with no groups, which is trusted for an hour with no background check, so links to it cost nothing; when that page renders personalization by then (published since), it asks at once. A URL with other UTM parameters is another view; a failed answer is kept for 10 seconds and never replaces a real one.
|
|
393
393
|
- **"Right" means what Prepr knows when the visitor clicks.** Prepr assigns segments from the visitor's tracked activity. If it has not yet processed the pixel event of the previous page view, the decision cannot include it, and the visitor sees that segment from a later page view.
|
|
394
|
-
- **Costs.** The page carries the HTML of every variant, and an item with groups nested inside it once per combination of their variants. `render` gets `defaultVariant`: give `priority` images only to the default variant and `loading="lazy"` to the others, or the browser downloads every variant's hero image. Every page
|
|
394
|
+
- **Costs.** The page carries the HTML of every variant, and an item with groups nested inside it once per combination of their variants. `render` gets `defaultVariant`: give `priority` images only to the default variant and `loading="lazy"` to the others, or the browser downloads every variant's hero image. Every page load with personalization, and every link hovered or pressed (also a press that turns into a scroll), is at most one decision request when this tab has no fresh decision for that URL, answered from Prepr's cache when other visitors had the same answer.
|
|
395
395
|
- Without JavaScript, visitors see the default variants.
|
|
396
396
|
|
|
397
397
|
##### Deploying
|
|
@@ -1054,7 +1054,7 @@ The toolbar. Takes the props returned by `getToolbarProps`, and renders nothing
|
|
|
1054
1054
|
|
|
1055
1055
|
#### `PreprPersonalizationSwitch`
|
|
1056
1056
|
|
|
1057
|
-
From `@preprio/toolkit/nextjs`.
|
|
1057
|
+
From `@preprio/toolkit/nextjs`. Gets each client-side navigation's decision in before the click: when the visitor hovers over a same-site link (or presses it, on touch devices), it asks `createPreprProxy` for the target page's decision. Clicks are never held (see [How each visitor gets their variant](#how-each-visitor-gets-their-variant)). Mount it once in the root layout, so links on pages without a `PreprStack` are covered too. Links to other sites and links that open a new tab or download are left alone. The decision requests are answered by `createPreprProxy` only. Takes no props and renders nothing.
|
|
1058
1058
|
|
|
1059
1059
|
#### `PreprPreview`
|
|
1060
1060
|
|
package/dist/astro/graphql.js
CHANGED
package/dist/astro/index.cjs
CHANGED
package/dist/astro/index.js
CHANGED
package/dist/graphql/codegen.js
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
toDecisionQuery,
|
|
3
3
|
toSchemaInfo,
|
|
4
4
|
toVariantsQuery
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-XL4Y7FGW.js";
|
|
6
|
+
import "../chunk-WQBKQG4R.js";
|
|
7
|
+
import "../chunk-5QIWVDP2.js";
|
|
8
8
|
|
|
9
9
|
// src/codegen/index.ts
|
|
10
10
|
function typeRef(type) {
|
package/dist/graphql.js
CHANGED
|
@@ -21,12 +21,12 @@ import {
|
|
|
21
21
|
toSchemaInfo,
|
|
22
22
|
toVariantsDocument,
|
|
23
23
|
toVariantsQuery
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-XL4Y7FGW.js";
|
|
25
25
|
import {
|
|
26
26
|
PreprError,
|
|
27
27
|
validatePreprToken
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-WQBKQG4R.js";
|
|
29
|
+
import "./chunk-5QIWVDP2.js";
|
|
30
30
|
|
|
31
31
|
// src/core/graphql/cache-tags.ts
|
|
32
32
|
var MAX_TAGS = 128;
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
|
@@ -7,7 +7,7 @@ export { P as PreprPixelConfig, l as loadTrackingPixel, s as setTrackingParam, t
|
|
|
7
7
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
8
8
|
* core can import it without cycling through the barrel.
|
|
9
9
|
*/
|
|
10
|
-
declare const VERSION = "0.6.0-alpha.
|
|
10
|
+
declare const VERSION = "0.6.0-alpha.9";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { P as PreprPixelConfig, l as loadTrackingPixel, s as setTrackingParam, t
|
|
|
7
7
|
* Package version; must match package.json. Lives in its own leaf module so
|
|
8
8
|
* core can import it without cycling through the barrel.
|
|
9
9
|
*/
|
|
10
|
-
declare const VERSION = "0.6.0-alpha.
|
|
10
|
+
declare const VERSION = "0.6.0-alpha.9";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Resolve a `PreprFeatures` bag to plain booleans, defaulting every omitted key
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
loadTrackingPixel,
|
|
16
16
|
setTrackingParam,
|
|
17
17
|
trackEvent
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-J66UOCK6.js";
|
|
19
19
|
import {
|
|
20
20
|
isPersonalizedResponse
|
|
21
21
|
} from "./chunk-3NCEVJJ3.js";
|
|
@@ -32,11 +32,11 @@ import {
|
|
|
32
32
|
getPreprUUIDFromHeaders,
|
|
33
33
|
getToolbarPropsFromHeaders,
|
|
34
34
|
validatePreprToken
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-WQBKQG4R.js";
|
|
36
36
|
import {
|
|
37
37
|
VERSION,
|
|
38
38
|
resolveFeatures
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-5QIWVDP2.js";
|
|
40
40
|
|
|
41
41
|
// src/core/middleware.ts
|
|
42
42
|
var UTM_PARAMS = [
|
|
@@ -2317,10 +2317,34 @@ function isReactHydrated(text) {
|
|
|
2317
2317
|
}
|
|
2318
2318
|
|
|
2319
2319
|
// src/nextjs/decision-switch.ts
|
|
2320
|
-
function applyPreprDecisions(decision) {
|
|
2320
|
+
function applyPreprDecisions(decision, options = {}) {
|
|
2321
2321
|
const state = window;
|
|
2322
2322
|
const key = location.pathname + location.search;
|
|
2323
|
-
|
|
2323
|
+
const previous = state.__preprDecision;
|
|
2324
|
+
let value = decision;
|
|
2325
|
+
if (value !== void 0 && value !== "*" && options.refresh && previous && previous.key === key && previous.value !== "*") {
|
|
2326
|
+
const pairs = (from) => {
|
|
2327
|
+
const out = {};
|
|
2328
|
+
from.split("~").forEach((pair) => {
|
|
2329
|
+
const colon = pair.indexOf(":");
|
|
2330
|
+
if (colon > 0) out[pair.slice(0, colon)] = pair;
|
|
2331
|
+
});
|
|
2332
|
+
return out;
|
|
2333
|
+
};
|
|
2334
|
+
const before = pairs(previous.value);
|
|
2335
|
+
const after = pairs(value);
|
|
2336
|
+
document.querySelectorAll("[data-prepr-v][data-prepr-show]").forEach((element) => {
|
|
2337
|
+
const range = document.createRange();
|
|
2338
|
+
range.selectNodeContents(element);
|
|
2339
|
+
if (range.getBoundingClientRect().top >= window.innerHeight) return;
|
|
2340
|
+
(element.getAttribute("data-prepr-v") || "").split(" ").forEach((token) => {
|
|
2341
|
+
const group = token.slice(0, token.indexOf(":"));
|
|
2342
|
+
if (before[group]) after[group] = before[group];
|
|
2343
|
+
});
|
|
2344
|
+
});
|
|
2345
|
+
value = Object.keys(after).map((group) => after[group]).join("~");
|
|
2346
|
+
}
|
|
2347
|
+
if (value !== void 0) state.__preprDecision = { key, value };
|
|
2324
2348
|
const current = state.__preprDecision;
|
|
2325
2349
|
if (!current || current.key !== key) return false;
|
|
2326
2350
|
document.querySelectorAll("[data-prepr-decision]").forEach((marker) => {
|
|
@@ -2346,12 +2370,76 @@ function applyPreprDecisions(decision) {
|
|
|
2346
2370
|
});
|
|
2347
2371
|
return true;
|
|
2348
2372
|
}
|
|
2373
|
+
function requestPreprDecision(key, options = {}) {
|
|
2374
|
+
const fresh = 1e4;
|
|
2375
|
+
const keep = 18e5;
|
|
2376
|
+
const keepStatic = 36e5;
|
|
2377
|
+
const state = window;
|
|
2378
|
+
const asking = state.__preprAsking = state.__preprAsking || {};
|
|
2379
|
+
const read = () => {
|
|
2380
|
+
try {
|
|
2381
|
+
const all = JSON.parse(sessionStorage.getItem("prepr_decisions") || "{}");
|
|
2382
|
+
return all && typeof all === "object" ? all : {};
|
|
2383
|
+
} catch {
|
|
2384
|
+
return {};
|
|
2385
|
+
}
|
|
2386
|
+
};
|
|
2387
|
+
const ask = () => {
|
|
2388
|
+
if (!asking[key]) {
|
|
2389
|
+
asking[key] = fetch(key, {
|
|
2390
|
+
headers: { "Prepr-Decide": "1" },
|
|
2391
|
+
cache: "no-store",
|
|
2392
|
+
credentials: "same-origin",
|
|
2393
|
+
// The proxy gives up on Prepr after its own `timeoutMs`; this only
|
|
2394
|
+
// covers a proxy that never answers.
|
|
2395
|
+
signal: AbortSignal.timeout ? AbortSignal.timeout(6e3) : void 0
|
|
2396
|
+
}).then((response) => response.ok ? response.text() : "*").catch(() => "*").then((answer) => {
|
|
2397
|
+
delete asking[key];
|
|
2398
|
+
try {
|
|
2399
|
+
const all = read();
|
|
2400
|
+
const at = Date.now();
|
|
2401
|
+
Object.keys(all).forEach((stored) => {
|
|
2402
|
+
const entry = all[stored];
|
|
2403
|
+
if (!(entry && typeof entry.at === "number" && at - entry.at < keepStatic))
|
|
2404
|
+
delete all[stored];
|
|
2405
|
+
});
|
|
2406
|
+
const kept = all[key];
|
|
2407
|
+
if (answer !== "*" || !kept || kept.value === "*")
|
|
2408
|
+
all[key] = { value: answer, at };
|
|
2409
|
+
sessionStorage.setItem("prepr_decisions", JSON.stringify(all));
|
|
2410
|
+
} catch {
|
|
2411
|
+
}
|
|
2412
|
+
return answer;
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
return asking[key];
|
|
2416
|
+
};
|
|
2417
|
+
const last = read()[key];
|
|
2418
|
+
const age = last && typeof last.at === "number" ? Date.now() - last.at : -1;
|
|
2419
|
+
const value = last && typeof last.value === "string" ? last.value : null;
|
|
2420
|
+
if (value !== null && !(value === "" && options.personalized) && age >= 0 && age < (value === "*" ? fresh : value === "" ? keepStatic : keep)) {
|
|
2421
|
+
if (value !== "" && age >= fresh) {
|
|
2422
|
+
ask().then((answer) => {
|
|
2423
|
+
if (answer !== "*" && answer !== value && options.onChange)
|
|
2424
|
+
options.onChange(answer);
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
return { result: value, value: Promise.resolve(value) };
|
|
2428
|
+
}
|
|
2429
|
+
const pending = {
|
|
2430
|
+
value: ask()
|
|
2431
|
+
};
|
|
2432
|
+
pending.value.then((answer) => {
|
|
2433
|
+
pending.result = answer;
|
|
2434
|
+
});
|
|
2435
|
+
return pending;
|
|
2436
|
+
}
|
|
2349
2437
|
|
|
2350
2438
|
// src/react/components.ts
|
|
2351
2439
|
var import_react = require("react");
|
|
2352
2440
|
|
|
2353
2441
|
// src/version.ts
|
|
2354
|
-
var VERSION = "0.6.0-alpha.
|
|
2442
|
+
var VERSION = "0.6.0-alpha.9";
|
|
2355
2443
|
|
|
2356
2444
|
// src/core/pixel.ts
|
|
2357
2445
|
var PIXEL_SCRIPT_URL = "https://cdn.tracking.prepr.io/js/prepr.min.js";
|
|
@@ -2426,35 +2514,22 @@ function PreprToolbar({
|
|
|
2426
2514
|
}, []);
|
|
2427
2515
|
return null;
|
|
2428
2516
|
}
|
|
2429
|
-
var DECIDE_HEADER = "Prepr-Decide";
|
|
2430
|
-
var DECIDE_TIMEOUT_MS = 6e3;
|
|
2431
|
-
function requestDecision(key) {
|
|
2432
|
-
const pending = { key, value: null };
|
|
2433
|
-
pending.value = fetch(key, {
|
|
2434
|
-
headers: { [DECIDE_HEADER]: "1" },
|
|
2435
|
-
cache: "no-store",
|
|
2436
|
-
credentials: "same-origin",
|
|
2437
|
-
signal: AbortSignal.timeout(DECIDE_TIMEOUT_MS)
|
|
2438
|
-
}).then((response) => response.ok ? response.text() : "*").catch(() => "*").then((value) => {
|
|
2439
|
-
pending.result = value;
|
|
2440
|
-
try {
|
|
2441
|
-
sessionStorage.setItem(
|
|
2442
|
-
"prepr_decision",
|
|
2443
|
-
JSON.stringify({ key, value, at: Date.now() })
|
|
2444
|
-
);
|
|
2445
|
-
} catch {
|
|
2446
|
-
}
|
|
2447
|
-
return value;
|
|
2448
|
-
});
|
|
2449
|
-
return pending;
|
|
2450
|
-
}
|
|
2451
|
-
var pressed = null;
|
|
2452
|
-
var replaying = null;
|
|
2453
2517
|
var shown = /* @__PURE__ */ new Map();
|
|
2454
2518
|
var historyStep = false;
|
|
2455
2519
|
var onPopState = () => {
|
|
2456
2520
|
historyStep = true;
|
|
2457
2521
|
};
|
|
2522
|
+
function requestDecision(key, personalized = false) {
|
|
2523
|
+
return requestPreprDecision(key, {
|
|
2524
|
+
personalized,
|
|
2525
|
+
onChange: (value) => {
|
|
2526
|
+
if (location.pathname + location.search !== key) return;
|
|
2527
|
+
applyPreprDecisions(value, { refresh: true });
|
|
2528
|
+
const state = window.__preprDecision;
|
|
2529
|
+
if (state) shown.set(key, state.value);
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
}
|
|
2458
2533
|
function linkTarget(event) {
|
|
2459
2534
|
const anchor = event.target?.closest?.("a[href]");
|
|
2460
2535
|
if (!(anchor instanceof HTMLAnchorElement)) return null;
|
|
@@ -2466,55 +2541,37 @@ function linkTarget(event) {
|
|
|
2466
2541
|
if (url.origin !== location.origin || key === location.pathname + location.search) {
|
|
2467
2542
|
return null;
|
|
2468
2543
|
}
|
|
2469
|
-
return
|
|
2544
|
+
return key;
|
|
2545
|
+
}
|
|
2546
|
+
var HOVER_DELAY_MS = 65;
|
|
2547
|
+
var hovering = null;
|
|
2548
|
+
function onPointerOver(event) {
|
|
2549
|
+
if (event.pointerType !== "mouse") return;
|
|
2550
|
+
const key = linkTarget(event);
|
|
2551
|
+
if (hovering?.key === key) return;
|
|
2552
|
+
if (hovering) clearTimeout(hovering.timer);
|
|
2553
|
+
hovering = key ? { key, timer: setTimeout(() => requestDecision(key), HOVER_DELAY_MS) } : null;
|
|
2470
2554
|
}
|
|
2471
2555
|
function onPointerDown(event) {
|
|
2472
2556
|
if (event.button !== 0) return;
|
|
2473
|
-
const
|
|
2474
|
-
if (
|
|
2475
|
-
return;
|
|
2476
|
-
}
|
|
2477
|
-
pressed = requestDecision(target.key);
|
|
2478
|
-
}
|
|
2479
|
-
function onClick(event) {
|
|
2480
|
-
const target = linkTarget(event);
|
|
2481
|
-
if (!target) return;
|
|
2482
|
-
if (replaying === target.anchor) {
|
|
2483
|
-
replaying = null;
|
|
2484
|
-
return;
|
|
2485
|
-
}
|
|
2486
|
-
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
2487
|
-
return;
|
|
2488
|
-
}
|
|
2489
|
-
const pending = pressed && pressed.key === target.key ? pressed : requestDecision(target.key);
|
|
2490
|
-
pressed = null;
|
|
2491
|
-
const record = (value) => {
|
|
2492
|
-
window.__preprDecision = { key: target.key, value };
|
|
2493
|
-
};
|
|
2494
|
-
if (pending.result !== void 0) {
|
|
2495
|
-
record(pending.result);
|
|
2496
|
-
return;
|
|
2497
|
-
}
|
|
2498
|
-
event.preventDefault();
|
|
2499
|
-
event.stopImmediatePropagation();
|
|
2500
|
-
void pending.value.then((value) => {
|
|
2501
|
-
record(value);
|
|
2502
|
-
replaying = target.anchor;
|
|
2503
|
-
target.anchor.click();
|
|
2504
|
-
});
|
|
2557
|
+
const key = linkTarget(event);
|
|
2558
|
+
if (key) requestDecision(key);
|
|
2505
2559
|
}
|
|
2506
2560
|
var listeners = 0;
|
|
2507
2561
|
function useDecisionRequests() {
|
|
2508
2562
|
(0, import_react2.useEffect)(() => {
|
|
2509
2563
|
if (listeners++ === 0) {
|
|
2510
|
-
window.addEventListener("
|
|
2511
|
-
window.addEventListener("
|
|
2564
|
+
window.addEventListener("pointerover", onPointerOver, { passive: true });
|
|
2565
|
+
window.addEventListener("pointerdown", onPointerDown, {
|
|
2566
|
+
capture: true,
|
|
2567
|
+
passive: true
|
|
2568
|
+
});
|
|
2512
2569
|
window.addEventListener("popstate", onPopState);
|
|
2513
2570
|
}
|
|
2514
2571
|
return () => {
|
|
2515
2572
|
if (--listeners === 0) {
|
|
2573
|
+
window.removeEventListener("pointerover", onPointerOver);
|
|
2516
2574
|
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
2517
|
-
window.removeEventListener("click", onClick, true);
|
|
2518
2575
|
window.removeEventListener("popstate", onPopState);
|
|
2519
2576
|
}
|
|
2520
2577
|
};
|
|
@@ -2538,12 +2595,16 @@ function PreprDecisionApplier() {
|
|
|
2538
2595
|
remember();
|
|
2539
2596
|
return;
|
|
2540
2597
|
}
|
|
2598
|
+
const pending = requestDecision(key, true);
|
|
2599
|
+
if (pending.result !== void 0) {
|
|
2600
|
+
applyPreprDecisions(pending.result);
|
|
2601
|
+
remember();
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2541
2604
|
let live = true;
|
|
2542
|
-
|
|
2543
|
-
const value = started?.key === key ? started.value : requestDecision(key).value;
|
|
2544
|
-
void value.then((value2) => {
|
|
2605
|
+
void pending.value.then((value) => {
|
|
2545
2606
|
if (live && location.pathname + location.search === key) {
|
|
2546
|
-
applyPreprDecisions(
|
|
2607
|
+
applyPreprDecisions(value);
|
|
2547
2608
|
remember();
|
|
2548
2609
|
}
|
|
2549
2610
|
});
|
|
@@ -23,15 +23,17 @@ declare function PreprTrackingPixel({ id, config, }: PreprTrackingPixelProps): n
|
|
|
23
23
|
*/
|
|
24
24
|
declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps): null;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
26
|
+
* Gets each client-side navigation's decision in before the click: when the
|
|
27
|
+
* visitor hovers over a same-site link (or presses it, on touch devices), it
|
|
28
|
+
* asks `createPreprProxy` which variants they get on that page. Clicks are
|
|
29
|
+
* never held: the new page paints with those variants when the answer is in,
|
|
30
|
+
* and keeps its personalized sections hidden until then otherwise. Pages
|
|
31
|
+
* without personalization answer with no groups and are not asked again for
|
|
32
|
+
* an hour.
|
|
31
33
|
*
|
|
32
34
|
* Mount it once in the root layout, so links on pages without a
|
|
33
|
-
* `PreprStack` are covered too.
|
|
34
|
-
*
|
|
35
|
+
* `PreprStack` are covered too. Links to other sites and links that open a
|
|
36
|
+
* new tab or download are left alone.
|
|
35
37
|
*
|
|
36
38
|
* @example
|
|
37
39
|
* <PreprPersonalizationSwitch />
|
|
@@ -39,12 +41,11 @@ declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps)
|
|
|
39
41
|
declare function PreprPersonalizationSwitch(): null;
|
|
40
42
|
/**
|
|
41
43
|
* Applies this page view's decision to the variant wrappers of the
|
|
42
|
-
* `PreprStack` it is rendered by
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `PreprStack`; you do not need it yourself.
|
|
44
|
+
* `PreprStack` it is rendered by, before the page paints when the decision is
|
|
45
|
+
* already in: asked for on hover, or kept from an earlier view of the page.
|
|
46
|
+
* Back and Forward show the page as this tab last showed it. Any other view
|
|
47
|
+
* keeps its personalized sections hidden until the decision request answers.
|
|
48
|
+
* Rendered by `PreprStack`; you do not need it yourself.
|
|
48
49
|
*/
|
|
49
50
|
declare function PreprDecisionApplier(): null;
|
|
50
51
|
/**
|
|
@@ -23,15 +23,17 @@ declare function PreprTrackingPixel({ id, config, }: PreprTrackingPixelProps): n
|
|
|
23
23
|
*/
|
|
24
24
|
declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps): null;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
26
|
+
* Gets each client-side navigation's decision in before the click: when the
|
|
27
|
+
* visitor hovers over a same-site link (or presses it, on touch devices), it
|
|
28
|
+
* asks `createPreprProxy` which variants they get on that page. Clicks are
|
|
29
|
+
* never held: the new page paints with those variants when the answer is in,
|
|
30
|
+
* and keeps its personalized sections hidden until then otherwise. Pages
|
|
31
|
+
* without personalization answer with no groups and are not asked again for
|
|
32
|
+
* an hour.
|
|
31
33
|
*
|
|
32
34
|
* Mount it once in the root layout, so links on pages without a
|
|
33
|
-
* `PreprStack` are covered too.
|
|
34
|
-
*
|
|
35
|
+
* `PreprStack` are covered too. Links to other sites and links that open a
|
|
36
|
+
* new tab or download are left alone.
|
|
35
37
|
*
|
|
36
38
|
* @example
|
|
37
39
|
* <PreprPersonalizationSwitch />
|
|
@@ -39,12 +41,11 @@ declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps)
|
|
|
39
41
|
declare function PreprPersonalizationSwitch(): null;
|
|
40
42
|
/**
|
|
41
43
|
* Applies this page view's decision to the variant wrappers of the
|
|
42
|
-
* `PreprStack` it is rendered by
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* `PreprStack`; you do not need it yourself.
|
|
44
|
+
* `PreprStack` it is rendered by, before the page paints when the decision is
|
|
45
|
+
* already in: asked for on hover, or kept from an earlier view of the page.
|
|
46
|
+
* Back and Forward show the page as this tab last showed it. Any other view
|
|
47
|
+
* keeps its personalized sections hidden until the decision request answers.
|
|
48
|
+
* Rendered by `PreprStack`; you do not need it yourself.
|
|
48
49
|
*/
|
|
49
50
|
declare function PreprDecisionApplier(): null;
|
|
50
51
|
/**
|