import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/en/functional-basic/Classes/EventItem - Advanced Event Management'/>

# EventItem Class

A powerful wrapper for managing event listeners on DOM elements or the `window` object. The class simplifies working with the event lifecycle (add, remove, toggle), supports automatic checking of the element's presence in the DOM, and provides built-in optimization for heavy events such as `resize` and `scroll`.

## Key Features

- **Lifecycle Management** — convenient `start`, `stop`, `toggle`, and `reset` methods to control event listening.
- **DOM Safety** — automatic `isInDom` check before executing the handler (a control element can be configured).
- **ResizeObserver Support** — built-in handling of the `resize` event for any HTML elements via a modern API.
- **Scroll Optimization** — a special `scroll-sync` event type using `requestAnimationFrame` for high performance.
- **Chaining and Flexibility** — support for call chaining and dynamic changing of the target, type, or event handler.
- **Custom Data** — the ability to pass and dispatch custom data via `CustomEvent`.

## Initialization

To initialize the object, call the constructor `EventItem(elementSelector, type, listener, options, detail)`.

### Generic Constraints

To ensure strict typing, the class supports the following generics:
- `E extends ElementOrWindow` — The type of element on which events are listened.
- `O extends Event` — The type of the event object.
- `D extends Record<string, any>` — The structure of additional data.

**Parameters:**
- `elementSelector?: ElementOrString<E>` — the target element on which the listener is attached.
- `type: string | string[] = 'click'` — event type, array of types, or special types (`'resize'`, `'scroll-sync'`).
- `listener?: EventListenerDetail<O, D>` — the event handler function.
- `options?: EventOptions` — standard `addEventListener` options.
- `detail?: D` — custom data that will be available in the handler.

```typescript
import { EventItem } from '@dxtmisha/functional-basic'

// 1. Basic initialization
const myEvent = new EventItem(
  '.my-button', 
  'click', 
  (event) => console.log('Event triggered:', event.type)
)

// 2. Using generics for strict typing
interface MyData { id: number }
const customEvent = new EventItem<Window, MouseEvent, MyData>(
  window,
  'mousedown',
  (event, detail) => {
    console.log('Window click, data ID:', detail?.id)
  },
  { passive: true },
  { id: 42 }
)

// 3. Activating listening
myEvent.start()
customEvent.start()
```

## Methods

### Information

- `isActive(): boolean` — Checks if event listening is currently active.
- `getElement(): E | undefined` — Returns the current target element.

### Configuration (Setters)

All methods in this group support chaining and automatically call `reset()` if the event is active.

- `setElement(elementSelector?: ElementOrString): this` — Changes the target element.
- `setElementControl(elementSelector?: ElementOrString): this` — Sets the control element (if it is not in the DOM, the event will not fire).
- `setType(type: string | string[]): this` — Changes the event type.
- `setListener(listener: Function): this` — Changes the handler function.
- `setOptions(options?: EventOptions): this` — Changes the listener parameters.
- `setDetail(detail?: D): this` — Changes the custom event data.

### Management

- `start(): this` — Starts event listening.
- `stop(): this` — Stops event listening.
- `toggle(activity: boolean): this` — Enables or disables listening depending on the flag.
- `reset(): this` — Restarts the event (useful after changing settings).
- `dispatch(detail?: D): this` — Triggers the event on the target element with data transfer.

## Types

#### `ElementOrWindow`
Element on which an event can be attached: `HTMLElement | Window`.

#### `ElementOrString<E>`
Type for passing an element or its selector: `E | string`.

#### `EventListenerDetail<O, D>`
Event listener function: `(event: O, detail?: D) => void`.

#### `EventOptions`
Listening options: `AddEventListenerOptions | boolean | undefined`.

#### `EventActivityItem<E>`
Internal interface for tracking active listeners.
- `element: E | undefined` — Target element.
- `type: string` — Event type.
- `listener?: (event: any) => void` — Active function.
- `observer?: ResizeObserver` — Observer instance (for `resize`).

## Special Events

### `resize`
If the event type is set to `resize`, the class automatically uses `ResizeObserver` to track changes in the size of the element (even if it is not `window`).

### `scroll-sync`
A special type for optimized scrolling. Internally uses `requestAnimationFrame`, preventing unnecessary handler calls and increasing performance.

## Examples

### Dynamic Element Switching
```javascript
const tracker = new EventItem('.item-1', 'mousemove', (e) => {
  console.log('Coordinates:', e.clientX)
})

tracker.start()

// ... switch to another element later
tracker.setElement('.item-2')
```

### Using CustomEvent with Data
```javascript
const emitter = new EventItem(window, 'my-custom-event')

emitter.setListener((e, detail) => {
  console.log('Data received:', e.detail) // data from CustomEvent
})

emitter.start()

// Dispatch event
emitter.dispatch({ userId: 123, action: 'refresh' })
```
