CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-inferno

An extremely fast, React-like JavaScript library for building modern user interfaces

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

event-handling.mddocs/

Event Handling

Optimized event handling system with linkEvent for performance optimization and comprehensive synthetic event support for cross-browser compatibility.

Capabilities

Link Event

Performance-optimized event handling that links data to event handlers to avoid closure creation.

/**
 * Links data to event handlers for performance optimization
 * @param data - Data to be passed as first argument to event handler
 * @param event - Event handler function that receives data and event
 * @returns LinkedEvent object or null if event is invalid
 */
function linkEvent<T, E extends Event>(
  data: T,
  event: (data: T, event: E) => void
): LinkedEvent<T, E> | null;

interface LinkedEvent<T, E extends Event> {
  data: T;
  event: (data: T, event: E) => void;
}

Usage Examples:

import { linkEvent, createVNode, VNodeFlags } from "inferno";

class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = { todos: [] };
  }

  // Event handler that receives data and event
  handleRemoveTodo = (todoId, event) => {
    this.setState(prevState => ({
      todos: prevState.todos.filter(todo => todo.id !== todoId)
    }));
  };

  render() {
    return createVNode(VNodeFlags.HtmlElement, 'ul', null, 
      this.state.todos.map(todo => 
        createVNode(VNodeFlags.HtmlElement, 'li', null, [
          todo.text,
          createVNode(VNodeFlags.HtmlElement, 'button', null, 'Remove', ChildFlags.HasInvalidChildren, {
            // linkEvent passes todo.id as first argument to handler
            onClick: linkEvent(todo.id, this.handleRemoveTodo)
          })
        ])
      )
    );
  }
}

// Alternative without linkEvent (less efficient)
class TodoListSlow extends Component {
  handleRemoveTodo = (todoId) => (event) => {
    // Creates new closure for each todo item
    this.setState(prevState => ({
      todos: prevState.todos.filter(todo => todo.id !== todoId)
    }));
  };

  render() {
    return createVNode(VNodeFlags.HtmlElement, 'ul', null, 
      this.state.todos.map(todo => 
        createVNode(VNodeFlags.HtmlElement, 'li', null, [
          todo.text,
          createVNode(VNodeFlags.HtmlElement, 'button', null, 'Remove', ChildFlags.HasInvalidChildren, {
            onClick: this.handleRemoveTodo(todo.id) // Creates closure
          })
        ])
      )
    );
  }
}

Is Link Event Object

Utility function to check if an object is a linked event.

/**
 * Checks if an object is a linked event object
 * @param o - Object to check
 * @returns True if object is a LinkedEvent
 */
function isLinkEventObject(o: any): o is LinkedEvent<any, any>;

Event Types

Comprehensive event handler types for all standard DOM events:

Generic Event Handlers

type EventHandler<E extends SemiSyntheticEvent<any>> = 
  | { bivarianceHack(event: E): void }['bivarianceHack']
  | LinkedEvent<any, E>
  | null;

type InfernoEventHandler<T = Element> = EventHandler<SemiSyntheticEvent<T>>;

Specific Event Handlers

type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent<T>>;
type CompositionEventHandler<T = Element> = EventHandler<CompositionEvent<T>>;
type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>;
type FocusEventHandler<T = Element> = EventHandler<FocusEvent<T>>;
type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>;
type ChangeEventHandler<T = Element> = EventHandler<ChangeEvent<T>>;
type KeyboardEventHandler<T = Element> = EventHandler<InfernoKeyboardEvent<T>>;
type MouseEventHandler<T = Element> = EventHandler<InfernoMouseEvent<T>>;
type TouchEventHandler<T = Element> = EventHandler<InfernoTouchEvent<T>>;
type PointerEventHandler<T = Element> = EventHandler<InfernoPointerEvent<T>>;
type UIEventHandler<T = Element> = EventHandler<InfernoUIEvent<T>>;
type WheelEventHandler<T = Element> = EventHandler<InfernoWheelEvent<T>>;
type AnimationEventHandler<T = Element> = EventHandler<InfernoAnimationEvent<T>>;
type TransitionEventHandler<T = Element> = EventHandler<InfernoTransitionEvent<T>>;

Synthetic Events

Inferno provides synthetic events for cross-browser compatibility:

Base Synthetic Event

interface SemiSyntheticEvent<T> extends Event {
  /** A reference to the element on which the event listener is registered */
  currentTarget: EventTarget & T;
  isDefaultPrevented?: () => boolean;
  isPropagationStopped?: () => boolean;
}

Specific Event Types

type ClipboardEvent<T> = SemiSyntheticEvent<T> & NativeClipboardEvent;
type CompositionEvent<T> = SemiSyntheticEvent<T> & NativeCompositionEvent;
type DragEvent<T> = InfernoMouseEvent<T> & NativeDragEvent;
type FocusEvent<T> = SemiSyntheticEvent<T> & NativeFocusEvent;

interface FormEvent<T> extends SemiSyntheticEvent<T> {
  target: EventTarget & T;
}

interface ChangeEvent<T> extends SemiSyntheticEvent<T> {
  target: EventTarget & T;
}

type InfernoKeyboardEvent<T> = SemiSyntheticEvent<T> & KeyboardEvent;
type InfernoMouseEvent<T> = SemiSyntheticEvent<T> & MouseEvent & {
  target: EventTarget & T;
};
type InfernoTouchEvent<T> = SemiSyntheticEvent<T> & TouchEvent;
type InfernoPointerEvent<T> = SemiSyntheticEvent<T> & PointerEvent;
type InfernoUIEvent<T> = SemiSyntheticEvent<T> & UIEvent;
type InfernoWheelEvent<T> = InfernoMouseEvent<T> & WheelEvent;
type InfernoAnimationEvent<T> = SemiSyntheticEvent<T> & AnimationEvent;
type InfernoTransitionEvent<T> = SemiSyntheticEvent<T> & TransitionEvent;

Event Usage Examples

Mouse Events

class ClickableComponent extends Component {
  handleClick = (event: InfernoMouseEvent<HTMLButtonElement>) => {
    console.log('Button clicked', event.currentTarget);
    event.preventDefault();
  };

  handleMouseEnter = (message, event) => {
    console.log(message, event.type);
  };

  render() {
    return createVNode(VNodeFlags.HtmlElement, 'button', null, 'Click me', ChildFlags.HasInvalidChildren, {
      onClick: this.handleClick,
      onMouseEnter: linkEvent('Mouse entered!', this.handleMouseEnter)
    });
  }
}

Form Events

class FormComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };
  }

  handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    this.setState({ value: event.target.value });
  };

  handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log('Submitted:', this.state.value);
  };

  render() {
    return createVNode(VNodeFlags.HtmlElement, 'form', null, [
      createVNode(VNodeFlags.InputElement, 'input', null, null, ChildFlags.HasInvalidChildren, {
        type: 'text',
        value: this.state.value,
        onChange: this.handleChange
      }),
      createVNode(VNodeFlags.HtmlElement, 'button', null, 'Submit', ChildFlags.HasInvalidChildren, {
        type: 'submit'
      })
    ], ChildFlags.HasNonKeyedChildren, {
      onSubmit: this.handleSubmit
    });
  }
}

Keyboard Events

class KeyboardComponent extends Component {
  handleKeyDown = (event: InfernoKeyboardEvent<HTMLInputElement>) => {
    if (event.key === 'Enter') {
      console.log('Enter pressed');
    } else if (event.key === 'Escape') {
      console.log('Escape pressed');
    }
  };

  render() {
    return createVNode(VNodeFlags.InputElement, 'input', null, null, ChildFlags.HasInvalidChildren, {
      onKeyDown: this.handleKeyDown,
      placeholder: 'Press Enter or Escape'
    });
  }
}

Performance Benefits of linkEvent

  1. No Closure Creation: Avoids creating new functions for each render
  2. Memory Efficiency: Reduces memory usage in lists with many items
  3. Consistent Performance: Event handler creation cost is constant regardless of list size
  4. Garbage Collection: Fewer objects created means less GC pressure

Event Delegation

Inferno uses event delegation for improved performance:

  • Events are attached to the document root instead of individual elements
  • Single event listener handles all events of the same type
  • Reduces memory usage and improves performance for large DOMs
  • Automatically handles dynamically added/removed elements

Cross-Browser Compatibility

Synthetic events provide consistent behavior across browsers:

  • Normalized event properties and methods
  • Consistent event bubbling and capturing
  • Standardized preventDefault() and stopPropagation()
  • Touch event support for mobile devices
  • Pointer event support for modern browsers

docs

component-system.md

core-rendering.md

event-handling.md

fragments-utilities.md

index.md

refs.md

vnode-creation.md

tile.json