UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

70 lines (69 loc) 2.85 kB
function createPrefetchIntent(options) { const { onPrefetch, maxReach = 500, perpWeight = 5, minSpeed = 8 } = options, done = /* @__PURE__ */ new Set(); let rects = [], px = 0, py = 0, vx = 0, vy = 0, moveCount = 0, lastPrefetchMove = 0; function setRects(newRects) { rects = newRects.filter((r) => !done.has(r.h)); } function move(x, y, dx, dy) { moveCount++; const smooth = moveCount < 3 ? 0.3 : 0.6; vx = vx * smooth + dx * (1 - smooth), vy = vy * smooth + dy * (1 - smooth), px = x, py = y; const speed = Math.sqrt(vx * vx + vy * vy); if (speed < minSpeed) return; const ux = vx / speed, uy = vy / speed; let best = 1 / 0, href = ""; for (const { r, h } of rects) { const cx = (r.left + r.right) / 2 - px, cy = (r.top + r.bottom) / 2 - py, dist = Math.sqrt(cx * cx + cy * cy), along = cx * ux + cy * uy; if (along < 0) continue; const perpX = cx - along * ux, perpY = cy - along * uy, perp = Math.sqrt(perpX * perpX + perpY * perpY), baseRadius = Math.max(r.width, r.height) / 2 + 30, distanceFactor = Math.max(0.2, 1 - dist / 1e3), radius = baseRadius * distanceFactor + 20; if (perp > radius) continue; const score = along + perp * perpWeight; score < best && (best = score, href = h); } href && best < maxReach && moveCount - lastPrefetchMove > 1 && (done.add(href), rects = rects.filter((r) => r.h !== href), lastPrefetchMove = moveCount, onPrefetch(href)); } const nodes = /* @__PURE__ */ new Map(); function observe(el, href) { return nodes.set(el, href), () => { nodes.delete(el), done.delete(href); }; } return { setRects, move, observe, nodes, done }; } let instance = null, started = !1; function startPrefetchIntent(onPrefetch) { if (started) return instance; started = !0, instance = createPrefetchIntent({ onPrefetch }); let frame = 0, px = 0, py = 0; function measure() { if (!instance.nodes.size) return setTimeout(measure, 300); const io = new IntersectionObserver((entries) => { io.disconnect(), instance.setRects( entries.filter((e) => e.isIntersecting).map((e) => ({ r: e.boundingClientRect, h: instance.nodes.get(e.target) })).filter((x) => x.h) ), setTimeout(measure, 300); }); instance.nodes.forEach((_, el) => io.observe(el)); } return measure(), document.addEventListener( "mousemove", (e) => { if (++frame % 4) return; const dx = e.clientX - px, dy = e.clientY - py; px = e.clientX, py = e.clientY, instance.move(px, py, dx, dy); }, { passive: !0 } ), instance; } function observePrefetchIntent(el, href) { return instance ? instance.observe(el, href) : () => { }; } export { createPrefetchIntent, observePrefetchIntent, startPrefetchIntent }; //# sourceMappingURL=prefetchIntent.js.map