js.foresight 3.0.1 → 3.1.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.
Files changed (97) hide show
  1. package/README.md +120 -5
  2. package/dist/{src/types/types.d.ts → index.d.mts} +156 -67
  3. package/dist/index.d.ts +61 -47
  4. package/dist/index.js +2 -6
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +2 -6
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +5 -12
  9. package/dist/Manager/ForesightManager.d.ts +0 -89
  10. package/dist/Manager/ForesightManager.d.ts.map +0 -1
  11. package/dist/Manager/ForesightManager.js +0 -639
  12. package/dist/Manager/ForesightManager.js.map +0 -1
  13. package/dist/Manager/constants.d.ts +0 -23
  14. package/dist/Manager/constants.d.ts.map +0 -1
  15. package/dist/Manager/constants.js +0 -24
  16. package/dist/Manager/constants.js.map +0 -1
  17. package/dist/Manager/helpers/clampNumber.d.ts +0 -2
  18. package/dist/Manager/helpers/clampNumber.d.ts.map +0 -1
  19. package/dist/Manager/helpers/clampNumber.js +0 -10
  20. package/dist/Manager/helpers/clampNumber.js.map +0 -1
  21. package/dist/Manager/helpers/getFocusedElementIndex.d.ts +0 -15
  22. package/dist/Manager/helpers/getFocusedElementIndex.d.ts.map +0 -1
  23. package/dist/Manager/helpers/getFocusedElementIndex.js +0 -27
  24. package/dist/Manager/helpers/getFocusedElementIndex.js.map +0 -1
  25. package/dist/Manager/helpers/getScrollDirection.d.ts +0 -3
  26. package/dist/Manager/helpers/getScrollDirection.d.ts.map +0 -1
  27. package/dist/Manager/helpers/getScrollDirection.js +0 -21
  28. package/dist/Manager/helpers/getScrollDirection.js.map +0 -1
  29. package/dist/Manager/helpers/lineSigmentIntersectsRect.d.ts +0 -12
  30. package/dist/Manager/helpers/lineSigmentIntersectsRect.d.ts.map +0 -1
  31. package/dist/Manager/helpers/lineSigmentIntersectsRect.js +0 -52
  32. package/dist/Manager/helpers/lineSigmentIntersectsRect.js.map +0 -1
  33. package/dist/Manager/helpers/predictNextMousePosition.d.ts +0 -19
  34. package/dist/Manager/helpers/predictNextMousePosition.d.ts.map +0 -1
  35. package/dist/Manager/helpers/predictNextMousePosition.js +0 -43
  36. package/dist/Manager/helpers/predictNextMousePosition.js.map +0 -1
  37. package/dist/Manager/helpers/predictNextScrollPosition.d.ts +0 -6
  38. package/dist/Manager/helpers/predictNextScrollPosition.d.ts.map +0 -1
  39. package/dist/Manager/helpers/predictNextScrollPosition.js +0 -20
  40. package/dist/Manager/helpers/predictNextScrollPosition.js.map +0 -1
  41. package/dist/Manager/helpers/rectAndHitSlop.d.ts +0 -33
  42. package/dist/Manager/helpers/rectAndHitSlop.d.ts.map +0 -1
  43. package/dist/Manager/helpers/rectAndHitSlop.js +0 -66
  44. package/dist/Manager/helpers/rectAndHitSlop.js.map +0 -1
  45. package/dist/Manager/helpers/shouldUpdateSetting.d.ts +0 -11
  46. package/dist/Manager/helpers/shouldUpdateSetting.d.ts.map +0 -1
  47. package/dist/Manager/helpers/shouldUpdateSetting.js +0 -16
  48. package/dist/Manager/helpers/shouldUpdateSetting.js.map +0 -1
  49. package/dist/helpers/shouldRegister.d.ts +0 -8
  50. package/dist/helpers/shouldRegister.d.ts.map +0 -1
  51. package/dist/helpers/shouldRegister.js +0 -31
  52. package/dist/helpers/shouldRegister.js.map +0 -1
  53. package/dist/index.d.ts.map +0 -1
  54. package/dist/src/Manager/ForesightManager.d.ts +0 -89
  55. package/dist/src/Manager/ForesightManager.d.ts.map +0 -1
  56. package/dist/src/Manager/ForesightManager.test.d.ts +0 -2
  57. package/dist/src/Manager/ForesightManager.test.d.ts.map +0 -1
  58. package/dist/src/Manager/constants.d.ts +0 -23
  59. package/dist/src/Manager/constants.d.ts.map +0 -1
  60. package/dist/src/Manager/helpers/clampNumber.d.ts +0 -2
  61. package/dist/src/Manager/helpers/clampNumber.d.ts.map +0 -1
  62. package/dist/src/Manager/helpers/clampNumber.test.d.ts +0 -2
  63. package/dist/src/Manager/helpers/clampNumber.test.d.ts.map +0 -1
  64. package/dist/src/Manager/helpers/getFocusedElementIndex.d.ts +0 -15
  65. package/dist/src/Manager/helpers/getFocusedElementIndex.d.ts.map +0 -1
  66. package/dist/src/Manager/helpers/getFocusedElementIndex.test.d.ts +0 -2
  67. package/dist/src/Manager/helpers/getFocusedElementIndex.test.d.ts.map +0 -1
  68. package/dist/src/Manager/helpers/getScrollDirection.d.ts +0 -3
  69. package/dist/src/Manager/helpers/getScrollDirection.d.ts.map +0 -1
  70. package/dist/src/Manager/helpers/lineSegmentIntersectsRect.test.d.ts +0 -2
  71. package/dist/src/Manager/helpers/lineSegmentIntersectsRect.test.d.ts.map +0 -1
  72. package/dist/src/Manager/helpers/lineSigmentIntersectsRect.d.ts +0 -12
  73. package/dist/src/Manager/helpers/lineSigmentIntersectsRect.d.ts.map +0 -1
  74. package/dist/src/Manager/helpers/predictNextMousePosition.d.ts +0 -19
  75. package/dist/src/Manager/helpers/predictNextMousePosition.d.ts.map +0 -1
  76. package/dist/src/Manager/helpers/predictNextMousePosition.test.d.ts +0 -2
  77. package/dist/src/Manager/helpers/predictNextMousePosition.test.d.ts.map +0 -1
  78. package/dist/src/Manager/helpers/predictNextScrollPosition.d.ts +0 -6
  79. package/dist/src/Manager/helpers/predictNextScrollPosition.d.ts.map +0 -1
  80. package/dist/src/Manager/helpers/rectAndHitSlop.d.ts +0 -33
  81. package/dist/src/Manager/helpers/rectAndHitSlop.d.ts.map +0 -1
  82. package/dist/src/Manager/helpers/rectAndHitSlop.test.d.ts +0 -2
  83. package/dist/src/Manager/helpers/rectAndHitSlop.test.d.ts.map +0 -1
  84. package/dist/src/Manager/helpers/shouldUpdateSetting.d.ts +0 -11
  85. package/dist/src/Manager/helpers/shouldUpdateSetting.d.ts.map +0 -1
  86. package/dist/src/helpers/shouldRegister.d.ts +0 -8
  87. package/dist/src/helpers/shouldRegister.d.ts.map +0 -1
  88. package/dist/src/index.d.ts +0 -3
  89. package/dist/src/index.d.ts.map +0 -1
  90. package/dist/src/types/types.d.ts.map +0 -1
  91. package/dist/test-setup.d.ts +0 -17
  92. package/dist/test-setup.d.ts.map +0 -1
  93. package/dist/tsconfig.tsbuildinfo +0 -1
  94. package/dist/types/types.d.ts +0 -312
  95. package/dist/types/types.d.ts.map +0 -1
  96. package/dist/types/types.js +0 -2
  97. package/dist/types/types.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -39,9 +39,9 @@ type TrajectoryPositions = {
39
39
  */
40
40
  type ElementBounds = {
41
41
  /** The expanded rectangle, including hitSlop, used for interaction detection. */
42
- expandedRect: Rect;
42
+ expandedRect: Readonly<Rect>;
43
43
  /** The original bounding rectangle of the element, as returned by `getBoundingClientRect()`. */
44
- originalRect?: DOMRectReadOnly | undefined;
44
+ originalRect: DOMRectReadOnly;
45
45
  /** The hit slop values applied to this element. */
46
46
  hitSlop: Exclude<HitSlop, number>;
47
47
  };
@@ -80,12 +80,21 @@ type ForesightElementData = Required<Pick<ForesightRegisterOptions, "callback" |
80
80
  trajectoryHitData: TrajectoryHitData;
81
81
  /**
82
82
  * Is the element intersecting with the viewport, usefull to track which element we should observe or not
83
+ * Can be @undefined in the split second the element is registering
83
84
  */
84
85
  isIntersectingWithViewport: boolean;
85
86
  /**
86
87
  * The element you registered
87
88
  */
88
89
  element: ForesightElement;
90
+ /**
91
+ * If the element is currently running its callback
92
+ */
93
+ isRunningCallback: boolean;
94
+ /**
95
+ * For debugging, check if you are registering the same element multiple times.
96
+ */
97
+ registerCount: number;
89
98
  };
90
99
  type MouseCallbackCounts = {
91
100
  hover: number;
@@ -103,7 +112,7 @@ type CallbackHits = {
103
112
  tab: TabCallbackCounts;
104
113
  scroll: ScrollCallbackCounts;
105
114
  };
106
- type HitType = {
115
+ type CallbackHitType = {
107
116
  kind: "mouse";
108
117
  subType: keyof MouseCallbackCounts;
109
118
  } | {
@@ -120,6 +129,7 @@ type ForesightManagerData = {
120
129
  registeredElements: ReadonlyMap<ForesightElement, ForesightElementData>;
121
130
  globalSettings: Readonly<ForesightManagerSettings>;
122
131
  globalCallbackHits: Readonly<CallbackHits>;
132
+ eventListeners: ReadonlyMap<keyof ForesightEventMap, ForesightEventListener[]>;
123
133
  };
124
134
  type BaseForesightManagerSettings = {
125
135
  /**
@@ -187,14 +197,6 @@ type BaseForesightManagerSettings = {
187
197
  * @default 2
188
198
  */
189
199
  tabOffset: number;
190
- /**
191
- * A global callback that runs whenever a callback is fired for any
192
- * registered element, just after the element's specific callback is fired.
193
- *
194
- * @param elementData - The ForesightTarget object for the element that triggered the event.
195
- * @param managerData - Data about the ForesightManager
196
- */
197
- onAnyCallbackFired: (elementData: ForesightElementData, managerData: ForesightManagerData) => void;
198
200
  };
199
201
  /**
200
202
  * Configuration options for the ForesightManager
@@ -240,21 +242,18 @@ interface ForesightEventMap {
240
242
  elementRegistered: ElementRegisteredEvent;
241
243
  elementUnregistered: ElementUnregisteredEvent;
242
244
  elementDataUpdated: ElementDataUpdatedEvent;
243
- callbackFired: CallbackFiredEvent;
245
+ callbackInvoked: CallbackInvokedEvent;
246
+ callbackCompleted: CallbackCompletedEvent;
244
247
  mouseTrajectoryUpdate: MouseTrajectoryUpdateEvent;
245
248
  scrollTrajectoryUpdate: ScrollTrajectoryUpdateEvent;
246
249
  managerSettingsChanged: ManagerSettingsChangedEvent;
247
250
  }
248
- type ForesightEventType = keyof ForesightEventMap;
249
- interface ForesightEvent {
250
- type: ForesightEventType;
251
- timestamp: number;
252
- }
253
- interface ElementRegisteredEvent extends ForesightEvent {
251
+ type ForesightEvent = "elementRegistered" | "elementUnregistered" | "elementDataUpdated" | "callbackInvoked" | "callbackCompleted" | "mouseTrajectoryUpdate" | "scrollTrajectoryUpdate" | "managerSettingsChanged";
252
+ interface ElementRegisteredEvent extends ForesightBaseEvent {
254
253
  type: "elementRegistered";
255
254
  elementData: ForesightElementData;
256
255
  }
257
- interface ElementUnregisteredEvent extends ForesightEvent {
256
+ interface ElementUnregisteredEvent extends ForesightBaseEvent {
258
257
  type: "elementUnregistered";
259
258
  elementData: ForesightElementData;
260
259
  unregisterReason: ElementUnregisteredReason;
@@ -266,30 +265,56 @@ interface ElementUnregisteredEvent extends ForesightEvent {
266
265
  * - `apiCall`: The developer manually called the `unregister()` function for the element.
267
266
  */
268
267
  type ElementUnregisteredReason = "callbackHit" | "disconnected" | "apiCall";
269
- interface ElementDataUpdatedEvent extends ForesightEvent {
268
+ interface ElementDataUpdatedEvent extends Omit<ForesightBaseEvent, "timestamp"> {
270
269
  type: "elementDataUpdated";
271
270
  elementData: ForesightElementData;
272
- updatedProp: "bounds" | "visibility";
271
+ updatedProps: UpdatedDataPropertyNames[];
273
272
  }
274
- interface CallbackFiredEvent extends ForesightEvent {
275
- type: "callbackFired";
273
+ type UpdatedDataPropertyNames = "bounds" | "visibility";
274
+ interface CallbackInvokedEvent extends ForesightBaseEvent {
275
+ type: "callbackInvoked";
276
276
  elementData: ForesightElementData;
277
- hitType: HitType;
278
- managerData: ForesightManagerData;
277
+ hitType: CallbackHitType;
279
278
  }
280
- interface MouseTrajectoryUpdateEvent extends ForesightEvent {
279
+ interface CallbackCompletedEventBase extends ForesightBaseEvent {
280
+ type: "callbackCompleted";
281
+ elementData: ForesightElementData;
282
+ hitType: CallbackHitType;
283
+ elapsed: number;
284
+ }
285
+ type CallbackCompletedEvent = CallbackCompletedEventBase & ({
286
+ status: "success";
287
+ } | {
288
+ status: "error";
289
+ errorMessage: string;
290
+ });
291
+ interface MouseTrajectoryUpdateEvent extends Omit<ForesightBaseEvent, "timestamp"> {
281
292
  type: "mouseTrajectoryUpdate";
282
293
  trajectoryPositions: TrajectoryPositions;
283
294
  predictionEnabled: boolean;
284
295
  }
285
- interface ScrollTrajectoryUpdateEvent extends ForesightEvent {
296
+ interface ScrollTrajectoryUpdateEvent extends Omit<ForesightBaseEvent, "timestamp"> {
286
297
  type: "scrollTrajectoryUpdate";
287
298
  currentPoint: Point;
288
299
  predictedPoint: Point;
300
+ scrollDirection: ScrollDirection;
289
301
  }
290
- interface ManagerSettingsChangedEvent extends ForesightEvent {
302
+ interface ManagerSettingsChangedEvent extends ForesightBaseEvent {
291
303
  type: "managerSettingsChanged";
292
304
  managerData: ForesightManagerData;
305
+ updatedSettings: UpdatedManagerSetting[];
306
+ }
307
+ type UpdatedManagerSetting = {
308
+ [K in keyof ForesightManagerSettings]: {
309
+ setting: K;
310
+ newValue: ForesightManagerSettings[K];
311
+ oldValue: ForesightManagerSettings[K];
312
+ };
313
+ }[keyof ForesightManagerSettings];
314
+ type ForesightEventListener<K extends ForesightEvent = ForesightEvent> = (event: ForesightEventMap[K]) => void;
315
+ interface ForesightBaseEvent {
316
+ type: ForesightEvent;
317
+ timestamp: number;
293
318
  }
294
319
 
295
320
  /**
@@ -324,14 +349,15 @@ declare class ForesightManager {
324
349
  private positionObserver;
325
350
  private lastKeyDown;
326
351
  private globalListenersController;
352
+ private rafId;
353
+ private pendingMouseEvent;
327
354
  private eventListeners;
328
355
  private constructor();
329
356
  static initialize(props?: Partial<UpdateForsightManagerSettings>): ForesightManager;
330
- addEventListener<K extends ForesightEventType>(eventType: K, listener: (event: ForesightEventMap[K]) => void, options?: {
357
+ addEventListener<K extends ForesightEvent>(eventType: K, listener: ForesightEventListener<K>, options?: {
331
358
  signal?: AbortSignal;
332
359
  }): (() => void) | undefined;
333
- removeEventListener<K extends ForesightEventType>(eventType: K, listener: (event: ForesightEventMap[K]) => void): void;
334
- logSubscribers(): void;
360
+ removeEventListener<K extends ForesightEvent>(eventType: K, listener: ForesightEventListener<K>): void;
335
361
  private emit;
336
362
  get getManagerData(): Readonly<ForesightManagerData>;
337
363
  static get isInitiated(): Readonly<boolean>;
@@ -344,19 +370,8 @@ declare class ForesightManager {
344
370
  alterGlobalSettings(props?: Partial<UpdateForsightManagerSettings>): void;
345
371
  private forceUpdateAllElementBounds;
346
372
  private updatePointerState;
347
- /**
348
- * Processes elements that unregister after a single callback.
349
- *
350
- * This is a "fire-and-forget" handler. Its only goal is to trigger the
351
- * callback once. It does so if the mouse trajectory is predicted to hit the
352
- * element (if prediction is on) OR if the mouse physically hovers over it.
353
- * It does not track state, as the element is immediately unregistered.
354
- *
355
- * @param elementData - The data object for the foresight element.
356
- * @param element - The HTML element being interacted with.
357
- */
358
- private handleCallbackInteraction;
359
373
  private handleMouseMove;
374
+ private processMouseMovement;
360
375
  /**
361
376
  * Detects when registered elements are removed from the DOM and automatically unregisters them to prevent stale references.
362
377
  *
@@ -373,12 +388,11 @@ declare class ForesightManager {
373
388
  * We need an observer for that
374
389
  */
375
390
  private forceUpdateElementBounds;
376
- private updateElementBounds;
377
- private handleScrollPrefetch;
378
391
  private handlePositionChange;
392
+ private handlePositionChangeDataUpdates;
393
+ private handleScrollPrefetch;
379
394
  private initializeGlobalListeners;
380
395
  private removeGlobalListeners;
381
396
  }
382
397
 
383
- export { ForesightManager };
384
- export type { CallbackFiredEvent, ElementDataUpdatedEvent, ElementRegisteredEvent, ElementUnregisteredEvent, CallbackHits as ForesightCallbackHits, ForesightElement, ForesightElementData, ForesightEvent, ForesightManagerSettings, Rect as ForesightRect, ForesightRegisterOptions, ForesightRegisterOptionsWithoutElement, ForesightRegisterResult, HitSlop, ManagerSettingsChangedEvent, MouseTrajectoryUpdateEvent, ScrollTrajectoryUpdateEvent, UpdateForsightManagerSettings };
398
+ export { type CallbackCompletedEvent, type CallbackHitType, type CallbackHits, type CallbackInvokedEvent, type ElementDataUpdatedEvent, type ElementRegisteredEvent, type ElementUnregisteredEvent, type ForesightElement, type ForesightElementData, type ForesightEvent, ForesightManager, type ForesightManagerSettings, type Rect as ForesightRect, type ForesightRegisterOptions, type ForesightRegisterOptionsWithoutElement, type ForesightRegisterResult, type HitSlop, type ManagerSettingsChangedEvent, type MouseTrajectoryUpdateEvent, type ScrollTrajectoryUpdateEvent, type UpdateForsightManagerSettings, type UpdatedManagerSetting };
package/dist/index.js CHANGED
@@ -1,6 +1,2 @@
1
- "use strict";
2
- /*!
3
- * tabbable 6.2.0
4
- * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
5
- */var t=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"].join(","),e="undefined"==typeof Element,i=e?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,n=!e&&Element.prototype.getRootNode?function(t){var e;return null==t||null===(e=t.getRootNode)||void 0===e?void 0:e.call(t)}:function(t){return null==t?void 0:t.ownerDocument},o=function t(e,i){var n;void 0===i&&(i=!0);var o=null==e||null===(n=e.getAttribute)||void 0===n?void 0:n.call(e,"inert");return""===o||"true"===o||i&&e&&t(e.parentNode)},s=function e(n,s,r){for(var l=[],a=Array.from(n);a.length;){var c=a.shift();if(!o(c,!1))if("SLOT"===c.tagName){var h=c.assignedElements(),u=e(h.length?h:c.children,!0,r);r.flatten?l.push.apply(l,u):l.push({scopeParent:c,candidates:u})}else{i.call(c,t)&&r.filter(c)&&(s||!n.includes(c))&&l.push(c);var d=c.shadowRoot||"function"==typeof r.getShadowRoot&&r.getShadowRoot(c),g=!o(d,!1)&&(!r.shadowRootFilter||r.shadowRootFilter(c));if(d&&g){var b=e(!0===d?c.children:d.children,!0,r);r.flatten?l.push.apply(l,b):l.push({scopeParent:c,candidates:b})}else a.unshift.apply(a,c.children)}}return l},r=function(t){return!isNaN(parseInt(t.getAttribute("tabindex"),10))},l=function(t){if(!t)throw new Error("No node provided");return t.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(t.tagName)||function(t){var e,i=null==t||null===(e=t.getAttribute)||void 0===e?void 0:e.call(t,"contenteditable");return""===i||"true"===i}(t))&&!r(t)?0:t.tabIndex},a=function(t,e){return t.tabIndex===e.tabIndex?t.documentOrder-e.documentOrder:t.tabIndex-e.tabIndex},c=function(t){return"INPUT"===t.tagName},h=function(t){return function(t){return c(t)&&"radio"===t.type}(t)&&!function(t){if(!t.name)return!0;var e,i=t.form||n(t),o=function(t){return i.querySelectorAll('input[type="radio"][name="'+t+'"]')};if("undefined"!=typeof window&&void 0!==window.CSS&&"function"==typeof window.CSS.escape)e=o(window.CSS.escape(t.name));else try{e=o(t.name)}catch(t){return console.error("Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s",t.message),!1}var s=function(t,e){for(var i=0;i<t.length;i++)if(t[i].checked&&t[i].form===e)return t[i]}(e,t.form);return!s||s===t}(t)},u=function(t){var e=t.getBoundingClientRect(),i=e.width,n=e.height;return 0===i&&0===n},d=function(t,e){var o=e.displayCheck,s=e.getShadowRoot;if("hidden"===getComputedStyle(t).visibility)return!0;var r=i.call(t,"details>summary:first-of-type")?t.parentElement:t;if(i.call(r,"details:not([open]) *"))return!0;if(o&&"full"!==o&&"legacy-full"!==o){if("non-zero-area"===o)return u(t)}else{if("function"==typeof s){for(var l=t;t;){var a=t.parentElement,c=n(t);if(a&&!a.shadowRoot&&!0===s(a))return u(t);t=t.assignedSlot?t.assignedSlot:a||c===t.ownerDocument?a:c.host}t=l}if(function(t){var e,i,o,s,r=t&&n(t),l=null===(e=r)||void 0===e?void 0:e.host,a=!1;if(r&&r!==t)for(a=!!(null!==(i=l)&&void 0!==i&&null!==(o=i.ownerDocument)&&void 0!==o&&o.contains(l)||null!=t&&null!==(s=t.ownerDocument)&&void 0!==s&&s.contains(t));!a&&l;){var c,h,u;a=!(null===(h=l=null===(c=r=n(l))||void 0===c?void 0:c.host)||void 0===h||null===(u=h.ownerDocument)||void 0===u||!u.contains(l))}return a}(t))return!t.getClientRects().length;if("legacy-full"!==o)return!0}return!1},g=function(t,e){return!(e.disabled||o(e)||function(t){return c(t)&&"hidden"===t.type}(e)||d(e,t)||function(t){return"DETAILS"===t.tagName&&Array.prototype.slice.apply(t.children).some(function(t){return"SUMMARY"===t.tagName})}(e)||function(t){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(t.tagName))for(var e=t.parentElement;e;){if("FIELDSET"===e.tagName&&e.disabled){for(var n=0;n<e.children.length;n++){var o=e.children.item(n);if("LEGEND"===o.tagName)return!!i.call(e,"fieldset[disabled] *")||!o.contains(t)}return!0}e=e.parentElement}return!1}(e))},b=function(t,e){return!(h(e)||l(e)<0||!g(t,e))},p=function(t){var e=parseInt(t.getAttribute("tabindex"),10);return!!(isNaN(e)||e>=0)},f=function t(e){var i=[],n=[];return e.forEach(function(e,o){var s=!!e.scopeParent,a=s?e.scopeParent:e,c=function(t,e){var i=l(t);return i<0&&e&&!r(t)?0:i}(a,s),h=s?t(e.candidates):a;0===c?s?i.push.apply(i,h):i.push(a):n.push({documentOrder:o,tabIndex:c,item:e,isScope:s,content:h})}),n.sort(a).reduce(function(t,e){return e.isScope?t.push.apply(t,e.content):t.push(e.content),t},[]).concat(i)},m=function(e,n){var r;return r=(n=n||{}).getShadowRoot?s([e],n.includeContainer,{filter:b.bind(null,n),flatten:!1,getShadowRoot:n.getShadowRoot,shadowRootFilter:p}):function(e,n,s){if(o(e))return[];var r=Array.prototype.slice.apply(e.querySelectorAll(t));return n&&i.call(e,t)&&r.unshift(e),r.filter(s)}(e,n.includeContainer,b.bind(null,n)),f(r)};function v(){const t=window.matchMedia("(pointer: coarse)").matches&&navigator.maxTouchPoints>0,e=function(){const t=navigator.connection;return!!t&&(/2g/.test(t.effectiveType)||t.saveData)}();return{isTouchDevice:t,isLimitedConnection:e,shouldRegister:!t&&!e}}const y=2e3;function S(t,e,i,n){return t<e?console.warn(`ForesightJS: "${n}" value ${t} is below minimum bound ${e}, clamping to ${e}`):t>i&&console.warn(`ForesightJS: "${n}" value ${t} is above maximum bound ${i}, clamping to ${i}`),Math.min(Math.max(t,e),i)}function w(t,e,i){let n=0,o=1;const s=e.x-t.x,r=e.y-t.y,l=(t,e)=>{if(0===t){if(e<0)return!1}else{const i=e/t;if(t<0){if(i>o)return!1;i>n&&(n=i)}else{if(i<n)return!1;i<o&&(o=i)}}return!0};return!!l(-s,t.x-i.left)&&(!!l(s,i.right-t.x)&&(!!l(-r,t.y-i.top)&&(!!l(r,i.bottom-t.y)&&n<=o)))}function R(t){if("number"==typeof t){const e=S(t,0,y,"hitslop");return{top:e,left:e,right:e,bottom:e}}return{top:S(t.top,0,y,"hitslop - top"),left:S(t.left,0,y,"hitslop - left"),right:S(t.right,0,y,"hitslop - right"),bottom:S(t.bottom,0,y,"hitslop - bottom")}}function C(t,e){return{left:t.left-e.left,right:t.right+e.right,top:t.top-e.top,bottom:t.bottom+e.bottom}}function P(t,e){return t&&e?t.left===e.left&&t.right===e.right&&t.top===e.top&&t.bottom===e.bottom:t===e}function E(t,e){return t.x>=e.left&&t.x<=e.right&&t.y>=e.top&&t.y<=e.bottom}function O(t,e){return void 0!==t&&e!==t}var D=class{static intersect(t,e){const i=Math.max(t.left,e.left),n=Math.min(t.right,e.right),o=Math.max(t.top,e.top),s=Math.min(t.bottom,e.bottom),r=Math.max(0,n-i),l=Math.max(0,s-o);return new DOMRect(i,o,r,l)}static clip(t,e){const i={...t.toJSON(),top:t.top+e.top,left:t.left+e.left,bottom:t.bottom-e.bottom,right:t.right-e.right};return i.width=i.right-i.left,i.height=i.bottom-i.top,i}static clipOffsets(t,e){return{top:e.top-t.top,left:e.left-t.left,bottom:t.bottom-e.bottom,right:t.right-e.right}}static equals(t,e){return null==t||null==e?t===e:t.x===e.x&&t.y===e.y&&t.width===e.width&&t.height===e.height}static sizeEqual(t,e){return Math.round(t.width)===Math.round(e.width)&&Math.round(t.height)===Math.round(e.height)}};function x(t,e){const i=Math.max(t.width,3),n=Math.max(t.height,3),o=t.top-e.top- -1,s=t.left-e.left- -1,r=e.right-t.left-i- -1,l=e.bottom-t.top-n- -1;return`${-Math.round(o)}px ${-Math.round(r)}px ${-Math.round(l)}px ${-Math.round(s)}px`}var B=[...Array.from({length:1e3},(t,e)=>e/1e3),1],M=class{constructor(t,e,i){this.#t=e,this.#e=i,this.#i=i.clientRect,this.#n(t)}#t;#o=void 0;#e;#i;#s=void 0;get visibleRect(){const t=this.#e.clip;return t?D.clip(this.#i,t):this.#i}get isIntersecting(){const{width:t,height:e}=this.visibleRect;return t>0&&e>0}#n(t){const{root:e,rootBounds:i}=this.#e,{visibleRect:n}=this;this.#o?.disconnect(),this.#o=new IntersectionObserver(this.#r,{root:e,rootMargin:x(n,i),threshold:B}),this.#o.observe(t)}#r=t=>{if(!this.#o)return;const e=t[t.length-1];if(e){const{intersectionRatio:t,boundingClientRect:i}=e,n=this.#i;this.#i=i;const o=this.#s,s=!D.equals(i,n);if(t!==this.#s||s){const n=this.#e.rootBounds,r=D.intersect(i,n),l=r.width>0&&r.height>0;if(!l)return;this.#s=t,(null!=o||s)&&(this.#t(new k(e.target,i,e.intersectionRect,l,n),this),this.#n(e.target))}}};disconnect(){this.#o?.disconnect()}},k=class{constructor(t,e,i,n,o){this.target=t,this.boundingClientRect=e,this.intersectionRect=i,this.isIntersecting=n,this.rootBounds=o}},I=class{constructor(t,e){const i=function(t){return!t||function(t){return t.nodeType===Node.DOCUMENT_NODE}(t)?t?.defaultView??window:t}(t);if(function(t){return L(t)&&t.nodeType===Node.ELEMENT_NODE}(i)){const t=i.ownerDocument??document;this.rootBounds=i.getBoundingClientRect(),this.#l=new ResizeObserver(t=>{for(const i of t){const[{inlineSize:t,blockSize:n}]=i.borderBoxSize;if(D.sizeEqual(this.rootBounds,{width:t,height:n}))continue;const o=i.target.getBoundingClientRect();this.rootBounds=o,e(o,this)}}),this.#l.observe(i),t.addEventListener("scroll",t=>{t.target&&t.target!==i&&L(t.target)&&t.target.contains(i)&&(this.rootBounds=i.getBoundingClientRect(),e(this.rootBounds,this))},{capture:!0,passive:!0,signal:this.#a.signal})}else{const t=i.visualViewport??i;this.rootBounds=T(i);const n=()=>{const t=T(i);D.equals(this.rootBounds,t)||(this.rootBounds=t,e(t,this))};t.addEventListener("resize",n,{signal:this.#a.signal})}}#l;#a=new AbortController;rootBounds;disconnect(){this.#l?.disconnect(),this.#a.abort()}};function T(t){const e=t.visualViewport?.width??t.innerWidth,i=t.visualViewport?.height??t.innerHeight;return new DOMRect(0,0,e,i)}function L(t){return"nodeType"in t}var z=class{constructor(t,e){this.#e=e,this.#t=e=>{const i=[];for(const t of e){const e=this.intersections.get(t.target);this.intersections.set(t.target,t),e?.isIntersecting===t.isIntersecting&&D.equals(e?.intersectionRect,t.intersectionRect)||i.push(t)}i.length>0&&t(i,this)}}#t;#c=new Map;#e;intersections=new WeakMap;observe(t){const e=t.ownerDocument;if(!e)return;let i=this.#c.get(e);i||(i=new IntersectionObserver(this.#t,{...this.#e,threshold:B}),this.#c.set(e,i)),i.observe(t)}unobserve(t){const e=t.ownerDocument;if(!e)return;const i=this.#c.get(e);i&&(i.unobserve(t),this.intersections.delete(t))}disconnect(){for(const t of this.#c.values())t.disconnect();this.#c.clear()}},j=class{constructor(t,e){this.#t=t,this.#e=e,this.#h=new I(e?.root,this.#u),this.#d=new z(this.#g,e),this.#l=new ResizeObserver(this.#b)}#t;#e;#p=new Map;#l;#f=new WeakMap;#h;#d;observe(t){this.#d.observe(t)}unobserve(t){t?(this.#p.get(t)?.disconnect(),this.#d.unobserve(t)):this.disconnect()}disconnect(){for(const t of this.#p.values())t.disconnect();this.#l.disconnect(),this.#h.disconnect(),this.#d.disconnect()}#m(t){const e=[];for(const i of t){const{target:t}=i;N(i,this.#f.get(t))||(this.#f.set(t,i),e.push(i))}e.length>0&&this.#t(e)}#u=t=>{const e=[];for(const[i]of this.#p){const n=i.getBoundingClientRect(),o=this.#v(i,n);e.push(new H(i,n,o.visibleRect,o.isIntersecting,t))}this.#m(e)};#v(t,e){const i=this.#d;this.#p.get(t)?.disconnect();const n=new M(t,this.#y,{clientRect:e,root:this.#e?.root,rootBounds:this.#h.rootBounds,get clip(){const e=i.intersections.get(t);if(!e)return;const{intersectionRect:n,boundingClientRect:o}=e;return D.clipOffsets(o,n)}});return this.#p.set(t,n),n}#g=t=>{const e=[];for(const i of t){const{target:t,isIntersecting:n,boundingClientRect:o}=i;n?(this.#v(t,o),this.#l.observe(t)):(this.#p.get(t)?.disconnect(),this.#p.delete(t),this.#l.unobserve(t));const s=this.#p.get(t);e.push(new H(t,o,s?.visibleRect??i.intersectionRect,n,this.#h.rootBounds))}this.#m(e)};#y=(t,e)=>{this.#m([new H(t.target,t.boundingClientRect,e.visibleRect,t.isIntersecting,this.#h.rootBounds)])};#b=t=>{const e=[];for(const i of t){const{target:t,borderBoxSize:n}=i,o=this.#f.get(t);if(o){const[{inlineSize:t,blockSize:e}]=n;if(D.sizeEqual(o.boundingClientRect,{width:t,height:e}))continue}const s=t.getBoundingClientRect(),r=this.#v(t,s);e.push(new H(t,s,r.visibleRect,this.#d.intersections.get(t)?.isIntersecting??!1,this.#h.rootBounds))}this.#m(e)}},H=class{constructor(t,e,i,n,o){this.target=t,this.boundingClientRect=e,this.intersectionRect=i,this.isIntersecting=n,this.rootBounds=o}};function N(t,e){return null!=e&&(t.target===e.target&&t.isIntersecting===e.isIntersecting&&D.equals(t.boundingClientRect,e.boundingClientRect)&&D.equals(t.intersectionRect,e.intersectionRect))}class _{constructor(){this.elements=new Map,this.isSetup=!1,this._globalCallbackHits={mouse:{hover:0,trajectory:0},tab:{forwards:0,reverse:0},scroll:{down:0,left:0,right:0,up:0},total:0},this._globalSettings={debug:!1,enableMousePrediction:true,enableScrollPrediction:true,positionHistorySize:8,trajectoryPredictionTime:120,scrollMargin:150,defaultHitSlop:{top:0,left:0,right:0,bottom:0},enableTabPrediction:true,tabOffset:2,onAnyCallbackFired:(t,e)=>{}},this.trajectoryPositions={positions:[],currentPoint:{x:0,y:0},predictedPoint:{x:0,y:0}},this.tabbableElementsCache=[],this.lastFocusedIndex=null,this.predictedScrollPoint=null,this.scrollDirection=null,this.domObserver=null,this.positionObserver=null,this.lastKeyDown=null,this.globalListenersController=null,this.eventListeners=new Map,this.handleMouseMove=t=>{this.updatePointerState(t),this.elements.forEach(t=>{t.isIntersectingWithViewport&&this.handleCallbackInteraction(t)}),this.emit({type:"mouseTrajectoryUpdate",predictionEnabled:this._globalSettings.enableMousePrediction,timestamp:Date.now(),trajectoryPositions:this.trajectoryPositions})},this.handleDomMutations=t=>{t.length&&(this.tabbableElementsCache=[],this.lastFocusedIndex=null);for(const e of t)if("childList"===e.type&&e.removedNodes.length>0)for(const t of Array.from(this.elements.keys()))t.isConnected||this.unregister(t,"disconnected")},this.handleKeyDown=t=>{"Tab"===t.key&&(this.lastKeyDown=t)},this.handleFocusIn=t=>{if(!this.lastKeyDown||!this._globalSettings.enableTabPrediction)return;const e=t.target;if(!(e instanceof HTMLElement))return;this.tabbableElementsCache.length||(this.tabbableElementsCache=m(document.documentElement));const i=this.lastKeyDown.shiftKey,n=function(t,e,i,n){if(null!==e){const o=t?e-1:e+1;if(o>=0&&o<i.length&&i[o]===n)return o}return i.findIndex(t=>t===n)}(i,this.lastFocusedIndex,this.tabbableElementsCache,e);this.lastFocusedIndex=n,this.lastKeyDown=null;const o=[];for(let t=0;t<=this._globalSettings.tabOffset;t++)if(i){const e=this.tabbableElementsCache[n-t];this.elements.has(e)&&o.push(e)}else{const e=this.tabbableElementsCache[n+t];this.elements.has(e)&&o.push(e)}o.forEach(t=>{this.callCallback(this.elements.get(t),{kind:"tab",subType:i?"reverse":"forwards"})})},this.handlePositionChange=t=>{for(const e of t){const t=this.elements.get(e.target);if(!t)continue;const i=t.isIntersectingWithViewport,n=e.isIntersecting;t.isIntersectingWithViewport=n,i!==n&&this.emit({type:"elementDataUpdated",elementData:t,timestamp:Date.now(),updatedProp:"visibility"}),n&&(this.updateElementBounds(e.boundingClientRect,t),this.handleScrollPrefetch(t,e.boundingClientRect))}this.scrollDirection=null,this.predictedScrollPoint=null}}static initialize(t){return this.isInitiated||(_.manager=new _),void 0!==t&&_.manager.alterGlobalSettings(t),_.manager}addEventListener(t,e,i){if(i?.signal?.aborted)return()=>{};this.eventListeners.has(t)||this.eventListeners.set(t,[]),this.eventListeners.get(t).push(e),i?.signal?.addEventListener("abort",()=>this.removeEventListener(t,e))}removeEventListener(t,e){const i=this.eventListeners.get(t);if(i){const t=i.indexOf(e);t>-1&&i.splice(t,1)}}logSubscribers(){console.log("%c[ForesightManager] Current Subscribers:","font-weight: bold; color: #3b82f6;");const t=Array.from(this.eventListeners.keys());0!==t.length?t.forEach(t=>{const e=this.eventListeners.get(t);e&&e.length>0&&(console.groupCollapsed(`Event: %c${t}`,"font-weight: bold;",`(${e.length} listener${e.length>1?"s":""})`),e.forEach((t,e)=>{console.log(`[${e}]:`,t)}),console.groupEnd())}):console.log(" No active subscribers.")}emit(t){const e=this.eventListeners.get(t.type);e&&e.forEach(e=>{try{e(t)}catch(e){console.error(`Error in ForesightManager event listener for ${t.type}:`,e)}})}get getManagerData(){return{registeredElements:this.elements,globalSettings:this._globalSettings,globalCallbackHits:this._globalCallbackHits}}static get isInitiated(){return!!_.manager}static get instance(){return this.initialize()}get registeredElements(){return this.elements}register({element:t,callback:e,hitSlop:i,name:n}){const{shouldRegister:o,isTouchDevice:s,isLimitedConnection:r}=v();if(!o)return{isLimitedConnection:r,isTouchDevice:s,isRegistered:!1,unregister:()=>{}};this.isSetup||this.initializeGlobalListeners();const l=i?R(i):this._globalSettings.defaultHitSlop,a={element:t,callback:e,elementBounds:{originalRect:void 0,expandedRect:{top:0,left:0,right:0,bottom:0},hitSlop:l},isHovering:!1,trajectoryHitData:{isTrajectoryHit:!1,trajectoryHitTime:0,trajectoryHitExpirationTimeoutId:void 0},name:n??t.id??"",isIntersectingWithViewport:!0};return this.elements.set(t,a),this.positionObserver?.observe(t),this.emit({type:"elementRegistered",timestamp:Date.now(),elementData:a}),{isTouchDevice:s,isLimitedConnection:r,isRegistered:!0,unregister:()=>this.unregister(t,"apiCall")}}unregister(t,e){if(!this.elements.has(t))return;const i=this.elements.get(t);i&&this.emit({type:"elementUnregistered",elementData:i,timestamp:Date.now(),unregisterReason:e}),i?.trajectoryHitData.trajectoryHitExpirationTimeoutId&&clearTimeout(i.trajectoryHitData.trajectoryHitExpirationTimeoutId),this.positionObserver?.unobserve(t),this.elements.delete(t),0===this.elements.size&&this.isSetup&&this.removeGlobalListeners()}updateNumericSettings(t,e,i,n){return!!O(t,this._globalSettings[e])&&(this._globalSettings[e]=S(t,i,n,e),!0)}updateBooleanSetting(t,e){return!!O(t,this._globalSettings[e])&&(this._globalSettings[e]=t,!0)}alterGlobalSettings(t){const e=this._globalSettings.positionHistorySize,i=this.updateNumericSettings(t?.positionHistorySize,"positionHistorySize",2,30);i&&this._globalSettings.positionHistorySize<e&&this.trajectoryPositions.positions.length>this._globalSettings.positionHistorySize&&(this.trajectoryPositions.positions=this.trajectoryPositions.positions.slice(this.trajectoryPositions.positions.length-this._globalSettings.positionHistorySize));const n=this.updateNumericSettings(t?.trajectoryPredictionTime,"trajectoryPredictionTime",10,200),o=this.updateNumericSettings(t?.scrollMargin,"scrollMargin",30,300),s=this.updateNumericSettings(t?.tabOffset,"tabOffset",0,20),r=this.updateBooleanSetting(t?.enableMousePrediction,"enableMousePrediction"),l=this.updateBooleanSetting(t?.enableScrollPrediction,"enableScrollPrediction"),a=this.updateBooleanSetting(t?.enableTabPrediction,"enableTabPrediction");void 0!==t?.onAnyCallbackFired&&(this._globalSettings.onAnyCallbackFired=t.onAnyCallbackFired);let c=!1;if(void 0!==t?.defaultHitSlop){const e=R(t.defaultHitSlop);P(this._globalSettings.defaultHitSlop,e)||(this._globalSettings.defaultHitSlop=e,c=!0,this.forceUpdateAllElementBounds())}(i||n||s||r||a||l||c||o)&&this.emit({type:"managerSettingsChanged",timestamp:Date.now(),managerData:this.getManagerData})}forceUpdateAllElementBounds(){this.elements.forEach((t,e)=>{const i=this.elements.get(e);i&&i.isIntersectingWithViewport&&this.forceUpdateElementBounds(i)})}updatePointerState(t){this.trajectoryPositions.currentPoint={x:t.clientX,y:t.clientY},this.trajectoryPositions.predictedPoint=this._globalSettings.enableMousePrediction?function(t,e,i,n){const o={point:t,time:performance.now()},{x:s,y:r}=t;if(e.push(o),e.length>i&&e.shift(),e.length<2)return{x:s,y:r};const l=e[0],a=e[e.length-1],c=(a.time-l.time)/1e3;if(0===c)return{x:s,y:r};const h=n/1e3;return{x:s+(a.point.x-l.point.x)/c*h,y:r+(a.point.y-l.point.y)/c*h}}(this.trajectoryPositions.currentPoint,this.trajectoryPositions.positions,this._globalSettings.positionHistorySize,this._globalSettings.trajectoryPredictionTime):{...this.trajectoryPositions.currentPoint}}handleCallbackInteraction(t){const{expandedRect:e}=t.elementBounds;if(this._globalSettings.enableMousePrediction)w(this.trajectoryPositions.currentPoint,this.trajectoryPositions.predictedPoint,e)&&this.callCallback(t,{kind:"mouse",subType:"trajectory"});else if(E(this.trajectoryPositions.currentPoint,e))return void this.callCallback(t,{kind:"mouse",subType:"hover"})}updateHitCounters(t,e){switch(e.kind){case"mouse":this._globalCallbackHits.mouse[e.subType]++;break;case"tab":this._globalCallbackHits.tab[e.subType]++;break;case"scroll":this._globalCallbackHits.scroll[e.subType]++}this._globalCallbackHits.total++}callCallback(t,e){t&&(this.updateHitCounters(t,e),t.callback(),this._globalSettings.onAnyCallbackFired(t,this.getManagerData),this.emit({type:"callbackFired",timestamp:Date.now(),elementData:t,hitType:e,managerData:this.getManagerData}),this.unregister(t.element,"callbackHit"))}forceUpdateElementBounds(t){const e=t.element.getBoundingClientRect(),i=C(e,t.elementBounds.hitSlop);if(!P(i,t.elementBounds.expandedRect)){const n={...t,elementBounds:{...t.elementBounds,originalRect:e,expandedRect:i}};this.elements.set(t.element,n),this.emit({type:"elementDataUpdated",timestamp:Date.now(),elementData:n,updatedProp:"bounds"})}}updateElementBounds(t,e){const i={...e,elementBounds:{...e.elementBounds,originalRect:t,expandedRect:C(t,e.elementBounds.hitSlop)}};this.elements.set(e.element,i),this.emit({type:"elementDataUpdated",timestamp:Date.now(),elementData:i,updatedProp:"bounds"})}handleScrollPrefetch(t,e){if(this._globalSettings.enableScrollPrediction){if(!t.elementBounds.originalRect)return;if(this.scrollDirection=this.scrollDirection??function(t,e){const i=e.top-t.top,n=e.left-t.left;return i<-1?"down":i>1?"up":n<-1?"right":n>1?"left":"none"}(t.elementBounds.originalRect,e),"none"===this.scrollDirection)return;this.predictedScrollPoint=this.predictedScrollPoint??function(t,e,i){const{x:n,y:o}=t,s={x:n,y:o};switch(e){case"down":s.y+=i;break;case"up":s.y-=i;break;case"left":s.x-=i;break;case"right":s.x+=i}return s}(this.trajectoryPositions.currentPoint,this.scrollDirection,this._globalSettings.scrollMargin),w(this.trajectoryPositions.currentPoint,this.predictedScrollPoint,t?.elementBounds.expandedRect)&&this.callCallback(t,{kind:"scroll",subType:this.scrollDirection}),this.emit({type:"scrollTrajectoryUpdate",timestamp:Date.now(),currentPoint:this.trajectoryPositions.currentPoint,predictedPoint:this.predictedScrollPoint})}else E(this.trajectoryPositions.currentPoint,t.elementBounds.expandedRect)&&this.callCallback(t,{kind:"mouse",subType:"hover"})}initializeGlobalListeners(){if(this.isSetup)return;if("undefined"==typeof window||"undefined"==typeof document)return;this.globalListenersController=new AbortController;const{signal:t}=this.globalListenersController;document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("keydown",this.handleKeyDown,{signal:t}),document.addEventListener("focusin",this.handleFocusIn,{signal:t}),this.domObserver=new MutationObserver(this.handleDomMutations),this.domObserver.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!1}),this.positionObserver=new j(this.handlePositionChange),this.isSetup=!0}removeGlobalListeners(){this.isSetup=!1,this.globalListenersController?.abort(),this.globalListenersController=null,this.domObserver?.disconnect(),this.domObserver=null,this.positionObserver?.disconnect(),this.positionObserver=null}}exports.ForesightManager=_;
6
- //# sourceMappingURL=index.js.map
1
+ "use strict";var E=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var j=Object.prototype.hasOwnProperty;var B=(i,e)=>{for(var t in e)E(i,t,{get:e[t],enumerable:!0})},K=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of k(e))!j.call(i,o)&&o!==t&&E(i,o,{get:()=>e[o],enumerable:!(n=U(e,o))||n.enumerable});return i};var G=i=>K(E({},"__esModule",{value:!0}),i);var ae={};B(ae,{ForesightManager:()=>f});module.exports=G(ae);var x=require("tabbable");function P(){let i=Y(),e=z();return{isTouchDevice:i,isLimitedConnection:e,shouldRegister:!i&&!e}}function Y(){return window.matchMedia("(pointer: coarse)").matches&&navigator.maxTouchPoints>0}function z(){let i=navigator.connection;return i?/2g/.test(i.effectiveType)||i.saveData:!1}function d(i,e,t,n){return i<e?console.warn(`ForesightJS: "${n}" value ${i} is below minimum bound ${e}, clamping to ${e}`):i>t&&console.warn(`ForesightJS: "${n}" value ${i} is above maximum bound ${t}, clamping to ${t}`),Math.min(Math.max(i,e),t)}function S(i,e,t){let n=0,o=1,s=e.x-i.x,r=e.y-i.y,a=(l,u)=>{if(l===0){if(u<0)return!1}else{let c=u/l;if(l<0){if(c>o)return!1;c>n&&(n=c)}else{if(c<n)return!1;c<o&&(o=c)}}return!0};return!a(-s,i.x-t.left)||!a(s,t.right-i.x)||!a(-r,i.y-t.top)||!a(r,t.bottom-i.y)?!1:n<=o}function _(i,e,t,n){let o=performance.now(),s={point:i,time:o},{x:r,y:a}=i;if(e.push(s),e.length>t&&e.shift(),e.length<2)return{x:r,y:a};let l=e[0],u=e[e.length-1],c=(u.time-l.time)/1e3;if(c===0)return{x:r,y:a};let g=u.point.x-l.point.x,L=u.point.y-l.point.y,N=g/c,A=L/c,R=n/1e3,H=r+N*R,w=a+A*R;return{x:H,y:w}}function v(i){if(typeof i=="number"){let e=d(i,0,2e3,"hitslop");return{top:e,left:e,right:e,bottom:e}}return{top:d(i.top,0,2e3,"hitslop - top"),left:d(i.left,0,2e3,"hitslop - left"),right:d(i.right,0,2e3,"hitslop - right"),bottom:d(i.bottom,0,2e3,"hitslop - bottom")}}function m(i,e){return{left:i.left-e.left,right:i.right+e.right,top:i.top-e.top,bottom:i.bottom+e.bottom}}function T(i,e){return!i||!e?i===e:i.left===e.left&&i.right===e.right&&i.top===e.top&&i.bottom===e.bottom}function y(i,e){return i.x>=e.left&&i.x<=e.right&&i.y>=e.top&&i.y<=e.bottom}function I(i,e){return i!==void 0&&e!==i}function M(i,e,t,n){if(e!==null){let o=i?e-1:e+1;if(o>=0&&o<t.length&&t[o]===n)return o}return t.findIndex(o=>o===n)}function F(i,e){let n=e.top-i.top,o=e.left-i.left;return n<-1?"down":n>1?"up":o<-1?"right":o>1?"left":"none"}function C(i,e,t){let{x:n,y:o}=i,s={x:n,y:o};switch(e){case"down":s.y+=t;break;case"up":s.y-=t;break;case"left":s.x-=t;break;case"right":s.x+=t;break;case"none":break;default:}return s}var D=require("position-observer");function O(i){let e=window.innerWidth||document.documentElement.clientWidth,t=window.innerHeight||document.documentElement.clientHeight;return i.top<t&&i.bottom>0&&i.left<e&&i.right>0}var f=class i{constructor(){this.elements=new Map;this.isSetup=!1;this._globalCallbackHits={mouse:{hover:0,trajectory:0},tab:{forwards:0,reverse:0},scroll:{down:0,left:0,right:0,up:0},total:0};this._globalSettings={debug:!1,enableMousePrediction:!0,enableScrollPrediction:!0,positionHistorySize:8,trajectoryPredictionTime:120,scrollMargin:150,defaultHitSlop:{top:0,left:0,right:0,bottom:0},enableTabPrediction:!0,tabOffset:2};this.trajectoryPositions={positions:[],currentPoint:{x:0,y:0},predictedPoint:{x:0,y:0}};this.tabbableElementsCache=[];this.lastFocusedIndex=null;this.predictedScrollPoint=null;this.scrollDirection=null;this.domObserver=null;this.positionObserver=null;this.lastKeyDown=null;this.globalListenersController=new AbortController;this.rafId=null;this.pendingMouseEvent=null;this.eventListeners=new Map;this.handleMouseMove=e=>{this.pendingMouseEvent=e,!this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.pendingMouseEvent&&(this.processMouseMovement(this.pendingMouseEvent),this.pendingMouseEvent=null),this.rafId=null}))};this.handleDomMutations=e=>{e.length&&(this.tabbableElementsCache=[],this.lastFocusedIndex=null);for(let t of e)if(t.type==="childList"&&t.removedNodes.length>0)for(let n of this.elements.keys())n.isConnected||this.unregister(n,"disconnected")};this.handleKeyDown=e=>{e.key==="Tab"&&(this.lastKeyDown=e)};this.handleFocusIn=e=>{if(!this.lastKeyDown||!this._globalSettings.enableTabPrediction)return;let t=e.target;if(!(t instanceof HTMLElement))return;this.tabbableElementsCache.length||(this.tabbableElementsCache=(0,x.tabbable)(document.documentElement));let n=this.lastKeyDown.shiftKey,o=M(n,this.lastFocusedIndex,this.tabbableElementsCache,t);this.lastFocusedIndex=o,this.lastKeyDown=null;let s=[];for(let r=0;r<=this._globalSettings.tabOffset;r++)if(n){let a=this.tabbableElementsCache[o-r];this.elements.has(a)&&s.push(a)}else{let a=this.tabbableElementsCache[o+r];this.elements.has(a)&&s.push(a)}s.forEach(r=>{let a=this.elements.get(r);a&&this.callCallback(a,{kind:"tab",subType:n?"reverse":"forwards"})})};this.handlePositionChange=e=>{for(let t of e){let n=this.elements.get(t.target);n&&(this.handlePositionChangeDataUpdates(n,t),this.handleScrollPrefetch(n,t.boundingClientRect))}this.scrollDirection=null,this.predictedScrollPoint=null};this.handlePositionChangeDataUpdates=(e,t)=>{let n=[],o=t.isIntersecting,s={...e,isIntersectingWithViewport:o};e.isIntersectingWithViewport!==o&&n.push("visibility"),o&&(n.push("bounds"),this.handleScrollPrefetch(s,t.boundingClientRect),s={...s,elementBounds:{hitSlop:e.elementBounds.hitSlop,originalRect:t.boundingClientRect,expandedRect:m(t.boundingClientRect,e.elementBounds.hitSlop)}}),this.elements.set(e.element,s),n.length&&this.emit({type:"elementDataUpdated",elementData:s,updatedProps:n})}}static initialize(e){return this.isInitiated||(i.manager=new i),e!==void 0&&i.manager.alterGlobalSettings(e),i.manager}addEventListener(e,t,n){if(n?.signal?.aborted)return()=>{};let o=this.eventListeners.get(e)??[];o.push(t),this.eventListeners.set(e,o),n?.signal?.addEventListener("abort",()=>this.removeEventListener(e,t))}removeEventListener(e,t){let n=this.eventListeners.get(e);if(!n)return;let o=n.indexOf(t);o>-1&&n.splice(o,1)}emit(e){let t=this.eventListeners.get(e.type);t&&t.forEach(n=>{try{n(e)}catch(o){console.error(`Error in ForesightManager event listener for ${e.type}:`,o)}})}get getManagerData(){return{registeredElements:this.elements,globalSettings:this._globalSettings,globalCallbackHits:this._globalCallbackHits,eventListeners:this.eventListeners}}static get isInitiated(){return!!i.manager}static get instance(){return this.initialize()}get registeredElements(){return this.elements}register({element:e,callback:t,hitSlop:n,name:o}){let{shouldRegister:s,isTouchDevice:r,isLimitedConnection:a}=P();if(!s)return{isLimitedConnection:a,isTouchDevice:r,isRegistered:!1,unregister:()=>{}};this.isSetup||this.initializeGlobalListeners();let l=e.getBoundingClientRect(),u=n?v(n):this._globalSettings.defaultHitSlop,c={element:e,callback:t,elementBounds:{originalRect:l,expandedRect:m(l,u),hitSlop:u},isHovering:!1,trajectoryHitData:{isTrajectoryHit:!1,trajectoryHitTime:0,trajectoryHitExpirationTimeoutId:void 0},name:o||e.id||"unnamed",isIntersectingWithViewport:O(l),isRunningCallback:!1,registerCount:(this.registeredElements.get(e)?.registerCount??0)+1};return this.elements.set(e,c),this.positionObserver?.observe(e),this.emit({type:"elementRegistered",timestamp:Date.now(),elementData:c}),{isTouchDevice:r,isLimitedConnection:a,isRegistered:!0,unregister:()=>this.unregister(e,"apiCall")}}unregister(e,t){if(!this.elements.has(e))return;let n=this.elements.get(e);n?.trajectoryHitData.trajectoryHitExpirationTimeoutId&&clearTimeout(n.trajectoryHitData.trajectoryHitExpirationTimeoutId),this.positionObserver?.unobserve(e),this.elements.delete(e),this.elements.size===0&&this.isSetup&&this.removeGlobalListeners(),n&&this.emit({type:"elementUnregistered",elementData:n,timestamp:Date.now(),unregisterReason:t})}updateNumericSettings(e,t,n,o){return I(e,this._globalSettings[t])?(this._globalSettings[t]=d(e,n,o,t),!0):!1}updateBooleanSetting(e,t){return I(e,this._globalSettings[t])?(this._globalSettings[t]=e,!0):!1}alterGlobalSettings(e){let t=[];if([{setting:"positionHistorySize",min:2,max:30},{setting:"trajectoryPredictionTime",min:10,max:200},{setting:"scrollMargin",min:30,max:300},{setting:"tabOffset",min:0,max:20}].forEach(({setting:s,min:r,max:a})=>{let l=e?.[s];if(l===void 0)return;let u=this._globalSettings[s];if(this.updateNumericSettings(l,s,r,a)&&(t.push({setting:s,oldValue:u,newValue:this._globalSettings[s]}),s==="positionHistorySize"&&this._globalSettings.positionHistorySize<u)){let g=this._globalSettings.positionHistorySize;this.trajectoryPositions.positions.length>g&&(this.trajectoryPositions.positions=this.trajectoryPositions.positions.slice(-g))}}),["enableMousePrediction","enableScrollPrediction","enableTabPrediction"].forEach(s=>{let r=e?.[s];if(r===void 0)return;let a=this._globalSettings[s];this.updateBooleanSetting(r,s)&&t.push({setting:s,oldValue:a,newValue:this._globalSettings[s]})}),e?.defaultHitSlop!==void 0){let s=this._globalSettings.defaultHitSlop,r=v(e.defaultHitSlop);T(s,r)||(this._globalSettings.defaultHitSlop=r,t.push({setting:"defaultHitSlop",oldValue:s,newValue:r}),this.forceUpdateAllElementBounds())}t.length>0&&this.emit({type:"managerSettingsChanged",timestamp:Date.now(),managerData:this.getManagerData,updatedSettings:t})}forceUpdateAllElementBounds(){for(let[e,t]of this.elements)t.isIntersectingWithViewport&&this.forceUpdateElementBounds(t)}updatePointerState(e){let t={x:e.clientX,y:e.clientY};this.trajectoryPositions.currentPoint=t,this._globalSettings.enableMousePrediction?this.trajectoryPositions.predictedPoint=_(t,this.trajectoryPositions.positions,this._globalSettings.positionHistorySize,this._globalSettings.trajectoryPredictionTime):this.trajectoryPositions.predictedPoint=t}processMouseMovement(e){this.updatePointerState(e);for(let t of this.elements.values()){if(!t.isIntersectingWithViewport)continue;let n=t.elementBounds.expandedRect;if(this._globalSettings.enableMousePrediction)S(this.trajectoryPositions.currentPoint,this.trajectoryPositions.predictedPoint,n)&&this.callCallback(t,{kind:"mouse",subType:"trajectory"});else if(y(this.trajectoryPositions.currentPoint,n)){this.callCallback(t,{kind:"mouse",subType:"hover"});return}}this.emit({type:"mouseTrajectoryUpdate",predictionEnabled:this._globalSettings.enableMousePrediction,trajectoryPositions:this.trajectoryPositions})}updateHitCounters(e,t){switch(e.kind){case"mouse":this._globalCallbackHits.mouse[e.subType]++;break;case"tab":this._globalCallbackHits.tab[e.subType]++;break;case"scroll":this._globalCallbackHits.scroll[e.subType]++;break;default:}this._globalCallbackHits.total++}callCallback(e,t){if(e.isRunningCallback)return;e.isRunningCallback=!0,(async()=>{this.updateHitCounters(t,e),this.emit({type:"callbackInvoked",timestamp:Date.now(),elementData:e,hitType:t});let o=performance.now();try{await e.callback(),this.emit({type:"callbackCompleted",timestamp:Date.now(),elementData:e,hitType:t,elapsed:performance.now()-o,status:"success"})}catch(s){let r=s instanceof Error?s.message:String(s);console.error(`Error in callback for element ${e.name} (${e.element.tagName}):`,s),this.emit({type:"callbackCompleted",timestamp:Date.now(),elementData:e,hitType:t,elapsed:performance.now()-o,status:"error",errorMessage:r})}this.unregister(e.element,"callbackHit")})()}forceUpdateElementBounds(e){let t=e.element.getBoundingClientRect(),n=m(t,e.elementBounds.hitSlop);if(!T(n,e.elementBounds.expandedRect)){let o={...e,elementBounds:{...e.elementBounds,originalRect:t,expandedRect:n}};this.elements.set(e.element,o),this.emit({type:"elementDataUpdated",elementData:o,updatedProps:["bounds"]})}}handleScrollPrefetch(e,t){if(e.isIntersectingWithViewport)if(!this._globalSettings.enableScrollPrediction)y(this.trajectoryPositions.currentPoint,e.elementBounds.expandedRect)&&this.callCallback(e,{kind:"mouse",subType:"hover"});else{if(this.scrollDirection=this.scrollDirection??F(e.elementBounds.originalRect,t),this.scrollDirection==="none")return;this.predictedScrollPoint=this.predictedScrollPoint??C(this.trajectoryPositions.currentPoint,this.scrollDirection,this._globalSettings.scrollMargin),S(this.trajectoryPositions.currentPoint,this.predictedScrollPoint,e.elementBounds.expandedRect)&&this.callCallback(e,{kind:"scroll",subType:this.scrollDirection}),this.emit({type:"scrollTrajectoryUpdate",currentPoint:this.trajectoryPositions.currentPoint,predictedPoint:this.predictedScrollPoint,scrollDirection:this.scrollDirection})}}initializeGlobalListeners(){if(this.isSetup||typeof window>"u"||typeof document>"u")return;let{signal:e}=this.globalListenersController;document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("keydown",this.handleKeyDown,{signal:e}),document.addEventListener("focusin",this.handleFocusIn,{signal:e}),this.domObserver=new MutationObserver(this.handleDomMutations),this.domObserver.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!1}),this.positionObserver=new D.PositionObserver(this.handlePositionChange),this.isSetup=!0}removeGlobalListeners(){this.isSetup=!1,this.globalListenersController?.abort(),this.tabbableElementsCache=[],this.lastFocusedIndex=null,this.domObserver?.disconnect(),this.domObserver=null,this.positionObserver?.disconnect(),this.positionObserver=null,this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.pendingMouseEvent=null}};0&&(module.exports={ForesightManager});
2
+ //# sourceMappingURL=index.js.map