# Events

ForesightManager emits events for element registration, prediction, and callback execution. The [ForesightJS DevTools](/docs/debugging/devtools.md) use them for visual debugging, and you can listen to them yourself for telemetry, analytics, or counters.

## Usage[​](#usage "Direct link to Usage")

All events are visible in the logs tab of the [devtools](/docs/debugging/devtools.md). However for tracking/analytics in production, implementing them in your own code is straightforward with the standard `addEventListener` pattern.

```
import { ForesightManager } from "js.foresight"

// Define handler as const for removal
const handleCallbackCompleted = event => {
  console.log(
    `Callback executed for ${event.state.name} in ${event.hitType.kind} mode, which took ${event.elapsed} ms`
  )
}

// Add the event
ForesightManager.instance.addEventListener("callbackCompleted", handleCallbackCompleted)

// Later, remove the listener using the same reference
ForesightManager.instance.removeEventListener("callbackCompleted", handleCallbackCompleted)
```

### AbortController support[​](#abortcontroller-support "Direct link to AbortController support")

Event listeners support [AbortController signals](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) for easy cleanup.

```
const controller = new AbortController()

manager.addEventListener("callbackCompleted", handleCallbackCompleted, {
  signal: controller.signal,
})

controller.abort()
```

## Available Events[​](#available-events "Direct link to Available Events")

### Interaction Events[​](#interaction-events "Direct link to Interaction Events")

Events fired when user interactions trigger callbacks.

***

#### `callbackInvoked`[​](#callbackinvoked "Direct link to callbackinvoked")

Fired **before** an element's callback is executed

```
type CallbackInvokedEvent = {
  type: "callbackInvoked"
  timestamp: number
  element: ForesightElement
  state: ForesightElementState
  hitType: CallbackHitType
}
```

**Related Types:** [`CallbackHitType`](/docs/getting-started/typescript.md#callbackhittype) • [`ForesightElementState`](/docs/getting-started/typescript.md#foresightelementstate)

***

#### `callbackCompleted`[​](#callbackcompleted "Direct link to callbackcompleted")

Fired **after** an element's callback is executed

```
type CallbackCompletedEvent = {
  type: "callbackCompleted"
  timestamp: number
  element: ForesightElement
  state: ForesightElementState
  hitType: CallbackHitType
  elapsed: number // Time between callbackInvoked and callbackCompleted
  status: "success" | "error" | undefined
  errorMessage: string | null
  wasLastActiveElement: boolean
}
```

**Related Types:** [`CallbackHitType`](/docs/getting-started/typescript.md#callbackhittype) • [`ForesightElementState`](/docs/getting-started/typescript.md#foresightelementstate)

### Element Lifecycle Events[​](#element-lifecycle-events "Direct link to Element Lifecycle Events")

Events fired during element registration, updates, and cleanup.

***

#### `elementRegistered`[​](#elementregistered "Direct link to elementregistered")

Fired when an element is successfully registered with `ForesightManager` using `ForesightManager.instance.register(element)`.

```
type ElementRegisteredEvent = {
  type: "elementRegistered"
  timestamp: number
  element: ForesightElement
  state: ForesightElementState
}
```

**Related Types:** [`ForesightElementState`](/docs/getting-started/typescript.md#foresightelementstate)

***

#### `elementUnregistered`[​](#elementunregistered "Direct link to elementunregistered")

Fired when an element is removed from `ForesightManager`'s tracking via `ForesightManager.instance.unregister(element)`. Detaching an element from the DOM no longer unregisters it. It is parked (kept registered but inactive) and resumed on reattach, so no `elementUnregistered` event fires for that. The `"disconnected"` reason is therefore no longer emitted.

```
type ElementUnregisteredEvent = {
  type: "elementUnregistered"
  timestamp: number
  element: ForesightElement
  state: ForesightElementState
  unregisterReason: "disconnected" | "apiCall" | "devtools" | (string & {})
  wasLastRegisteredElement: boolean
}
```

**Related Types:** [`ForesightElementState`](/docs/getting-started/typescript.md#foresightelementstate)

***

### Prediction Events[​](#prediction-events "Direct link to Prediction Events")

Events fired during movement prediction calculations.

***

#### `mouseTrajectoryUpdate`[​](#mousetrajectoryupdate "Direct link to mousetrajectoryupdate")

Fired during mouse movement for trajectory calculations

```
type MouseTrajectoryUpdateEvent = {
  type: "mouseTrajectoryUpdate"
  trajectoryPositions: {
    positions: CircularBuffer<MousePosition> // mouse position history
    currentPoint: { x: number; y: number }
    predictedPoint: { x: number; y: number }
  }
  predictionEnabled: boolean
}
```

***

#### `scrollTrajectoryUpdate`[​](#scrolltrajectoryupdate "Direct link to scrolltrajectoryupdate")

Fired during scroll events when scroll prediction is active

```
type ScrollTrajectoryUpdateEvent = {
  type: "scrollTrajectoryUpdate"
  currentPoint: Point // { x: number; y: number }
  predictedPoint: Point // { x: number; y: number }
  scrollDirection: ScrollDirection // "down" | "up" | "left" | "right"
}
```

***

### Configuration Events[​](#configuration-events "Direct link to Configuration Events")

Events fired when ForesightManager configuration changes.

***

#### `managerSettingsChanged`[​](#managersettingschanged "Direct link to managersettingschanged")

Fired when global `ForesightManager` settings are updated via the devtools or via `ForesightManager.instance.alterGlobalSettings()`.

```
type ManagerSettingsChangedEvent = {
  type: "managerSettingsChanged"
  timestamp: number
  managerData: Readonly<ForesightManagerData>
  updatedSettings: UpdatedManagerSetting[]
}
```

**Related Types:** [`ForesightManagerData`](/docs/getting-started/typescript.md#foresightmanagerdata)

***

#### `deviceStrategyChanged`[​](#devicestrategychanged "Direct link to devicestrategychanged")

Fired when user switches between input methods (mouse, touch, or pen).

```
type DeviceStrategyChangedEvent = {
  type: "deviceStrategyChanged"
  timestamp: number
  newStrategy: CurrentDeviceStrategy // "mouse" | "touch" | "pen"
  oldStrategy: CurrentDeviceStrategy // "mouse" | "touch" | "pen"
}
```

***
