An extremely fast, React-like JavaScript library for building modern user interfaces
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Optimized event handling system with linkEvent for performance optimization and comprehensive synthetic event support for cross-browser compatibility.
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
})
])
)
);
}
}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>;Comprehensive event handler types for all standard DOM events:
type EventHandler<E extends SemiSyntheticEvent<any>> =
| { bivarianceHack(event: E): void }['bivarianceHack']
| LinkedEvent<any, E>
| null;
type InfernoEventHandler<T = Element> = EventHandler<SemiSyntheticEvent<T>>;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>>;Inferno provides synthetic events for cross-browser compatibility:
interface SemiSyntheticEvent<T> extends Event {
/** A reference to the element on which the event listener is registered */
currentTarget: EventTarget & T;
isDefaultPrevented?: () => boolean;
isPropagationStopped?: () => boolean;
}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;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)
});
}
}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
});
}
}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'
});
}
}Inferno uses event delegation for improved performance:
Synthetic events provide consistent behavior across browsers: