js.foresight 0.0.13 → 0.0.15
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/package.json +1 -1
- package/dist/index.d.ts +0 -177
- package/dist/index.js +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js.foresight",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Predicts mouse trajectory to trigger actions as users approach elements, enabling anticipatory UI updates or pre-loading. Made with vanilla javascript and usable in every framework.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
package/dist/index.d.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
type Rect = {
|
|
2
|
-
top: number;
|
|
3
|
-
left: number;
|
|
4
|
-
right: number;
|
|
5
|
-
bottom: number;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* A callback function that is executed when a foresight interaction
|
|
9
|
-
* (e.g., hover, trajectory hit) occurs on a registered element.
|
|
10
|
-
* Only triggers ones per interaction
|
|
11
|
-
*/
|
|
12
|
-
type ForesightCallback = () => void;
|
|
13
|
-
/**
|
|
14
|
-
* Represents the HTML element that is being tracked by the ForesightManager.
|
|
15
|
-
* This is typically a standard DOM `Element`.
|
|
16
|
-
*/
|
|
17
|
-
type ForesightElement = Element;
|
|
18
|
-
/**
|
|
19
|
-
* Configuration options for the ForesightManager
|
|
20
|
-
*/
|
|
21
|
-
type ForesightManagerProps = {
|
|
22
|
-
/**
|
|
23
|
-
* Number of mouse positions to keep in history for trajectory calculation.
|
|
24
|
-
* A higher number might lead to smoother but slightly delayed predictions.
|
|
25
|
-
* @default 8
|
|
26
|
-
*/
|
|
27
|
-
positionHistorySize: number;
|
|
28
|
-
/**
|
|
29
|
-
* How far ahead (in milliseconds) to predict the mouse trajectory.
|
|
30
|
-
* A larger value means the prediction extends further into the future. (meaning it will trigger callbacks sooner)
|
|
31
|
-
* @default 80
|
|
32
|
-
*/
|
|
33
|
-
trajectoryPredictionTime: number;
|
|
34
|
-
/**
|
|
35
|
-
* Whether to enable mouse trajectory prediction.
|
|
36
|
-
* If false, only direct hover/interaction is considered.
|
|
37
|
-
* @default true
|
|
38
|
-
*/
|
|
39
|
-
enableMousePrediction: boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Whether to show visual debugging information on the screen.
|
|
42
|
-
* This includes overlays for elements, hit slop areas, and the predicted mouse path.
|
|
43
|
-
* @default false
|
|
44
|
-
*/
|
|
45
|
-
debug: boolean;
|
|
46
|
-
/**
|
|
47
|
-
* Default hit slop to apply to all registered elements if no specific
|
|
48
|
-
* hit slop is provided during registration.
|
|
49
|
-
* Can be a single number for uniform slop on all sides, or a Rect object
|
|
50
|
-
* for different values per side.
|
|
51
|
-
* @default { top: 0, left: 0, right: 0, bottom: 0 }
|
|
52
|
-
*/
|
|
53
|
-
defaultHitSlop: Rect | number;
|
|
54
|
-
/**
|
|
55
|
-
* Amount of time in ms the element bounds get recalculated on scroll/resize of the page.
|
|
56
|
-
* @default 50
|
|
57
|
-
*/
|
|
58
|
-
resizeScrollThrottleDelay: number;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Manages the prediction of user intent based on mouse trajectory and element interactions.
|
|
63
|
-
*
|
|
64
|
-
* ForesightManager is a singleton class responsible for:
|
|
65
|
-
* - Registering HTML elements to monitor.
|
|
66
|
-
* - Tracking mouse movements and predicting future cursor positions.
|
|
67
|
-
* - Detecting when a predicted trajectory intersects with a registered element's bounds.
|
|
68
|
-
* - Invoking callbacks associated with elements upon predicted or actual interaction.
|
|
69
|
-
* - Handling global settings for prediction behavior (e.g., history size, prediction time).
|
|
70
|
-
* - Optionally enabling a {@link ForesightDebugger} for visual feedback.
|
|
71
|
-
*
|
|
72
|
-
* It should be initialized once using {@link ForesightManager.initialize} and then
|
|
73
|
-
* accessed via the static getter {@link ForesightManager.instance}.
|
|
74
|
-
*/
|
|
75
|
-
declare class ForesightManager {
|
|
76
|
-
private static manager;
|
|
77
|
-
private links;
|
|
78
|
-
private isSetup;
|
|
79
|
-
private debugMode;
|
|
80
|
-
private debugger;
|
|
81
|
-
private globalSettings;
|
|
82
|
-
private positions;
|
|
83
|
-
private currentPoint;
|
|
84
|
-
private predictedPoint;
|
|
85
|
-
private lastResizeScrollCallTimestamp;
|
|
86
|
-
private resizeScrollThrottleTimeoutId;
|
|
87
|
-
private constructor();
|
|
88
|
-
/**
|
|
89
|
-
* Initializes the ForesightManager singleton instance with optional global settings.
|
|
90
|
-
*
|
|
91
|
-
* This method sets up the manager, applying any provided configuration. If the manager
|
|
92
|
-
* is already initialized and this method is called again with new props, it will
|
|
93
|
-
* log an error and apply the new settings using `alterGlobalSettings`.
|
|
94
|
-
* It's recommended to call this method only once at the application's entry point.
|
|
95
|
-
*
|
|
96
|
-
* If `props.debug` is true or becomes true, the {@link ForesightDebugger} will be initialized or updated.
|
|
97
|
-
*
|
|
98
|
-
* @param {Partial<ForesightManagerProps>} [props] - Optional initial global settings
|
|
99
|
-
* to configure the manager. See {@link ForesightManagerProps} for details.
|
|
100
|
-
* @returns {ForesightManager} The singleton instance of the ForesightManager.
|
|
101
|
-
*/
|
|
102
|
-
static initialize(props?: Partial<ForesightManagerProps>): ForesightManager;
|
|
103
|
-
/**
|
|
104
|
-
* Gets the singleton instance of the ForesightManager.
|
|
105
|
-
*
|
|
106
|
-
* If the manager has not been initialized yet, this getter will call
|
|
107
|
-
* {@link ForesightManager.initialize} with default settings to create the instance.
|
|
108
|
-
*
|
|
109
|
-
* @returns {ForesightManager} The singleton instance of the ForesightManager.
|
|
110
|
-
*/
|
|
111
|
-
static get instance(): ForesightManager;
|
|
112
|
-
private checkTrajectoryHitExpiration;
|
|
113
|
-
private normalizeHitSlop;
|
|
114
|
-
/**
|
|
115
|
-
* Registers an element with the ForesightManager to monitor for predicted interactions.
|
|
116
|
-
*
|
|
117
|
-
* @param element The HTML element to monitor.
|
|
118
|
-
* @param callback The function to execute when an interaction is predicted or occurs.
|
|
119
|
-
* (Corresponds to {@link ForesightElementConfig.callback})
|
|
120
|
-
* @param hitSlop Optional. The amount of "slop" to add to the element's bounding box
|
|
121
|
-
* for hit detection. Can be a single number or a Rect object.
|
|
122
|
-
* This will overwrite the default global hitSlop set by the initializer of foresight.
|
|
123
|
-
* @param name Optional. A descriptive name for the element, useful for debugging.
|
|
124
|
-
* Defaults to "Unnamed".
|
|
125
|
-
* @returns A function to unregister the element.
|
|
126
|
-
*/
|
|
127
|
-
register(element: ForesightElement, callback: ForesightCallback, hitSlop?: number | Rect, name?: string): () => void;
|
|
128
|
-
private unregister;
|
|
129
|
-
/**
|
|
130
|
-
* Alters the global settings of the ForesightManager at runtime.
|
|
131
|
-
*
|
|
132
|
-
* This method allows dynamic updates to global configuration properties such as
|
|
133
|
-
* prediction parameters (`positionHistorySize`, `trajectoryPredictionTime`),
|
|
134
|
-
* `defaultHitSlop`, `debug` mode, and more.
|
|
135
|
-
*
|
|
136
|
-
* While global settings are typically best configured once via
|
|
137
|
-
* {@link ForesightManager.initialize} at the application's start, this method
|
|
138
|
-
* provides a way to modify them post-initialization. It is notably used by the
|
|
139
|
-
* {@link ForesightDebugger} UI to allow real-time adjustments for testing and
|
|
140
|
-
* tuning prediction behavior.
|
|
141
|
-
*
|
|
142
|
-
* For element-specific configurations (like an individual element's `hitSlop` or `name`),
|
|
143
|
-
* those should be provided during the element's registration via the
|
|
144
|
-
* {@link ForesightManager.register} method.
|
|
145
|
-
*
|
|
146
|
-
* If debug mode is active (`globalSettings.debug` is true) and any settings
|
|
147
|
-
* that affect the debugger's display or controls are changed, the
|
|
148
|
-
* {@link ForesightDebugger} instance will be updated accordingly.
|
|
149
|
-
*
|
|
150
|
-
* @param {Partial<ForesightManagerProps>} [props] - An object containing the global
|
|
151
|
-
* settings to update. Only properties provided in this object will be changed.
|
|
152
|
-
* See {@link ForesightManagerProps} for available settings.
|
|
153
|
-
*/
|
|
154
|
-
alterGlobalSettings(props?: Partial<ForesightManagerProps>): void;
|
|
155
|
-
private turnOnDebugMode;
|
|
156
|
-
private getExpandedRect;
|
|
157
|
-
private updateExpandedRect;
|
|
158
|
-
private updateAllRects;
|
|
159
|
-
private predictMousePosition;
|
|
160
|
-
/**
|
|
161
|
-
* Checks if a line segment intersects with an axis-aligned rectangle.
|
|
162
|
-
* Uses the Liang-Barsky line clipping algorithm.
|
|
163
|
-
* @param p1 Start point of the line segment.
|
|
164
|
-
* @param p2 End point of the line segment.
|
|
165
|
-
* @param rect The rectangle to check against.
|
|
166
|
-
* @returns True if the line segment intersects the rectangle, false otherwise.
|
|
167
|
-
*/
|
|
168
|
-
private lineSegmentIntersectsRect;
|
|
169
|
-
private isMouseInExpandedArea;
|
|
170
|
-
private handleMouseMove;
|
|
171
|
-
private handleResizeOrScroll;
|
|
172
|
-
private setupGlobalListeners;
|
|
173
|
-
private removeGlobalListeners;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export { ForesightManager };
|
|
177
|
-
export type { ForesightCallback, ForesightElement, ForesightManagerProps, Rect as ForesightRect };
|
package/dist/index.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var e=function(){return e=Object.assign||function(e){for(var t,i=1,n=arguments.length;i<n;i++)for(var o in t=arguments[i])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e},e.apply(this,arguments)};"function"==typeof SuppressedError&&SuppressedError;var t=function(){function e(e){this.shadowHost=null,this.shadowRoot=null,this.debugContainer=null,this.debugLinkOverlays=new Map,this.debugPredictedMouseIndicator=null,this.debugTrajectoryLine=null,this.debugControlsContainer=null,this.debugStyleElement=null,this.foresightManagerInstance=e}return e.prototype.initialize=function(e,t,i,n){var o=this;"undefined"!=typeof window&&(this.cleanup(),this.shadowHost=document.createElement("div"),this.shadowHost.id="jsforesight-debugger-shadow-host",this.shadowHost.style.pointerEvents="none",document.body.appendChild(this.shadowHost),this.shadowRoot=this.shadowHost.attachShadow({mode:"open"}),this.debugStyleElement=document.createElement("style"),this.debugStyleElement.textContent='\n #jsforesight-debug-container {\n position: fixed; top: 0; left: 0; width: 100%; height: 100%;\n pointer-events: none; z-index: 9999;\n }\n .jsforesight-link-overlay {\n position: absolute; border: 2px solid blue;\n background-color: rgba(0, 0, 255, 0.1); box-sizing: border-box;\n transition: opacity 0.2s ease, border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;\n }\n .jsforesight-link-overlay.active {\n border-color: orange; background-color: rgba(255, 0, 0, 0.1);\n }\n .jsforesight-link-overlay.trajectory-hit {\n border-color: lime; background-color: rgba(0, 255, 0, 0.3);\n box-shadow: 0 0 10px rgba(0, 255, 0, 0.8);\n }\n .jsforesight-expanded-overlay {\n position: absolute; border: 1px dashed rgba(0, 0, 255, 0.5);\n background-color: rgba(0, 0, 255, 0.05); box-sizing: border-box;\n }\n .jsforesight-mouse-predicted {\n position: absolute; width: 20px; height: 20px; border-radius: 50%;\n border: 2px solid orange; background-color: rgba(255, 165, 0, 0.3);\n transform: translate(-50%, -50%); z-index: 10000;\n }\n .jsforesight-trajectory-line {\n position: absolute; height: 2px; background-color: rgba(255, 100, 0, 0.5);\n transform-origin: left center; z-index: 9999;\n }\n .jsforesight-name-label { /* Added style for name label */\n position: absolute;\n background-color: rgba(0, 0, 0, 0.75);\n color: white;\n padding: 3px 6px;\n font-size: 11px;\n font-family: Arial, sans-serif;\n border-radius: 3px;\n z-index: 10001; /* Above link overlays */\n white-space: nowrap;\n pointer-events: none;\n }\n #jsforesight-debug-controls {\n position: fixed; bottom: 10px; right: 10px;\n background-color: rgba(0, 0, 0, 0.75); color: white; padding: 12px;\n border-radius: 5px; font-family: Arial, sans-serif; font-size: 13px;\n z-index: 10001; pointer-events: auto; display: flex; flex-direction: column; gap: 8px;\n min-width: 300px;\n }\n .jsforesight-debugger-title-container {\n display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 8px;\n }\n .jsforesight-debugger-title-container h3 { margin: 0; font-size: 15px; }\n #jsforesight-debug-controls label { display: flex; align-items: center; gap: 5px; cursor: pointer; }\n #jsforesight-debug-controls input[type="range"] { flex-grow: 1; margin: 0 5px; cursor: pointer;}\n #jsforesight-debug-controls input[type="checkbox"] { margin-right: 5px; cursor: pointer; }\n #jsforesight-debug-controls .control-row { display: flex; align-items: center; justify-content: space-between; }\n #jsforesight-debug-controls .control-row label { flex-basis: auto; }\n #jsforesight-debug-controls .control-row span:not(.jsforesight-info-icon) { min-width: 30px; text-align: right; }\n .jsforesight-info-icon {\n display: inline-flex; align-items: center; justify-content: center;\n width: 16px; height: 16px; border-radius: 50%;\n background-color: #555; color: white;\n font-size: 10px; font-style: italic; font-weight: bold;\n font-family: \'Georgia\', serif;\n cursor: help; user-select: none;\n flex-shrink: 0;\n }\n ',this.shadowRoot.appendChild(this.debugStyleElement),this.debugContainer=document.createElement("div"),this.debugContainer.id="jsforesight-debug-container",this.shadowRoot.appendChild(this.debugContainer),this.debugPredictedMouseIndicator=document.createElement("div"),this.debugPredictedMouseIndicator.className="jsforesight-mouse-predicted",this.debugContainer.appendChild(this.debugPredictedMouseIndicator),this.debugTrajectoryLine=document.createElement("div"),this.debugTrajectoryLine.className="jsforesight-trajectory-line",this.debugContainer.appendChild(this.debugTrajectoryLine),this.createDebugControls(t),e.forEach((function(e,t){o.createOrUpdateLinkOverlay(t,e)})),this.updateTrajectoryVisuals(i,n,t.enableMousePrediction))},e.prototype.cleanup=function(){var e;null===(e=this.shadowHost)||void 0===e||e.remove(),this.shadowHost=null,this.shadowRoot=null,this.debugLinkOverlays.forEach((function(e){e.linkOverlay.remove(),e.expandedOverlay.remove(),e.nameLabel.remove()})),this.debugLinkOverlays.clear()},e.prototype.createOrUpdateLinkOverlay=function(e,t){if(this.debugContainer&&this.shadowRoot){var i=this.debugLinkOverlays.get(e);if(!i){var n=document.createElement("div");n.className="jsforesight-link-overlay",this.debugContainer.appendChild(n);var o=document.createElement("div");o.className="jsforesight-expanded-overlay",this.debugContainer.appendChild(o);var r=document.createElement("div");r.className="jsforesight-name-label",this.debugContainer.appendChild(r),i={linkOverlay:n,expandedOverlay:o,nameLabel:r},this.debugLinkOverlays.set(e,i)}var s=i.linkOverlay,a=i.expandedOverlay,l=i.nameLabel,d=e.getBoundingClientRect();s.style.left="".concat(d.left,"px"),s.style.top="".concat(d.top,"px"),s.style.width="".concat(d.width,"px"),s.style.height="".concat(d.height,"px"),s.classList.toggle("trajectory-hit",t.isTrajectoryHit),s.classList.toggle("active",t.isHovering),t.elementBounds.expandedRect?(a.style.left="".concat(t.elementBounds.expandedRect.left,"px"),a.style.top="".concat(t.elementBounds.expandedRect.top,"px"),a.style.width="".concat(t.elementBounds.expandedRect.right-t.elementBounds.expandedRect.left,"px"),a.style.height="".concat(t.elementBounds.expandedRect.bottom-t.elementBounds.expandedRect.top,"px"),a.style.display="block"):a.style.display="none",t.name&&"Unnamed"!==t.name?(l.textContent=t.name,l.style.display="block",l.style.left="".concat(d.left,"px"),l.style.top="".concat(d.top-22,"px")):l.style.display="none"}},e.prototype.removeLinkOverlay=function(e){var t=this.debugLinkOverlays.get(e);t&&(t.linkOverlay.remove(),t.expandedOverlay.remove(),t.nameLabel.remove(),this.debugLinkOverlays.delete(e))},e.prototype.updateAllLinkVisuals=function(e){var t=this;if(this.shadowRoot&&this.debugContainer){var i=new Set(e.keys());this.debugLinkOverlays.forEach((function(e,n){i.has(n)||t.removeLinkOverlay(n)})),e.forEach((function(e,i){t.createOrUpdateLinkOverlay(i,e)}))}},e.prototype.updateTrajectoryVisuals=function(e,t,i){if(this.shadowRoot&&this.debugContainer&&(this.debugPredictedMouseIndicator&&(this.debugPredictedMouseIndicator.style.left="".concat((null==t?void 0:t.x)||0,"px"),this.debugPredictedMouseIndicator.style.top="".concat((null==t?void 0:t.y)||0,"px"),this.debugPredictedMouseIndicator.style.display=i&&t?"block":"none"),this.debugTrajectoryLine))if(i&&e&&t){var n=t.x-e.x,o=t.y-e.y,r=Math.sqrt(n*n+o*o),s=180*Math.atan2(o,n)/Math.PI;this.debugTrajectoryLine.style.left="".concat(e.x,"px"),this.debugTrajectoryLine.style.top="".concat(e.y,"px"),this.debugTrajectoryLine.style.width="".concat(r,"px"),this.debugTrajectoryLine.style.transform="translateY(-50%) rotate(".concat(s,"deg)"),this.debugTrajectoryLine.style.display="block"}else this.debugTrajectoryLine.style.display="none"},e.prototype.createDebugControls=function(e){var t=this;if(this.shadowRoot){this.debugControlsContainer=document.createElement("div"),this.debugControlsContainer.id="jsforesight-debug-controls",this.shadowRoot.appendChild(this.debugControlsContainer),this.debugControlsContainer.innerHTML='\n <div class="jsforesight-debugger-title-container">\n <h3>Foresight Debugger</h3>\n <span class="jsforesight-info-icon" title="Changes made here are for the current session only and won\'t persist. Update initial values in the ForesightManager.initialize() props for permanent changes.">i</span>\n </div>\n <div class="control-row">\n <label for="jsforesight-trajectory-enabled">\n Enable Mouse Prediction\n <span class="jsforesight-info-icon" title="Toggles mouse movement prediction. If disabled, only direct hovers trigger actions.">i</span>\n </label>\n <input type="checkbox" id="jsforesight-trajectory-enabled" '.concat(e.enableMousePrediction?"checked":"",'>\n </div>\n <div class="control-row">\n <label for="jsforesight-history-size">\n History Size\n <span class="jsforesight-info-icon" title="Number of past mouse positions for velocity calculation (Min: 2, Max: 20). Higher values smooth predictions but add latency.">i</span>\n </label>\n <input type="range" id="jsforesight-history-size" min="2" max="20" value="').concat(e.positionHistorySize,'">\n <span id="jsforesight-history-value">').concat(e.positionHistorySize,'</span>\n </div>\n <div class="control-row">\n <label for="jsforesight-prediction-time">\n Prediction Time (ms)\n <span class="jsforesight-info-icon" title="How far (ms) to project trajectory (Min: 10, Max: 500). Larger values detect intent sooner.">i</span>\n </label>\n <input type="range" id="jsforesight-prediction-time" min="10" max="500" step="10" value="').concat(e.trajectoryPredictionTime,'">\n <span id="jsforesight-prediction-value">').concat(e.trajectoryPredictionTime,'</span>\n </div>\n <div class="control-row">\n <label for="jsforesight-throttle-delay">\n Scroll/Resize Throttle (ms)\n <span class="jsforesight-info-icon" title="Delay (ms) for recalculating element positions on resize/scroll (Min: 0, Max: 500). Higher values improve performance during rapid events.">i</span>\n </label>\n <input type="range" id="jsforesight-throttle-delay" min="0" max="500" step="10" value="').concat(e.resizeScrollThrottleDelay,'">\n <span id="jsforesight-throttle-value">').concat(e.resizeScrollThrottleDelay,"</span>\n </div>\n ");var i=this.debugControlsContainer.querySelector("#jsforesight-trajectory-enabled");i.addEventListener("change",(function(){t.foresightManagerInstance.alterGlobalSettings({enableMousePrediction:i.checked})}));var n=this.debugControlsContainer.querySelector("#jsforesight-history-size"),o=this.debugControlsContainer.querySelector("#jsforesight-history-value");n.addEventListener("input",(function(){var e=parseInt(n.value);o.textContent=e.toString(),t.foresightManagerInstance.alterGlobalSettings({positionHistorySize:e})}));var r=this.debugControlsContainer.querySelector("#jsforesight-prediction-time"),s=this.debugControlsContainer.querySelector("#jsforesight-prediction-value");r.addEventListener("input",(function(){var e=parseInt(r.value);s.textContent=e.toString(),t.foresightManagerInstance.alterGlobalSettings({trajectoryPredictionTime:e})}));var a=this.debugControlsContainer.querySelector("#jsforesight-throttle-delay"),l=this.debugControlsContainer.querySelector("#jsforesight-throttle-value");a.addEventListener("input",(function(){var e=parseInt(a.value);l.textContent=e.toString(),t.foresightManagerInstance.alterGlobalSettings({resizeScrollThrottleDelay:e})}))}},e.prototype.updateControlsState=function(e){if(this.debugControlsContainer){var t=this.debugControlsContainer.querySelector("#jsforesight-trajectory-enabled");t&&(t.checked=e.enableMousePrediction);var i=this.debugControlsContainer.querySelector("#jsforesight-history-size"),n=this.debugControlsContainer.querySelector("#jsforesight-history-value");i&&n&&(i.value=e.positionHistorySize.toString(),n.textContent=e.positionHistorySize.toString());var o=this.debugControlsContainer.querySelector("#jsforesight-prediction-time"),r=this.debugControlsContainer.querySelector("#jsforesight-prediction-value");o&&r&&(o.value=e.trajectoryPredictionTime.toString(),r.textContent=e.trajectoryPredictionTime.toString());var s=this.debugControlsContainer.querySelector("#jsforesight-throttle-delay"),a=this.debugControlsContainer.querySelector("#jsforesight-throttle-value");s&&a&&(s.value=e.resizeScrollThrottleDelay.toString(),a.textContent=e.resizeScrollThrottleDelay.toString())}},e}(),i=function(){function i(){var t=this;this.links=new Map,this.isSetup=!1,this.debugMode=!1,this.debugger=null,this.globalSettings={debug:!1,enableMousePrediction:!0,positionHistorySize:8,trajectoryPredictionTime:80,defaultHitSlop:{top:0,left:0,right:0,bottom:0},resizeScrollThrottleDelay:50},this.positions=[],this.currentPoint={x:0,y:0},this.predictedPoint={x:0,y:0},this.lastResizeScrollCallTimestamp=0,this.resizeScrollThrottleTimeoutId=null,this.normalizeHitSlop=function(e){return"number"==typeof e?{top:e,left:e,right:e,bottom:e}:e},this.predictMousePosition=function(e){var i={point:e,time:performance.now()},n=e.x,o=e.y;if(t.positions.push(i),t.positions.length>t.globalSettings.positionHistorySize&&t.positions.shift(),t.positions.length<2)return{x:n,y:o};var r=t.positions[0],s=t.positions[t.positions.length-1],a=(s.time-r.time)/1e3;if(0===a)return{x:n,y:o};var l=(s.point.x-r.point.x)/a,d=(s.point.y-r.point.y)/a,c=t.globalSettings.trajectoryPredictionTime/1e3;return{x:n+l*c,y:o+d*c}},this.isMouseInExpandedArea=function(e,t,i){var n=t.x>=e.left&&t.x<=e.right&&t.y>=e.top&&t.y<=e.bottom;return n&&!i?{isHoveringInArea:!0,shouldRunCallback:!0}:{isHoveringInArea:n,shouldRunCallback:!1}},this.handleMouseMove=function(i){t.currentPoint={x:i.clientX,y:i.clientY},t.predictedPoint=t.globalSettings.enableMousePrediction?t.predictMousePosition(t.currentPoint):t.currentPoint;var n=[];t.links.forEach((function(i,o){if(i.elementBounds.expandedRect){var r=t.isMouseInExpandedArea(i.elementBounds.expandedRect,t.currentPoint,i.isHovering),s=r.isHoveringInArea,a=r.shouldRunCallback,l=!1;t.globalSettings.enableMousePrediction&&!s&&t.lineSegmentIntersectsRect(t.currentPoint,t.predictedPoint,i.elementBounds.expandedRect)&&(i.isTrajectoryHit||(i.callback(),t.links.set(o,e(e({},i),{isTrajectoryHit:!0,trajectoryHitTime:performance.now(),isHovering:s})),l=!0)),i.isHovering!==s&&(t.links.set(o,e(e({},i),{isHovering:s,isTrajectoryHit:t.links.get(o).isTrajectoryHit,trajectoryHitTime:t.links.get(o).trajectoryHitTime})),l=!0),l&&n.push(o),a&&(!i.isTrajectoryHit||i.isTrajectoryHit&&!t.globalSettings.enableMousePrediction)&&i.callback()}})),t.debugMode&&t.debugger&&(n.forEach((function(e){var i=t.links.get(e);i&&t.debugger.createOrUpdateLinkOverlay(e,i)})),t.debugger.updateTrajectoryVisuals(t.currentPoint,t.predictedPoint,t.globalSettings.enableMousePrediction))},this.handleResizeOrScroll=function(){t.resizeScrollThrottleTimeoutId&&clearTimeout(t.resizeScrollThrottleTimeoutId);var e=performance.now(),i=e-t.lastResizeScrollCallTimestamp,n=t.globalSettings.resizeScrollThrottleDelay;i>=n?(t.updateAllRects(),t.lastResizeScrollCallTimestamp=e,t.resizeScrollThrottleTimeoutId=null):t.resizeScrollThrottleTimeoutId=setTimeout((function(){t.updateAllRects(),t.lastResizeScrollCallTimestamp=performance.now(),t.resizeScrollThrottleTimeoutId=null}),n-i)},this.globalSettings.defaultHitSlop=this.normalizeHitSlop(this.globalSettings.defaultHitSlop),setInterval(this.checkTrajectoryHitExpiration.bind(this),100)}return i.initialize=function(e){return i.manager?e&&(console.warn("ForesightManager is already initialized. Use alterGlobalSettings to update settings. Make sure to not put the ForesightManager.initialize() in a place that rerenders often."),i.manager.alterGlobalSettings(e)):(i.manager=new i,e?i.manager.alterGlobalSettings(e):i.manager.globalSettings.debug&&i.manager.turnOnDebugMode()),i.manager.debugMode=i.manager.globalSettings.debug,i.manager},Object.defineProperty(i,"instance",{get:function(){return i.manager?i.manager:this.initialize()},enumerable:!1,configurable:!0}),i.prototype.checkTrajectoryHitExpiration=function(){var t=this,i=performance.now(),n=!1,o=[];this.links.forEach((function(r,s){r.isTrajectoryHit&&i-r.trajectoryHitTime>100&&(t.links.set(s,e(e({},r),{isTrajectoryHit:!1})),n=!0,o.push(s))})),n&&this.debugMode&&this.debugger&&o.forEach((function(e){var i=t.links.get(e);i&&t.debugger&&t.debugger.createOrUpdateLinkOverlay(e,i)}))},i.prototype.register=function(e,t,i,n){var o=this,r=i?this.normalizeHitSlop(i):this.globalSettings.defaultHitSlop,s=e.getBoundingClientRect(),a={callback:t,elementBounds:{expandedRect:this.getExpandedRect(s,r),originalRect:s,hitSlop:r},isHovering:!1,isTrajectoryHit:!1,trajectoryHitTime:0,name:null!=n?n:"Unnamed"};if(this.links.set(e,a),this.setupGlobalListeners(),this.debugMode&&this.debugger){var l=this.links.get(e);l&&this.debugger.createOrUpdateLinkOverlay(e,l)}return function(){return o.unregister(e)}},i.prototype.unregister=function(e){this.links.delete(e),this.debugMode&&this.debugger&&this.debugger.removeLinkOverlay(e),0===this.links.size&&this.isSetup&&this.removeGlobalListeners()},i.prototype.alterGlobalSettings=function(e){var t=!1;void 0!==(null==e?void 0:e.enableMousePrediction)&&this.globalSettings.enableMousePrediction!==e.enableMousePrediction&&(this.globalSettings.enableMousePrediction=e.enableMousePrediction,t=!0,this.globalSettings.enableMousePrediction?this.predictedPoint=this.predictMousePosition(this.currentPoint):this.predictedPoint=this.currentPoint),void 0!==(null==e?void 0:e.debug)&&this.globalSettings.debug!==e.debug&&(this.globalSettings.debug=e.debug,this.globalSettings.debug?this.turnOnDebugMode():this.debugger&&(this.debugger.cleanup(),this.debugger=null),this.debugMode=this.globalSettings.debug),t&&this.globalSettings.debug&&this.debugger&&(this.debugger.updateControlsState(this.globalSettings),this.debugger.updateTrajectoryVisuals(this.currentPoint,this.predictedPoint,this.globalSettings.enableMousePrediction))},i.prototype.turnOnDebugMode=function(){this.debugMode=!0,this.debugger?(this.debugger.updateControlsState(this.globalSettings),this.debugger.updateTrajectoryVisuals(this.currentPoint,this.predictedPoint,this.globalSettings.enableMousePrediction)):(this.debugger=new t(this),this.debugger.initialize(this.links,this.globalSettings,this.currentPoint,this.predictedPoint))},i.prototype.getExpandedRect=function(e,t){return{left:e.left-t.left,right:e.right+t.right,top:e.top-t.top,bottom:e.bottom+t.bottom}},i.prototype.updateExpandedRect=function(t,i){var n=this.links.get(t);if(n){var o=this.getExpandedRect(t.getBoundingClientRect(),i);if(JSON.stringify(o)!==JSON.stringify(n.elementBounds.expandedRect)&&this.links.set(t,e(e({},n),{elementBounds:e(e({},n.elementBounds),{expandedRect:o})})),this.debugMode&&this.debugger){var r=this.links.get(t);r&&this.debugger.createOrUpdateLinkOverlay(t,r)}}},i.prototype.updateAllRects=function(){var e=this;this.links.forEach((function(t,i){e.updateExpandedRect(i,t.elementBounds.hitSlop)}))},i.prototype.lineSegmentIntersectsRect=function(e,t,i){var n=0,o=1,r=t.x-e.x,s=t.y-e.y,a=function(e,t){if(0===e){if(t<0)return!1}else{var i=t/e;if(e<0){if(i>o)return!1;i>n&&(n=i)}else{if(i<n)return!1;i<o&&(o=i)}}return!0};return!!a(-r,e.x-i.left)&&(!!a(r,i.right-e.x)&&(!!a(-s,e.y-i.top)&&(!!a(s,i.bottom-e.y)&&n<=o)))},i.prototype.setupGlobalListeners=function(){this.isSetup||(document.addEventListener("mousemove",this.handleMouseMove),window.addEventListener("resize",this.handleResizeOrScroll),window.addEventListener("scroll",this.handleResizeOrScroll),this.isSetup=!0)},i.prototype.removeGlobalListeners=function(){document.removeEventListener("mousemove",this.handleMouseMove),window.removeEventListener("resize",this.handleResizeOrScroll),window.removeEventListener("scroll",this.handleResizeOrScroll),this.resizeScrollThrottleTimeoutId&&(clearTimeout(this.resizeScrollThrottleTimeoutId),this.resizeScrollThrottleTimeoutId=null),this.isSetup=!1},i}();exports.ForesightManager=i;
|
|
2
|
-
//# sourceMappingURL=index.js.map
|