intently 0.2.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/LICENSE +21 -0
- package/README.md +157 -0
- package/dist/chunk-WUH3J7BB.js +462 -0
- package/dist/chunk-WUH3J7BB.js.map +1 -0
- package/dist/core-N6dbpDzv.d.cts +77 -0
- package/dist/core-N6dbpDzv.d.ts +77 -0
- package/dist/index.cjs +469 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +40 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +483 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +24 -0
- package/dist/react.d.ts +24 -0
- package/dist/react.js +20 -0
- package/dist/react.js.map +1 -0
- package/package.json +67 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/eligibility.ts
|
|
4
|
+
function shouldRun(respectSaveData) {
|
|
5
|
+
if (typeof navigator === "undefined") return false;
|
|
6
|
+
if (!respectSaveData) return true;
|
|
7
|
+
const c = navigator.connection;
|
|
8
|
+
if (!c) return true;
|
|
9
|
+
if (c.saveData) return false;
|
|
10
|
+
if (typeof c.effectiveType === "string" && /(^|-)2g$/.test(c.effectiveType)) return false;
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
function makeEligible(opts) {
|
|
14
|
+
const here = typeof location !== "undefined" ? location : null;
|
|
15
|
+
const originOk = (url, el) => {
|
|
16
|
+
if (typeof opts.origins === "function") return opts.origins(url, el);
|
|
17
|
+
const allow = opts.origins ?? (here ? [here.hostname] : []);
|
|
18
|
+
return allow.includes(url.hostname);
|
|
19
|
+
};
|
|
20
|
+
const ignored = (url, el) => {
|
|
21
|
+
const ig = opts.ignores;
|
|
22
|
+
if (!ig) return false;
|
|
23
|
+
if (typeof ig === "function") return ig(url, el);
|
|
24
|
+
return ig.some(
|
|
25
|
+
(rule) => typeof rule === "string" ? url.href.includes(rule) : rule.test(url.href)
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
return (el) => {
|
|
29
|
+
const href = el.href;
|
|
30
|
+
if (!href) return null;
|
|
31
|
+
let url;
|
|
32
|
+
try {
|
|
33
|
+
url = new URL(href, here?.href);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
38
|
+
if (el.hasAttribute("download")) return null;
|
|
39
|
+
if (here && url.href.replace(/#.*$/, "") === here.href.replace(/#.*$/, "")) return null;
|
|
40
|
+
if (!originOk(url, el)) return null;
|
|
41
|
+
if (ignored(url, el)) return null;
|
|
42
|
+
return url.href;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/loader.ts
|
|
47
|
+
var speculationRulesSupported = typeof HTMLScriptElement !== "undefined" && typeof HTMLScriptElement.supports === "function" && HTMLScriptElement.supports("speculationrules");
|
|
48
|
+
var linkPrefetchSupported = (() => {
|
|
49
|
+
if (typeof document === "undefined") return false;
|
|
50
|
+
try {
|
|
51
|
+
const l = document.createElement("link");
|
|
52
|
+
return l.relList && l.relList.supports && l.relList.supports("prefetch");
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
})();
|
|
57
|
+
var MAX_NODES = 50;
|
|
58
|
+
var MAX_PRERENDERS = 3;
|
|
59
|
+
function createLoader(limit) {
|
|
60
|
+
const loaded = /* @__PURE__ */ new Map();
|
|
61
|
+
const nodes = [];
|
|
62
|
+
const prerenderNodes = [];
|
|
63
|
+
let count = 0;
|
|
64
|
+
function track(node) {
|
|
65
|
+
nodes.push(node);
|
|
66
|
+
while (nodes.length > MAX_NODES) nodes.shift()?.remove();
|
|
67
|
+
}
|
|
68
|
+
const tier = speculationRulesSupported ? "speculationrules" : linkPrefetchSupported ? "link" : typeof fetch === "function" ? "fetch" : "none";
|
|
69
|
+
function addSpeculationRule(url, strategy) {
|
|
70
|
+
const script = document.createElement("script");
|
|
71
|
+
script.type = "speculationrules";
|
|
72
|
+
script.textContent = JSON.stringify({
|
|
73
|
+
[strategy]: [{ source: "list", urls: [url], eagerness: "immediate" }]
|
|
74
|
+
});
|
|
75
|
+
document.head.appendChild(script);
|
|
76
|
+
if (strategy === "prerender") {
|
|
77
|
+
prerenderNodes.push({ url, node: script });
|
|
78
|
+
while (prerenderNodes.length > MAX_PRERENDERS) {
|
|
79
|
+
const old = prerenderNodes.shift();
|
|
80
|
+
if (old) {
|
|
81
|
+
old.node.remove();
|
|
82
|
+
loaded.delete(old.url);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
track(script);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function addPrefetchLink(url) {
|
|
90
|
+
const link = document.createElement("link");
|
|
91
|
+
link.rel = "prefetch";
|
|
92
|
+
link.href = url;
|
|
93
|
+
document.head.appendChild(link);
|
|
94
|
+
track(link);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
tier,
|
|
98
|
+
load(url, strategy) {
|
|
99
|
+
if (tier === "none") return null;
|
|
100
|
+
const prior = loaded.get(url);
|
|
101
|
+
if (prior === "prerender" || prior === "prefetch" && strategy === "prefetch") {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (prior === void 0 && count >= limit) return null;
|
|
105
|
+
if (prior === void 0) count++;
|
|
106
|
+
const effective = strategy === "prerender" && tier !== "speculationrules" ? "prefetch" : strategy;
|
|
107
|
+
if (tier === "speculationrules") {
|
|
108
|
+
addSpeculationRule(url, effective);
|
|
109
|
+
} else if (tier === "link") {
|
|
110
|
+
if (prior === void 0) addPrefetchLink(url);
|
|
111
|
+
} else {
|
|
112
|
+
if (prior === void 0) {
|
|
113
|
+
fetch(url, { credentials: "same-origin" }).catch(() => {
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
loaded.set(url, effective);
|
|
118
|
+
return effective;
|
|
119
|
+
},
|
|
120
|
+
destroy() {
|
|
121
|
+
for (const n of nodes) n.remove();
|
|
122
|
+
for (const p of prerenderNodes) p.node.remove();
|
|
123
|
+
nodes.length = 0;
|
|
124
|
+
prerenderNodes.length = 0;
|
|
125
|
+
loaded.clear();
|
|
126
|
+
count = 0;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/predict.ts
|
|
132
|
+
function distanceToRect(x, y, r) {
|
|
133
|
+
const dx = Math.max(r.left - x, 0, x - r.right);
|
|
134
|
+
const dy = Math.max(r.top - y, 0, y - r.bottom);
|
|
135
|
+
return Math.hypot(dx, dy);
|
|
136
|
+
}
|
|
137
|
+
function falloff(distance, radius, exponent = 2) {
|
|
138
|
+
return Math.max(0, 1 - distance / radius) ** exponent;
|
|
139
|
+
}
|
|
140
|
+
function proximityScore(x, y, r, radius) {
|
|
141
|
+
return falloff(distanceToRect(x, y, r), radius);
|
|
142
|
+
}
|
|
143
|
+
function trajectoryScore(x, y, v, r, cone = 0.6) {
|
|
144
|
+
const speed = Math.hypot(v.x, v.y);
|
|
145
|
+
if (speed < 0.04) return 0;
|
|
146
|
+
const cx = (r.left + r.right) / 2;
|
|
147
|
+
const cy = (r.top + r.bottom) / 2;
|
|
148
|
+
const dx = cx - x;
|
|
149
|
+
const dy = cy - y;
|
|
150
|
+
const d = Math.hypot(dx, dy) || 1;
|
|
151
|
+
const align = dx / d * (v.x / speed) + dy / d * (v.y / speed);
|
|
152
|
+
if (align <= cone) return 0;
|
|
153
|
+
const aligned = (align - cone) / (1 - cone);
|
|
154
|
+
const committed = Math.min(1, speed / 0.6);
|
|
155
|
+
return aligned * (0.6 + 0.4 * committed);
|
|
156
|
+
}
|
|
157
|
+
function updateVelocity(v, prev, x, y, t, smoothing = 0.7) {
|
|
158
|
+
if (prev) {
|
|
159
|
+
const dt = Math.max(1, t - prev.t);
|
|
160
|
+
v.x = v.x * smoothing + (x - prev.x) / dt * (1 - smoothing);
|
|
161
|
+
v.y = v.y * smoothing + (y - prev.y) / dt * (1 - smoothing);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/core.ts
|
|
166
|
+
var DEFAULTS = {
|
|
167
|
+
intentThreshold: 0.5,
|
|
168
|
+
prerenderThreshold: 0.85,
|
|
169
|
+
proximityRadius: 80,
|
|
170
|
+
hoverDelay: 65,
|
|
171
|
+
eagerOnPress: true,
|
|
172
|
+
viewportPrefetch: false,
|
|
173
|
+
limit: Infinity,
|
|
174
|
+
respectSaveData: true
|
|
175
|
+
};
|
|
176
|
+
var ARM_FRAMES = 8;
|
|
177
|
+
function now() {
|
|
178
|
+
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
179
|
+
}
|
|
180
|
+
function intently(options = {}) {
|
|
181
|
+
const opts = { ...DEFAULTS, ...options };
|
|
182
|
+
const root = opts.root ?? (typeof document !== "undefined" ? document : null);
|
|
183
|
+
const loader = createLoader(opts.limit);
|
|
184
|
+
const signals = new Set(opts.signals ?? ["trajectory", "proximity", "hover", "touch"]);
|
|
185
|
+
const useTrajectory = signals.has("trajectory");
|
|
186
|
+
const useProximity = signals.has("proximity");
|
|
187
|
+
const useHover = signals.has("hover");
|
|
188
|
+
const usePress = opts.eagerOnPress;
|
|
189
|
+
const useViewport = signals.has("viewport") || opts.viewportPrefetch;
|
|
190
|
+
if (typeof window === "undefined" || !root || loader.tier === "none" || !shouldRun(opts.respectSaveData)) {
|
|
191
|
+
return { prefetch() {
|
|
192
|
+
}, prerender() {
|
|
193
|
+
}, destroy() {
|
|
194
|
+
}, loaded: /* @__PURE__ */ new Set() };
|
|
195
|
+
}
|
|
196
|
+
const eligible = makeEligible(opts);
|
|
197
|
+
const scopeEl = root instanceof Element ? root : null;
|
|
198
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
199
|
+
const visible = /* @__PURE__ */ new Set();
|
|
200
|
+
const rectCache = /* @__PURE__ */ new Map();
|
|
201
|
+
const loadedView = /* @__PURE__ */ new Set();
|
|
202
|
+
let rectsDirty = false;
|
|
203
|
+
let destroyed = false;
|
|
204
|
+
const pointer = { x: 0, y: 0 };
|
|
205
|
+
const vel = { x: 0, y: 0 };
|
|
206
|
+
let prevSample = null;
|
|
207
|
+
let lastMove = 0;
|
|
208
|
+
let lastMeasure = 0;
|
|
209
|
+
let raf = 0;
|
|
210
|
+
function prerenderSafe(el, urlStr) {
|
|
211
|
+
try {
|
|
212
|
+
if (new URL(urlStr).search) return false;
|
|
213
|
+
} catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const rel = (el.getAttribute("rel") || "").toLowerCase();
|
|
217
|
+
if (/\b(nofollow|external)\b/.test(rel)) return false;
|
|
218
|
+
const target = el.getAttribute("target");
|
|
219
|
+
if (target && target !== "_self") return false;
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
function load(el, url, confidence, wantPrerender) {
|
|
223
|
+
if (destroyed) return;
|
|
224
|
+
let strategy = "prefetch";
|
|
225
|
+
if (wantPrerender && opts.prerenderThreshold !== false && confidence >= opts.prerenderThreshold && prerenderSafe(el, url)) {
|
|
226
|
+
strategy = "prerender";
|
|
227
|
+
}
|
|
228
|
+
const used = loader.load(url, strategy);
|
|
229
|
+
if (used) {
|
|
230
|
+
loadedView.add(url);
|
|
231
|
+
opts.onLoad?.(url, used);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function emit(el, c, confidence, signal) {
|
|
235
|
+
if (!opts.onPredict) return;
|
|
236
|
+
if (Math.abs(c.emitted - confidence) < 0.02) return;
|
|
237
|
+
c.emitted = confidence;
|
|
238
|
+
opts.onPredict({ el, url: c.url, confidence, signal });
|
|
239
|
+
}
|
|
240
|
+
function consider(el) {
|
|
241
|
+
const url = scopeEl && !scopeEl.contains(el) ? null : eligible(el);
|
|
242
|
+
const existing = candidates.get(el);
|
|
243
|
+
if (!url) {
|
|
244
|
+
if (existing) drop(el);
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
if (existing) {
|
|
248
|
+
existing.url = url;
|
|
249
|
+
return existing;
|
|
250
|
+
}
|
|
251
|
+
const c = { url, armedFrames: 0, emitted: -1 };
|
|
252
|
+
candidates.set(el, c);
|
|
253
|
+
io.observe(el);
|
|
254
|
+
return c;
|
|
255
|
+
}
|
|
256
|
+
function drop(el) {
|
|
257
|
+
const c = candidates.get(el);
|
|
258
|
+
if (c) {
|
|
259
|
+
if (c.emitted > 0) emit(el, c, 0, "proximity");
|
|
260
|
+
candidates.delete(el);
|
|
261
|
+
io.unobserve(el);
|
|
262
|
+
visible.delete(el);
|
|
263
|
+
rectCache.delete(el);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function scan() {
|
|
267
|
+
root.querySelectorAll("a[href]").forEach(consider);
|
|
268
|
+
}
|
|
269
|
+
const io = new IntersectionObserver(
|
|
270
|
+
(entries) => {
|
|
271
|
+
for (const e of entries) {
|
|
272
|
+
const el = e.target;
|
|
273
|
+
if (e.isIntersecting) {
|
|
274
|
+
visible.add(el);
|
|
275
|
+
rectCache.set(el, e.boundingClientRect);
|
|
276
|
+
if (useViewport) {
|
|
277
|
+
idle(() => {
|
|
278
|
+
const cc = candidates.get(el);
|
|
279
|
+
if (cc && !loadedView.has(cc.url)) load(el, cc.url, 0, false);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
visible.delete(el);
|
|
284
|
+
rectCache.delete(el);
|
|
285
|
+
const c = candidates.get(el);
|
|
286
|
+
if (c && c.emitted > 0) emit(el, c, 0, "proximity");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
{ rootMargin: "0px" }
|
|
291
|
+
);
|
|
292
|
+
const mo = new MutationObserver((muts) => {
|
|
293
|
+
for (const m of muts) {
|
|
294
|
+
if (m.type === "attributes") {
|
|
295
|
+
if (m.target instanceof HTMLAnchorElement) consider(m.target);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
m.addedNodes.forEach((n) => {
|
|
299
|
+
if (!(n instanceof Element)) return;
|
|
300
|
+
if (n.matches?.("a[href]")) consider(n);
|
|
301
|
+
n.querySelectorAll?.("a[href]").forEach(consider);
|
|
302
|
+
});
|
|
303
|
+
m.removedNodes.forEach((n) => {
|
|
304
|
+
if (!(n instanceof Element)) return;
|
|
305
|
+
if (n.matches?.("a[href]")) drop(n);
|
|
306
|
+
n.querySelectorAll?.("a[href]").forEach((el) => drop(el));
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
function refreshRects() {
|
|
311
|
+
for (const el of visible) rectCache.set(el, el.getBoundingClientRect());
|
|
312
|
+
rectsDirty = false;
|
|
313
|
+
}
|
|
314
|
+
function kick() {
|
|
315
|
+
if (!raf && !destroyed && (useProximity || useTrajectory)) raf = requestAnimationFrame(tick);
|
|
316
|
+
}
|
|
317
|
+
function tick(t) {
|
|
318
|
+
if (destroyed) {
|
|
319
|
+
raf = 0;
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (document.hidden || t - lastMove > 500) {
|
|
323
|
+
raf = 0;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (rectsDirty || t - lastMeasure > 250) {
|
|
327
|
+
refreshRects();
|
|
328
|
+
lastMeasure = t;
|
|
329
|
+
}
|
|
330
|
+
if (t - lastMove > 80) {
|
|
331
|
+
vel.x = 0;
|
|
332
|
+
vel.y = 0;
|
|
333
|
+
}
|
|
334
|
+
for (const el of visible) {
|
|
335
|
+
const c = candidates.get(el);
|
|
336
|
+
if (!c || loadedView.has(c.url)) continue;
|
|
337
|
+
const r = rectCache.get(el);
|
|
338
|
+
if (!r) continue;
|
|
339
|
+
const prox = useProximity ? proximityScore(pointer.x, pointer.y, r, opts.proximityRadius) : 0;
|
|
340
|
+
const traj = useTrajectory ? trajectoryScore(pointer.x, pointer.y, vel, r) : 0;
|
|
341
|
+
const confidence = Math.max(prox, traj);
|
|
342
|
+
const signal = traj >= prox ? "trajectory" : "proximity";
|
|
343
|
+
if (confidence < 0.05) {
|
|
344
|
+
c.armedFrames = 0;
|
|
345
|
+
emit(el, c, 0, signal);
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
let wantPrerender = false;
|
|
349
|
+
if (opts.prerenderThreshold !== false && confidence >= opts.prerenderThreshold) {
|
|
350
|
+
c.armedFrames++;
|
|
351
|
+
if (c.armedFrames >= ARM_FRAMES) wantPrerender = true;
|
|
352
|
+
} else {
|
|
353
|
+
c.armedFrames = 0;
|
|
354
|
+
}
|
|
355
|
+
if (confidence >= opts.intentThreshold || wantPrerender) {
|
|
356
|
+
load(el, c.url, confidence, wantPrerender);
|
|
357
|
+
}
|
|
358
|
+
emit(el, c, confidence, signal);
|
|
359
|
+
}
|
|
360
|
+
raf = requestAnimationFrame(tick);
|
|
361
|
+
}
|
|
362
|
+
function onMove(e) {
|
|
363
|
+
updateVelocity(vel, prevSample, e.clientX, e.clientY, e.timeStamp);
|
|
364
|
+
prevSample = { x: e.clientX, y: e.clientY, t: e.timeStamp };
|
|
365
|
+
pointer.x = e.clientX;
|
|
366
|
+
pointer.y = e.clientY;
|
|
367
|
+
lastMove = now();
|
|
368
|
+
kick();
|
|
369
|
+
}
|
|
370
|
+
let hovered = null;
|
|
371
|
+
let hoverTimer = 0;
|
|
372
|
+
function onOver(e) {
|
|
373
|
+
const a = e.target?.closest?.("a[href]");
|
|
374
|
+
if (!a || a === hovered) return;
|
|
375
|
+
hovered = a;
|
|
376
|
+
clearTimeout(hoverTimer);
|
|
377
|
+
const c = consider(a);
|
|
378
|
+
if (!c || loadedView.has(c.url)) return;
|
|
379
|
+
hoverTimer = window.setTimeout(() => {
|
|
380
|
+
if (hovered === a) load(a, c.url, 1, true);
|
|
381
|
+
}, opts.hoverDelay);
|
|
382
|
+
}
|
|
383
|
+
function onOut(e) {
|
|
384
|
+
if (hovered && e.relatedTarget instanceof Node && hovered.contains(e.relatedTarget)) return;
|
|
385
|
+
hovered = null;
|
|
386
|
+
clearTimeout(hoverTimer);
|
|
387
|
+
}
|
|
388
|
+
function onPress(e) {
|
|
389
|
+
const a = e.target?.closest?.("a[href]");
|
|
390
|
+
if (!a) return;
|
|
391
|
+
const c = consider(a);
|
|
392
|
+
if (c && !loadedView.has(c.url)) load(a, c.url, 1, false);
|
|
393
|
+
}
|
|
394
|
+
function onScroll() {
|
|
395
|
+
rectsDirty = true;
|
|
396
|
+
}
|
|
397
|
+
function onVisibility() {
|
|
398
|
+
if (!document.hidden) {
|
|
399
|
+
lastMove = now();
|
|
400
|
+
kick();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
function idle(fn) {
|
|
404
|
+
const ric = window.requestIdleCallback;
|
|
405
|
+
const guarded = () => {
|
|
406
|
+
if (!destroyed) fn();
|
|
407
|
+
};
|
|
408
|
+
if (ric) ric(guarded);
|
|
409
|
+
else setTimeout(guarded, 1);
|
|
410
|
+
}
|
|
411
|
+
scan();
|
|
412
|
+
mo.observe(scopeEl ?? document.documentElement, {
|
|
413
|
+
childList: true,
|
|
414
|
+
subtree: true,
|
|
415
|
+
attributes: true,
|
|
416
|
+
attributeFilter: ["href"]
|
|
417
|
+
});
|
|
418
|
+
window.addEventListener("pointermove", onMove, { passive: true });
|
|
419
|
+
if (useHover) {
|
|
420
|
+
window.addEventListener("pointerover", onOver, { passive: true });
|
|
421
|
+
window.addEventListener("pointerout", onOut, { passive: true });
|
|
422
|
+
}
|
|
423
|
+
if (usePress) {
|
|
424
|
+
window.addEventListener("pointerdown", onPress, { passive: true });
|
|
425
|
+
window.addEventListener("touchstart", onPress, { passive: true });
|
|
426
|
+
}
|
|
427
|
+
window.addEventListener("scroll", onScroll, { passive: true, capture: true });
|
|
428
|
+
window.addEventListener("resize", onScroll, { passive: true });
|
|
429
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
430
|
+
return {
|
|
431
|
+
prefetch: (url) => {
|
|
432
|
+
const used = loader.load(url, "prefetch");
|
|
433
|
+
if (used) loadedView.add(url);
|
|
434
|
+
},
|
|
435
|
+
prerender: (url) => {
|
|
436
|
+
const used = loader.load(url, "prerender");
|
|
437
|
+
if (used) loadedView.add(url);
|
|
438
|
+
},
|
|
439
|
+
destroy() {
|
|
440
|
+
destroyed = true;
|
|
441
|
+
if (raf) cancelAnimationFrame(raf);
|
|
442
|
+
clearTimeout(hoverTimer);
|
|
443
|
+
io.disconnect();
|
|
444
|
+
mo.disconnect();
|
|
445
|
+
window.removeEventListener("pointermove", onMove);
|
|
446
|
+
window.removeEventListener("pointerover", onOver);
|
|
447
|
+
window.removeEventListener("pointerout", onOut);
|
|
448
|
+
window.removeEventListener("pointerdown", onPress);
|
|
449
|
+
window.removeEventListener("touchstart", onPress);
|
|
450
|
+
window.removeEventListener("scroll", onScroll, { capture: true });
|
|
451
|
+
window.removeEventListener("resize", onScroll);
|
|
452
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
453
|
+
loader.destroy();
|
|
454
|
+
candidates.clear();
|
|
455
|
+
visible.clear();
|
|
456
|
+
rectCache.clear();
|
|
457
|
+
},
|
|
458
|
+
loaded: loadedView
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
exports.distanceToRect = distanceToRect;
|
|
463
|
+
exports.falloff = falloff;
|
|
464
|
+
exports.intently = intently;
|
|
465
|
+
exports.proximityScore = proximityScore;
|
|
466
|
+
exports.trajectoryScore = trajectoryScore;
|
|
467
|
+
exports.updateVelocity = updateVelocity;
|
|
468
|
+
//# sourceMappingURL=index.cjs.map
|
|
469
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/eligibility.ts","../src/loader.ts","../src/predict.ts","../src/core.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { IntentlyOptions } from \"./types\";\n\n/**\n * Should intently run at all right now? Honors Save-Data and slow/metered\n * connections so we never spend a careful user's bytes guessing.\n */\nexport function shouldRun(respectSaveData: boolean): boolean {\n if (typeof navigator === \"undefined\") return false;\n if (!respectSaveData) return true;\n const c = (navigator as Navigator & { connection?: NetworkInformation }).connection;\n if (!c) return true;\n if (c.saveData) return false;\n if (typeof c.effectiveType === \"string\" && /(^|-)2g$/.test(c.effectiveType)) return false;\n return true;\n}\n\ninterface NetworkInformation {\n saveData?: boolean;\n effectiveType?: string;\n}\n\n/**\n * Build the per-link eligibility test. Returns the resolved URL for links worth\n * considering, or `null` for ones we must leave alone (cross-origin, current\n * page, downloads, anything the caller ignored).\n */\nexport function makeEligible(opts: IntentlyOptions) {\n const here = typeof location !== \"undefined\" ? location : null;\n\n const originOk = (url: URL, el: HTMLAnchorElement) => {\n if (typeof opts.origins === \"function\") return opts.origins(url, el);\n const allow = opts.origins ?? (here ? [here.hostname] : []);\n return allow.includes(url.hostname);\n };\n\n const ignored = (url: URL, el: HTMLAnchorElement) => {\n const ig = opts.ignores;\n if (!ig) return false;\n if (typeof ig === \"function\") return ig(url, el);\n return ig.some((rule) =>\n typeof rule === \"string\" ? url.href.includes(rule) : rule.test(url.href),\n );\n };\n\n return (el: HTMLAnchorElement): string | null => {\n const href = el.href;\n if (!href) return null;\n\n let url: URL;\n try {\n url = new URL(href, here?.href);\n } catch {\n return null;\n }\n\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return null;\n if (el.hasAttribute(\"download\")) return null;\n // Same document (ignoring the hash) — nothing to fetch.\n if (here && url.href.replace(/#.*$/, \"\") === here.href.replace(/#.*$/, \"\")) return null;\n if (!originOk(url, el)) return null;\n if (ignored(url, el)) return null;\n\n return url.href;\n };\n}\n","import type { Strategy } from \"./types\";\n\n/**\n * The loading backend, in tiers:\n * 1. Speculation Rules API — real prefetch *and* prerender, cross-document,\n * with the browser managing priority. Chromium today.\n * 2. <link rel=\"prefetch\"> — prefetch only, broad support.\n * 3. fetch(low priority) — last resort; warms the HTTP cache.\n *\n * We pick the best available tier and degrade silently. prerender always\n * degrades to prefetch where prerender isn't available.\n */\n\nconst speculationRulesSupported =\n typeof HTMLScriptElement !== \"undefined\" &&\n typeof HTMLScriptElement.supports === \"function\" &&\n HTMLScriptElement.supports(\"speculationrules\");\n\nconst linkPrefetchSupported = (() => {\n if (typeof document === \"undefined\") return false;\n try {\n const l = document.createElement(\"link\");\n return l.relList && l.relList.supports && l.relList.supports(\"prefetch\");\n } catch {\n return false;\n }\n})();\n\nexport interface Loader {\n load(url: string, strategy: Strategy): Strategy | null;\n readonly tier: \"speculationrules\" | \"link\" | \"fetch\" | \"none\";\n destroy(): void;\n}\n\n// Cap how many speculation-rule / prefetch nodes live in <head> at once so a\n// long SPA session (feeds, infinite scroll) doesn't accumulate hundreds. We\n// evict the oldest — least likely to be the next click. The fetch already\n// happened, so eviction only tidies the DOM.\nconst MAX_NODES = 50;\n// A prerender is a live, resource-holding page. Removing its rule cancels it, so\n// these are NOT freely evictable — cap at a small budget (matching what Chrome\n// keeps anyway) and, when one is dropped, forget it so it can be recreated.\nconst MAX_PRERENDERS = 3;\n\nexport function createLoader(limit: number): Loader {\n const loaded = new Map<string, Strategy>();\n const nodes: HTMLElement[] = []; // prefetch / link nodes — safe to evict (fetch already happened)\n const prerenderNodes: { url: string; node: HTMLElement }[] = [];\n let count = 0;\n\n function track(node: HTMLElement) {\n nodes.push(node);\n while (nodes.length > MAX_NODES) nodes.shift()?.remove();\n }\n\n const tier: Loader[\"tier\"] = speculationRulesSupported\n ? \"speculationrules\"\n : linkPrefetchSupported\n ? \"link\"\n : typeof fetch === \"function\"\n ? \"fetch\"\n : \"none\";\n\n function addSpeculationRule(url: string, strategy: Strategy) {\n // One script per rule — appending new speculationrules scripts is the\n // spec-supported way to add rules dynamically. eagerness is \"immediate\"\n // because *our predictor* already decided the timing.\n const script = document.createElement(\"script\");\n script.type = \"speculationrules\";\n script.textContent = JSON.stringify({\n [strategy]: [{ source: \"list\", urls: [url], eagerness: \"immediate\" }],\n });\n document.head.appendChild(script);\n if (strategy === \"prerender\") {\n prerenderNodes.push({ url, node: script });\n while (prerenderNodes.length > MAX_PRERENDERS) {\n const old = prerenderNodes.shift();\n if (old) {\n old.node.remove();\n loaded.delete(old.url); // let it be recreated if intent returns\n }\n }\n } else {\n track(script);\n }\n }\n\n function addPrefetchLink(url: string) {\n const link = document.createElement(\"link\");\n link.rel = \"prefetch\";\n link.href = url; // no `as` — document is the implied destination for rel=prefetch\n document.head.appendChild(link);\n track(link);\n }\n\n return {\n tier,\n load(url, strategy) {\n if (tier === \"none\") return null;\n const prior = loaded.get(url);\n // Already done at an equal-or-stronger tier? Skip. (prerender ⊇ prefetch.)\n if (prior === \"prerender\" || (prior === \"prefetch\" && strategy === \"prefetch\")) {\n return null;\n }\n if (prior === undefined && count >= limit) return null;\n if (prior === undefined) count++;\n\n const effective: Strategy =\n strategy === \"prerender\" && tier !== \"speculationrules\" ? \"prefetch\" : strategy;\n\n if (tier === \"speculationrules\") {\n addSpeculationRule(url, effective);\n } else if (tier === \"link\") {\n if (prior === undefined) addPrefetchLink(url); // link tier can't prerender\n } else {\n if (prior === undefined) {\n // Same-origin (eligibility guarantees it): a normal credentialed GET so\n // the cached response actually matches the real navigation. (no-cors +\n // omit would store an opaque, credential-mismatched entry the browser\n // can't reuse — defeating the warm-up.)\n fetch(url, { credentials: \"same-origin\" }).catch(() => {});\n }\n }\n\n loaded.set(url, effective);\n return effective;\n },\n destroy() {\n for (const n of nodes) n.remove();\n for (const p of prerenderNodes) p.node.remove();\n nodes.length = 0;\n prerenderNodes.length = 0;\n loaded.clear();\n count = 0;\n },\n };\n}\n","/**\n * The prediction math, lifted from the input-anticipation work\n * (https://seangeng.com/writing/interfaces-that-anticipate-input). Same engine\n * that warms a focus ring — here it scores how likely a link is your next click.\n */\n\nexport interface Rect {\n left: number;\n right: number;\n top: number;\n bottom: number;\n}\n\nexport interface Velocity {\n x: number;\n y: number;\n}\n\n/** Distance from a point to the nearest edge of a rect (0 if inside). */\nexport function distanceToRect(x: number, y: number, r: Rect): number {\n const dx = Math.max(r.left - x, 0, x - r.right);\n const dy = Math.max(r.top - y, 0, y - r.bottom);\n return Math.hypot(dx, dy);\n}\n\n/** Turn a distance into 0–1 intent via a falloff curve. exponent=2 reads best. */\nexport function falloff(distance: number, radius: number, exponent = 2): number {\n return Math.max(0, 1 - distance / radius) ** exponent;\n}\n\n/**\n * Proximity confidence: how close is the cursor to this rect, 0–1.\n */\nexport function proximityScore(x: number, y: number, r: Rect, radius: number): number {\n return falloff(distanceToRect(x, y, r), radius);\n}\n\n/**\n * Trajectory confidence: is the cursor *heading at* this rect, 0–1. Uses the\n * dot product of the (normalized) velocity with the direction to the rect's\n * center, gated by a forward cone so a glancing pass scores ~0. Returns 0 when\n * the pointer is too slow to have a meaningful heading.\n */\nexport function trajectoryScore(\n x: number,\n y: number,\n v: Velocity,\n r: Rect,\n cone = 0.6,\n): number {\n const speed = Math.hypot(v.x, v.y);\n if (speed < 0.04) return 0; // px/ms — basically still\n const cx = (r.left + r.right) / 2;\n const cy = (r.top + r.bottom) / 2;\n const dx = cx - x;\n const dy = cy - y;\n const d = Math.hypot(dx, dy) || 1;\n const align = (dx / d) * (v.x / speed) + (dy / d) * (v.y / speed); // -1..1\n if (align <= cone) return 0;\n // Remap (cone..1] → (0..1], and let faster, more committed moves score higher.\n const aligned = (align - cone) / (1 - cone);\n const committed = Math.min(1, speed / 0.6);\n return aligned * (0.6 + 0.4 * committed);\n}\n\n/** Exponential moving average of pointer velocity, in px/ms. */\nexport function updateVelocity(\n v: Velocity,\n prev: { x: number; y: number; t: number } | null,\n x: number,\n y: number,\n t: number,\n smoothing = 0.7,\n): void {\n if (prev) {\n const dt = Math.max(1, t - prev.t);\n v.x = v.x * smoothing + ((x - prev.x) / dt) * (1 - smoothing);\n v.y = v.y * smoothing + ((y - prev.y) / dt) * (1 - smoothing);\n }\n}\n","import { makeEligible, shouldRun } from \"./eligibility\";\nimport { createLoader } from \"./loader\";\nimport {\n proximityScore,\n trajectoryScore,\n updateVelocity,\n type Velocity,\n} from \"./predict\";\nimport type { IntentlyHandle, IntentlyOptions, Signal } from \"./types\";\n\ninterface Candidate {\n url: string;\n armedFrames: number; // consecutive frames above the prerender bar\n emitted: number; // last confidence sent to onPredict (dedupe)\n}\n\nconst DEFAULTS = {\n intentThreshold: 0.5,\n prerenderThreshold: 0.85 as number | false,\n proximityRadius: 80,\n hoverDelay: 65,\n eagerOnPress: true,\n viewportPrefetch: false,\n limit: Infinity,\n respectSaveData: true,\n};\n\nconst ARM_FRAMES = 8; // ~130ms at 60fps — sustained, not wall-clock (survives idle)\n\nfunction now() {\n return typeof performance !== \"undefined\" ? performance.now() : Date.now();\n}\n\n/**\n * Start intent-aware prefetching. Zero-config: `intently()` binds every\n * eligible same-origin link and prefetches the one the cursor is heading\n * toward. Returns a handle to control or tear it down.\n */\nexport function intently(options: IntentlyOptions = {}): IntentlyHandle {\n const opts = { ...DEFAULTS, ...options };\n const root: ParentNode = opts.root ?? (typeof document !== \"undefined\" ? document : (null as never));\n const loader = createLoader(opts.limit);\n\n const signals = new Set<Signal>(opts.signals ?? [\"trajectory\", \"proximity\", \"hover\", \"touch\"]);\n const useTrajectory = signals.has(\"trajectory\");\n const useProximity = signals.has(\"proximity\");\n const useHover = signals.has(\"hover\");\n const usePress = opts.eagerOnPress; // pointerdown / touchstart — covers touch + mouse\n const useViewport = signals.has(\"viewport\") || opts.viewportPrefetch;\n\n // No-op safely in non-DOM environments (SSR) or when we shouldn't run.\n if (\n typeof window === \"undefined\" ||\n !root ||\n loader.tier === \"none\" ||\n !shouldRun(opts.respectSaveData)\n ) {\n return { prefetch() {}, prerender() {}, destroy() {}, loaded: new Set() };\n }\n\n const eligible = makeEligible(opts);\n // When a non-document root is given, scope everything to it (not just the\n // initial scan): the MutationObserver and per-anchor checks honor it too.\n const scopeEl: Element | null = root instanceof Element ? root : null;\n const candidates = new Map<HTMLAnchorElement, Candidate>();\n const visible = new Set<HTMLAnchorElement>();\n const rectCache = new Map<HTMLAnchorElement, DOMRect>();\n const loadedView = new Set<string>();\n let rectsDirty = false;\n let destroyed = false;\n\n const pointer = { x: 0, y: 0 };\n const vel: Velocity = { x: 0, y: 0 };\n let prevSample: { x: number; y: number; t: number } | null = null;\n let lastMove = 0;\n let lastMeasure = 0;\n let raf = 0;\n\n // Prerender *runs* the page, so only ever prerender links that look free of\n // side effects: no query string, not nofollow/external, not a new tab.\n function prerenderSafe(el: HTMLAnchorElement, urlStr: string): boolean {\n try {\n if (new URL(urlStr).search) return false;\n } catch {\n return false;\n }\n const rel = (el.getAttribute(\"rel\") || \"\").toLowerCase();\n if (/\\b(nofollow|external)\\b/.test(rel)) return false;\n const target = el.getAttribute(\"target\");\n if (target && target !== \"_self\") return false;\n return true;\n }\n\n function load(el: HTMLAnchorElement, url: string, confidence: number, wantPrerender: boolean) {\n if (destroyed) return;\n let strategy: \"prefetch\" | \"prerender\" = \"prefetch\";\n if (\n wantPrerender &&\n opts.prerenderThreshold !== false &&\n confidence >= opts.prerenderThreshold &&\n prerenderSafe(el, url)\n ) {\n strategy = \"prerender\";\n }\n const used = loader.load(url, strategy);\n if (used) {\n loadedView.add(url);\n opts.onLoad?.(url, used);\n }\n }\n\n function emit(el: HTMLAnchorElement, c: Candidate, confidence: number, signal: Signal) {\n if (!opts.onPredict) return;\n if (Math.abs(c.emitted - confidence) < 0.02) return; // only on meaningful change\n c.emitted = confidence;\n opts.onPredict({ el, url: c.url, confidence, signal });\n }\n\n // ---- candidate discovery -------------------------------------------------\n\n function consider(el: HTMLAnchorElement): Candidate | null {\n const url = scopeEl && !scopeEl.contains(el) ? null : eligible(el);\n const existing = candidates.get(el);\n if (!url) {\n if (existing) drop(el);\n return null;\n }\n if (existing) {\n existing.url = url; // href changed in place (SPA routers) — keep it fresh\n return existing;\n }\n const c: Candidate = { url, armedFrames: 0, emitted: -1 };\n candidates.set(el, c);\n io.observe(el);\n return c;\n }\n\n function drop(el: HTMLAnchorElement) {\n const c = candidates.get(el);\n if (c) {\n if (c.emitted > 0) emit(el, c, 0, \"proximity\"); // let a UI affordance clear\n candidates.delete(el);\n io.unobserve(el);\n visible.delete(el);\n rectCache.delete(el);\n }\n }\n\n function scan() {\n root.querySelectorAll<HTMLAnchorElement>(\"a[href]\").forEach(consider);\n }\n\n const io = new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n const el = e.target as HTMLAnchorElement;\n if (e.isIntersecting) {\n visible.add(el);\n rectCache.set(el, e.boundingClientRect as DOMRect); // fresh at callback time\n if (useViewport) {\n idle(() => {\n const cc = candidates.get(el); // re-resolve: href may have changed\n if (cc && !loadedView.has(cc.url)) load(el, cc.url, 0, false);\n });\n }\n } else {\n visible.delete(el);\n rectCache.delete(el);\n const c = candidates.get(el);\n if (c && c.emitted > 0) emit(el, c, 0, \"proximity\"); // scrolled away — clear affordance\n }\n }\n },\n { rootMargin: \"0px\" },\n );\n\n const mo = new MutationObserver((muts) => {\n for (const m of muts) {\n if (m.type === \"attributes\") {\n if (m.target instanceof HTMLAnchorElement) consider(m.target);\n continue;\n }\n m.addedNodes.forEach((n) => {\n if (!(n instanceof Element)) return;\n if ((n as Element).matches?.(\"a[href]\")) consider(n as HTMLAnchorElement);\n n.querySelectorAll?.<HTMLAnchorElement>(\"a[href]\").forEach(consider);\n });\n m.removedNodes.forEach((n) => {\n if (!(n instanceof Element)) return;\n if ((n as Element).matches?.(\"a[href]\")) drop(n as HTMLAnchorElement);\n n.querySelectorAll?.(\"a[href]\").forEach((el) => drop(el as HTMLAnchorElement));\n });\n }\n });\n\n // ---- the scoring loop (cached rects — no per-frame layout reads) ----------\n\n function refreshRects() {\n for (const el of visible) rectCache.set(el, el.getBoundingClientRect());\n rectsDirty = false;\n }\n\n function kick() {\n if (!raf && !destroyed && (useProximity || useTrajectory)) raf = requestAnimationFrame(tick);\n }\n\n function tick(t: number) {\n if (destroyed) { raf = 0; return; }\n if (document.hidden || t - lastMove > 500) { raf = 0; return; }\n // Re-measure on demand (scroll/resize) and on a throttle, so layout shifts\n // that don't fire scroll/resize (accordions, image/font loads) can't leave\n // the cache stale. Only the small `visible` set is read, batched.\n if (rectsDirty || t - lastMeasure > 250) { refreshRects(); lastMeasure = t; }\n // The velocity EMA only updates on pointermove; if the cursor has paused,\n // drop the stale heading so trajectory can't fire for a link we stopped short of.\n if (t - lastMove > 80) { vel.x = 0; vel.y = 0; }\n for (const el of visible) {\n const c = candidates.get(el);\n if (!c || loadedView.has(c.url)) continue;\n const r = rectCache.get(el);\n if (!r) continue;\n const prox = useProximity ? proximityScore(pointer.x, pointer.y, r, opts.proximityRadius) : 0;\n const traj = useTrajectory ? trajectoryScore(pointer.x, pointer.y, vel, r) : 0;\n const confidence = Math.max(prox, traj);\n const signal: Signal = traj >= prox ? \"trajectory\" : \"proximity\";\n\n if (confidence < 0.05) {\n c.armedFrames = 0;\n emit(el, c, 0, signal);\n continue;\n }\n\n let wantPrerender = false;\n if (opts.prerenderThreshold !== false && confidence >= opts.prerenderThreshold) {\n c.armedFrames++;\n if (c.armedFrames >= ARM_FRAMES) wantPrerender = true;\n } else {\n c.armedFrames = 0;\n }\n\n if (confidence >= opts.intentThreshold || wantPrerender) {\n load(el, c.url, confidence, wantPrerender);\n }\n emit(el, c, confidence, signal);\n }\n raf = requestAnimationFrame(tick);\n }\n\n // ---- event wiring --------------------------------------------------------\n\n function onMove(e: PointerEvent) {\n updateVelocity(vel, prevSample, e.clientX, e.clientY, e.timeStamp);\n prevSample = { x: e.clientX, y: e.clientY, t: e.timeStamp };\n pointer.x = e.clientX;\n pointer.y = e.clientY;\n lastMove = now();\n kick();\n }\n\n let hovered: HTMLAnchorElement | null = null;\n let hoverTimer = 0;\n function onOver(e: PointerEvent) {\n const a = (e.target as Element)?.closest?.(\"a[href]\") as HTMLAnchorElement | null;\n if (!a || a === hovered) return;\n hovered = a;\n clearTimeout(hoverTimer);\n const c = consider(a);\n if (!c || loadedView.has(c.url)) return;\n hoverTimer = window.setTimeout(() => {\n if (hovered === a) load(a, c.url, 1, true);\n }, opts.hoverDelay);\n }\n function onOut(e: PointerEvent) {\n // pointerout fires when crossing onto a child of the link — ignore those.\n if (hovered && e.relatedTarget instanceof Node && hovered.contains(e.relatedTarget)) return;\n hovered = null;\n clearTimeout(hoverTimer);\n }\n\n function onPress(e: Event) {\n const a = (e.target as Element)?.closest?.(\"a[href]\") as HTMLAnchorElement | null;\n if (!a) return;\n const c = consider(a);\n if (c && !loadedView.has(c.url)) load(a, c.url, 1, false);\n }\n\n function onScroll() {\n rectsDirty = true;\n }\n function onVisibility() {\n if (!document.hidden) {\n lastMove = now();\n kick();\n }\n }\n\n function idle(fn: () => void) {\n const ric = (window as Window & { requestIdleCallback?: (cb: () => void) => number }).requestIdleCallback;\n const guarded = () => { if (!destroyed) fn(); };\n if (ric) ric(guarded);\n else setTimeout(guarded, 1);\n }\n\n // ---- boot ----------------------------------------------------------------\n\n scan();\n // documentElement, not body — body may be null if intently() runs in <head>.\n mo.observe(scopeEl ?? document.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"href\"],\n });\n window.addEventListener(\"pointermove\", onMove, { passive: true });\n if (useHover) {\n window.addEventListener(\"pointerover\", onOver, { passive: true });\n window.addEventListener(\"pointerout\", onOut, { passive: true });\n }\n if (usePress) {\n window.addEventListener(\"pointerdown\", onPress, { passive: true });\n window.addEventListener(\"touchstart\", onPress, { passive: true });\n }\n window.addEventListener(\"scroll\", onScroll, { passive: true, capture: true });\n window.addEventListener(\"resize\", onScroll, { passive: true });\n document.addEventListener(\"visibilitychange\", onVisibility);\n\n return {\n prefetch: (url) => {\n const used = loader.load(url, \"prefetch\");\n if (used) loadedView.add(url);\n },\n prerender: (url) => {\n const used = loader.load(url, \"prerender\");\n if (used) loadedView.add(url);\n },\n destroy() {\n destroyed = true;\n if (raf) cancelAnimationFrame(raf);\n clearTimeout(hoverTimer);\n io.disconnect();\n mo.disconnect();\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerover\", onOver);\n window.removeEventListener(\"pointerout\", onOut);\n window.removeEventListener(\"pointerdown\", onPress);\n window.removeEventListener(\"touchstart\", onPress);\n window.removeEventListener(\"scroll\", onScroll, { capture: true });\n window.removeEventListener(\"resize\", onScroll);\n document.removeEventListener(\"visibilitychange\", onVisibility);\n loader.destroy();\n candidates.clear();\n visible.clear();\n rectCache.clear();\n },\n loaded: loadedView,\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export { I as IntentlyHandle, a as IntentlyOptions, P as PredictInfo, S as Signal, b as Strategy, i as intently } from './core-N6dbpDzv.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The prediction math, lifted from the input-anticipation work
|
|
5
|
+
* (https://seangeng.com/writing/interfaces-that-anticipate-input). Same engine
|
|
6
|
+
* that warms a focus ring — here it scores how likely a link is your next click.
|
|
7
|
+
*/
|
|
8
|
+
interface Rect {
|
|
9
|
+
left: number;
|
|
10
|
+
right: number;
|
|
11
|
+
top: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
}
|
|
14
|
+
interface Velocity {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
}
|
|
18
|
+
/** Distance from a point to the nearest edge of a rect (0 if inside). */
|
|
19
|
+
declare function distanceToRect(x: number, y: number, r: Rect): number;
|
|
20
|
+
/** Turn a distance into 0–1 intent via a falloff curve. exponent=2 reads best. */
|
|
21
|
+
declare function falloff(distance: number, radius: number, exponent?: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* Proximity confidence: how close is the cursor to this rect, 0–1.
|
|
24
|
+
*/
|
|
25
|
+
declare function proximityScore(x: number, y: number, r: Rect, radius: number): number;
|
|
26
|
+
/**
|
|
27
|
+
* Trajectory confidence: is the cursor *heading at* this rect, 0–1. Uses the
|
|
28
|
+
* dot product of the (normalized) velocity with the direction to the rect's
|
|
29
|
+
* center, gated by a forward cone so a glancing pass scores ~0. Returns 0 when
|
|
30
|
+
* the pointer is too slow to have a meaningful heading.
|
|
31
|
+
*/
|
|
32
|
+
declare function trajectoryScore(x: number, y: number, v: Velocity, r: Rect, cone?: number): number;
|
|
33
|
+
/** Exponential moving average of pointer velocity, in px/ms. */
|
|
34
|
+
declare function updateVelocity(v: Velocity, prev: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
t: number;
|
|
38
|
+
} | null, x: number, y: number, t: number, smoothing?: number): void;
|
|
39
|
+
|
|
40
|
+
export { type Rect, type Velocity, distanceToRect, falloff, proximityScore, trajectoryScore, updateVelocity };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export { I as IntentlyHandle, a as IntentlyOptions, P as PredictInfo, S as Signal, b as Strategy, i as intently } from './core-N6dbpDzv.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The prediction math, lifted from the input-anticipation work
|
|
5
|
+
* (https://seangeng.com/writing/interfaces-that-anticipate-input). Same engine
|
|
6
|
+
* that warms a focus ring — here it scores how likely a link is your next click.
|
|
7
|
+
*/
|
|
8
|
+
interface Rect {
|
|
9
|
+
left: number;
|
|
10
|
+
right: number;
|
|
11
|
+
top: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
}
|
|
14
|
+
interface Velocity {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
}
|
|
18
|
+
/** Distance from a point to the nearest edge of a rect (0 if inside). */
|
|
19
|
+
declare function distanceToRect(x: number, y: number, r: Rect): number;
|
|
20
|
+
/** Turn a distance into 0–1 intent via a falloff curve. exponent=2 reads best. */
|
|
21
|
+
declare function falloff(distance: number, radius: number, exponent?: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* Proximity confidence: how close is the cursor to this rect, 0–1.
|
|
24
|
+
*/
|
|
25
|
+
declare function proximityScore(x: number, y: number, r: Rect, radius: number): number;
|
|
26
|
+
/**
|
|
27
|
+
* Trajectory confidence: is the cursor *heading at* this rect, 0–1. Uses the
|
|
28
|
+
* dot product of the (normalized) velocity with the direction to the rect's
|
|
29
|
+
* center, gated by a forward cone so a glancing pass scores ~0. Returns 0 when
|
|
30
|
+
* the pointer is too slow to have a meaningful heading.
|
|
31
|
+
*/
|
|
32
|
+
declare function trajectoryScore(x: number, y: number, v: Velocity, r: Rect, cone?: number): number;
|
|
33
|
+
/** Exponential moving average of pointer velocity, in px/ms. */
|
|
34
|
+
declare function updateVelocity(v: Velocity, prev: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
t: number;
|
|
38
|
+
} | null, x: number, y: number, t: number, smoothing?: number): void;
|
|
39
|
+
|
|
40
|
+
export { type Rect, type Velocity, distanceToRect, falloff, proximityScore, trajectoryScore, updateVelocity };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|