phase 0.0.6 → 0.0.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.
@@ -1207,6 +1207,415 @@ function createPointer(options) {
1207
1207
  };
1208
1208
  }
1209
1209
  //#endregion
1210
- export { invalidDurationError as _, whenIdle as a, serverContextError as b, createRenderState as c, createLifecycle as d, readMediaQuery as f, PhaseError as g, createTicker as h, prefersReducedMotion as i, createScrollProgress as l, createSight as m, createMutation as n, readDpr as o, subscribeMediaQuery as p, REDUCED_MOTION_QUERY as r, subscribeDpr as s, createPointer as t, createLoop as u, isPhaseError as v, linkAbortSignal as x, missingContextError as y };
1210
+ //#region src/core/_internal/pool/ro-pool.ts
1211
+ let observer = null;
1212
+ const callbacks = /* @__PURE__ */ new Map();
1213
+ /**
1214
+ * Observe an element via a singleton ResizeObserver.
1215
+ * One RO instance for the entire page. Per-element `box` options are
1216
+ * forwarded to `ResizeObserver.observe()`.
1217
+ *
1218
+ * @returns Cleanup function that unobserves the element.
1219
+ */
1220
+ function observeResize(element, callback, box) {
1221
+ callbacks.set(element, callback);
1222
+ getObserver().observe(element, box ? { box } : void 0);
1223
+ let disposed = false;
1224
+ return () => {
1225
+ if (disposed) return;
1226
+ disposed = true;
1227
+ if (callbacks.get(element) === callback) {
1228
+ callbacks.delete(element);
1229
+ observer?.unobserve(element);
1230
+ }
1231
+ };
1232
+ }
1233
+ /** Lazy-created singleton. RO takes zero constructor options, so one instance can observe everything. */
1234
+ function getObserver() {
1235
+ if (!observer) observer = new ResizeObserver((entries) => {
1236
+ for (const entry of entries) {
1237
+ const cb = callbacks.get(entry.target);
1238
+ if (cb) cb(entry);
1239
+ }
1240
+ });
1241
+ return observer;
1242
+ }
1243
+ //#endregion
1244
+ //#region src/core/scroll/index.ts
1245
+ /**
1246
+ * Lifecycle-aware scroll tracker. Reads `scrollLeft`/`scrollTop` once per rAF
1247
+ * frame and reads the reflow-heavy geometry (`scrollWidth`/`clientWidth`) only
1248
+ * on resize or explicit `measure()`, never on the scroll path. Auto-pauses when
1249
+ * the element is off-screen.
1250
+ *
1251
+ * This is to `scroll` + `scrollWidth` what `createPointer` is to `pointermove`
1252
+ * + `getBoundingClientRect`: the layout read is batched off the hot path so the
1253
+ * per-scroll work is a single cheap position read plus math on cached geometry.
1254
+ */
1255
+ function createScroll(options) {
1256
+ if (typeof document === "undefined") serverContextError("createScroll");
1257
+ const { element, onScroll, onPhaseChange, visibility = "pause", intersectionOptions, signal } = options;
1258
+ if (!element) noElementError("createScroll");
1259
+ let _phase = "paused";
1260
+ let _reason = "initial";
1261
+ let stopped = false;
1262
+ const _state = {
1263
+ x: 0,
1264
+ y: 0,
1265
+ maxX: 0,
1266
+ maxY: 0,
1267
+ progressX: 0,
1268
+ progressY: 0,
1269
+ visibleX: 1,
1270
+ visibleY: 1
1271
+ };
1272
+ let rafId = 0;
1273
+ let dirty = false;
1274
+ let listenersAttached = false;
1275
+ let unobserveRO;
1276
+ function setPhase(phase, reason) {
1277
+ const prev = _phase;
1278
+ _phase = phase;
1279
+ _reason = reason;
1280
+ if (prev !== phase) onPhaseChange?.(phase, reason);
1281
+ }
1282
+ function computePosition() {
1283
+ const { maxX, maxY } = _state;
1284
+ const x = element.scrollLeft;
1285
+ const y = element.scrollTop;
1286
+ _state.x = x < 0 ? 0 : x > maxX ? maxX : x;
1287
+ _state.y = y < 0 ? 0 : y > maxY ? maxY : y;
1288
+ _state.progressX = maxX > 0 ? _state.x / maxX : 0;
1289
+ _state.progressY = maxY > 0 ? _state.y / maxY : 0;
1290
+ }
1291
+ function measure() {
1292
+ if (stopped || !listenersAttached) return;
1293
+ const scrollWidth = element.scrollWidth;
1294
+ const clientWidth = element.clientWidth;
1295
+ const scrollHeight = element.scrollHeight;
1296
+ const clientHeight = element.clientHeight;
1297
+ const maxX = scrollWidth - clientWidth;
1298
+ const maxY = scrollHeight - clientHeight;
1299
+ _state.maxX = maxX > 0 ? maxX : 0;
1300
+ _state.maxY = maxY > 0 ? maxY : 0;
1301
+ _state.visibleX = maxX > 0 ? clientWidth / scrollWidth : 1;
1302
+ _state.visibleY = maxY > 0 ? clientHeight / scrollHeight : 1;
1303
+ computePosition();
1304
+ onScroll(_state);
1305
+ }
1306
+ function flush() {
1307
+ rafId = 0;
1308
+ if (!dirty || stopped) return;
1309
+ dirty = false;
1310
+ computePosition();
1311
+ onScroll(_state);
1312
+ }
1313
+ function scheduleFlush() {
1314
+ if (rafId !== 0) return;
1315
+ rafId = requestAnimationFrame(flush);
1316
+ }
1317
+ function cancelFlush() {
1318
+ if (rafId !== 0) {
1319
+ cancelAnimationFrame(rafId);
1320
+ rafId = 0;
1321
+ }
1322
+ dirty = false;
1323
+ }
1324
+ function onScrollEvent() {
1325
+ if (stopped) return;
1326
+ dirty = true;
1327
+ scheduleFlush();
1328
+ }
1329
+ function onROResize() {
1330
+ if (stopped) return;
1331
+ measure();
1332
+ }
1333
+ function attachListeners() {
1334
+ if (listenersAttached) return;
1335
+ listenersAttached = true;
1336
+ element.addEventListener("scroll", onScrollEvent, { passive: true });
1337
+ unobserveRO = observeResize(element, onROResize);
1338
+ measure();
1339
+ }
1340
+ function detachListeners() {
1341
+ if (!listenersAttached) return;
1342
+ listenersAttached = false;
1343
+ element.removeEventListener("scroll", onScrollEvent);
1344
+ unobserveRO?.();
1345
+ unobserveRO = void 0;
1346
+ cancelFlush();
1347
+ }
1348
+ let cleanupVisibility;
1349
+ if (visibility === "pause") {
1350
+ let elementInView = false;
1351
+ let documentVisible = !document.hidden;
1352
+ function recompute() {
1353
+ if (stopped) return;
1354
+ const shouldTrack = documentVisible && elementInView;
1355
+ if (shouldTrack && !listenersAttached) {
1356
+ setPhase("tracking", "started");
1357
+ attachListeners();
1358
+ } else if (!shouldTrack && listenersAttached) {
1359
+ detachListeners();
1360
+ setPhase("paused", "sight");
1361
+ }
1362
+ }
1363
+ function onVisChange() {
1364
+ documentVisible = !document.hidden;
1365
+ recompute();
1366
+ }
1367
+ function onPageShow(event) {
1368
+ if (!event.persisted) return;
1369
+ documentVisible = true;
1370
+ recompute();
1371
+ }
1372
+ document.addEventListener("visibilitychange", onVisChange);
1373
+ window.addEventListener("pageshow", onPageShow);
1374
+ const unobserveIO = observeIntersection({
1375
+ element,
1376
+ onIntersect: (entry) => {
1377
+ elementInView = entry.isIntersecting;
1378
+ recompute();
1379
+ },
1380
+ ...intersectionOptions
1381
+ });
1382
+ cleanupVisibility = () => {
1383
+ document.removeEventListener("visibilitychange", onVisChange);
1384
+ window.removeEventListener("pageshow", onPageShow);
1385
+ unobserveIO();
1386
+ };
1387
+ } else {
1388
+ setPhase("tracking", "started");
1389
+ attachListeners();
1390
+ }
1391
+ let unlinkAbort;
1392
+ function stop() {
1393
+ if (stopped) return;
1394
+ stopped = true;
1395
+ unlinkAbort?.();
1396
+ cleanupVisibility?.();
1397
+ detachListeners();
1398
+ cancelFlush();
1399
+ setPhase("stopped", "disposed");
1400
+ }
1401
+ unlinkAbort = linkAbortSignal(signal, stop);
1402
+ return {
1403
+ get phase() {
1404
+ return _phase;
1405
+ },
1406
+ get phaseReason() {
1407
+ return _reason;
1408
+ },
1409
+ get state() {
1410
+ return _state;
1411
+ },
1412
+ measure,
1413
+ stop
1414
+ };
1415
+ }
1416
+ //#endregion
1417
+ //#region src/core/throttle/index.ts
1418
+ /**
1419
+ * Frame-aligned, visibility-aware throttle. Leading calls fire synchronously;
1420
+ * a pending trailing call rides a one-shot rAF chain and fires with the latest
1421
+ * value on the first frame at or past `interval`. While the document is hidden
1422
+ * nothing is scheduled: a pending call is flushed or dropped per `hidden`, and
1423
+ * new calls are recorded but deferred until the document is visible again.
1424
+ *
1425
+ * @remarks
1426
+ * `call` takes exactly one value and stores it by reference, so the hot path
1427
+ * never allocates. Trailing calls read the value at fire time.
1428
+ */
1429
+ function createThrottle(options) {
1430
+ if (typeof document === "undefined") serverContextError("createThrottle");
1431
+ const { callback, interval, edge = "both", hidden = "flush", signal } = options;
1432
+ const leading = edge !== "trailing";
1433
+ const trailing = edge !== "leading";
1434
+ let stopped = false;
1435
+ let pending = false;
1436
+ let lastFire = 0;
1437
+ let rafId = 0;
1438
+ let documentVisible = !document.hidden;
1439
+ let latest = void 0;
1440
+ function fire(now) {
1441
+ lastFire = now;
1442
+ pending = false;
1443
+ callback(latest);
1444
+ }
1445
+ function cancelRaf() {
1446
+ if (rafId !== 0) {
1447
+ cancelAnimationFrame(rafId);
1448
+ rafId = 0;
1449
+ }
1450
+ }
1451
+ function tick() {
1452
+ rafId = 0;
1453
+ if (stopped || !pending) return;
1454
+ const now = performance.now();
1455
+ if (now - lastFire >= interval) fire(now);
1456
+ else rafId = requestAnimationFrame(tick);
1457
+ }
1458
+ function scheduleRaf() {
1459
+ if (rafId === 0) rafId = requestAnimationFrame(tick);
1460
+ }
1461
+ function call(value) {
1462
+ if (stopped) return;
1463
+ latest = value;
1464
+ if (!documentVisible) {
1465
+ pending = true;
1466
+ return;
1467
+ }
1468
+ const now = performance.now();
1469
+ if (now - lastFire >= interval) {
1470
+ if (leading) {
1471
+ fire(now);
1472
+ return;
1473
+ }
1474
+ lastFire = now;
1475
+ }
1476
+ if (trailing) {
1477
+ pending = true;
1478
+ scheduleRaf();
1479
+ }
1480
+ }
1481
+ function flush() {
1482
+ if (stopped || !pending) return;
1483
+ cancelRaf();
1484
+ fire(performance.now());
1485
+ }
1486
+ function cancel() {
1487
+ if (stopped) return;
1488
+ cancelRaf();
1489
+ pending = false;
1490
+ lastFire = 0;
1491
+ }
1492
+ function onVisibilityChange() {
1493
+ documentVisible = !document.hidden;
1494
+ if (stopped) return;
1495
+ if (!documentVisible) {
1496
+ cancelRaf();
1497
+ if (pending) if (hidden === "flush") fire(performance.now());
1498
+ else pending = false;
1499
+ } else if (pending) scheduleRaf();
1500
+ }
1501
+ function onPageShow(event) {
1502
+ if (!event.persisted) return;
1503
+ documentVisible = true;
1504
+ if (!stopped && pending) scheduleRaf();
1505
+ }
1506
+ document.addEventListener("visibilitychange", onVisibilityChange);
1507
+ window.addEventListener("pageshow", onPageShow);
1508
+ let unlinkAbort;
1509
+ function stop() {
1510
+ if (stopped) return;
1511
+ stopped = true;
1512
+ unlinkAbort?.();
1513
+ document.removeEventListener("visibilitychange", onVisibilityChange);
1514
+ window.removeEventListener("pageshow", onPageShow);
1515
+ cancelRaf();
1516
+ pending = false;
1517
+ }
1518
+ unlinkAbort = linkAbortSignal(signal, stop);
1519
+ return {
1520
+ call,
1521
+ flush,
1522
+ cancel,
1523
+ get pending() {
1524
+ return pending;
1525
+ },
1526
+ stop
1527
+ };
1528
+ }
1529
+ //#endregion
1530
+ //#region src/core/debounce/index.ts
1531
+ /**
1532
+ * Visibility-aware trailing debounce. Fires the callback with the latest
1533
+ * value once `wait` milliseconds pass without a new call. While the document
1534
+ * is hidden no timer runs: a pending call is flushed or dropped per `hidden`,
1535
+ * and new calls are recorded but wait until the document is visible again,
1536
+ * when the quiet timer restarts.
1537
+ */
1538
+ function createDebounce(options) {
1539
+ if (typeof document === "undefined") serverContextError("createDebounce");
1540
+ const { callback, wait, hidden = "flush", signal } = options;
1541
+ let stopped = false;
1542
+ let pending = false;
1543
+ let timer;
1544
+ let documentVisible = !document.hidden;
1545
+ let latest = void 0;
1546
+ function fire() {
1547
+ pending = false;
1548
+ callback(latest);
1549
+ }
1550
+ function clearTimer() {
1551
+ if (timer !== void 0) {
1552
+ clearTimeout(timer);
1553
+ timer = void 0;
1554
+ }
1555
+ }
1556
+ function onTimer() {
1557
+ timer = void 0;
1558
+ if (stopped || !pending) return;
1559
+ fire();
1560
+ }
1561
+ function startTimer() {
1562
+ clearTimer();
1563
+ timer = setTimeout(onTimer, wait);
1564
+ }
1565
+ function call(value) {
1566
+ if (stopped) return;
1567
+ latest = value;
1568
+ pending = true;
1569
+ if (documentVisible) startTimer();
1570
+ }
1571
+ function flush() {
1572
+ if (stopped || !pending) return;
1573
+ clearTimer();
1574
+ fire();
1575
+ }
1576
+ function cancel() {
1577
+ if (stopped) return;
1578
+ clearTimer();
1579
+ pending = false;
1580
+ }
1581
+ function onVisibilityChange() {
1582
+ documentVisible = !document.hidden;
1583
+ if (stopped) return;
1584
+ if (!documentVisible) {
1585
+ clearTimer();
1586
+ if (pending) if (hidden === "flush") fire();
1587
+ else pending = false;
1588
+ } else if (pending) startTimer();
1589
+ }
1590
+ function onPageShow(event) {
1591
+ if (!event.persisted) return;
1592
+ documentVisible = true;
1593
+ if (!stopped && pending) startTimer();
1594
+ }
1595
+ document.addEventListener("visibilitychange", onVisibilityChange);
1596
+ window.addEventListener("pageshow", onPageShow);
1597
+ let unlinkAbort;
1598
+ function stop() {
1599
+ if (stopped) return;
1600
+ stopped = true;
1601
+ unlinkAbort?.();
1602
+ document.removeEventListener("visibilitychange", onVisibilityChange);
1603
+ window.removeEventListener("pageshow", onPageShow);
1604
+ clearTimer();
1605
+ pending = false;
1606
+ }
1607
+ unlinkAbort = linkAbortSignal(signal, stop);
1608
+ return {
1609
+ call,
1610
+ flush,
1611
+ cancel,
1612
+ get pending() {
1613
+ return pending;
1614
+ },
1615
+ stop
1616
+ };
1617
+ }
1618
+ //#endregion
1619
+ export { missingContextError as C, isPhaseError as S, linkAbortSignal as T, subscribeMediaQuery as _, createPointer as a, PhaseError as b, prefersReducedMotion as c, subscribeDpr as d, createRenderState as f, readMediaQuery as g, createLifecycle as h, observeResize as i, whenIdle as l, createLoop as m, createThrottle as n, createMutation as o, createScrollProgress as p, createScroll as r, REDUCED_MOTION_QUERY as s, createDebounce as t, readDpr as u, createSight as v, serverContextError as w, invalidDurationError as x, createTicker as y };
1211
1620
 
1212
- //# sourceMappingURL=pointer-D5F7_Jjs.js.map
1621
+ //# sourceMappingURL=debounce-D5ugkrXN.js.map