or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

dom-events.mddom-utilities.mdfocus-accessibility.mdfunction-utilities.mdindex.mdmath-utilities.mdobject-manipulation.mdreact-utilities.mdresponsive.mdtype-checking.md
tile.json

dom-events.mddocs/

DOM and Event Utilities

Cross-browser DOM utilities for event handling, element queries, pointer interactions, and window/document management. These utilities provide a unified API for mouse, touch, and pointer events while handling browser compatibility and providing cleanup mechanisms.

Capabilities

Event Management

Utilities for adding and managing DOM event listeners with automatic cleanup.

/**
 * Adds a DOM event listener and returns a cleanup function
 * @param target - Element or EventTarget to attach listener to
 * @param eventName - Name of the event to listen for
 * @param handler - Event handler function
 * @param options - Optional event listener options
 * @returns Cleanup function to remove the event listener
 */
function addDomEvent(
  target: EventTarget,
  eventName: string,
  handler: EventListener,
  options?: AddEventListenerOptions
): () => void;

/**
 * Adds pointer event with mouse button filtering for pointerdown events
 * @param target - Element or EventTarget to attach listener to
 * @param type - Pointer event type
 * @param cb - Mixed event listener that receives both event and point info
 * @param options - Optional event listener options
 * @returns Cleanup function to remove the event listener
 */
function addPointerEvent(
  target: EventTarget,
  type: string,
  cb: MixedEventListener,
  options?: AddEventListenerOptions
): () => void;

interface MixedEventListener {
  (e: AnyPointerEvent, info: PointerEventInfo): void;
}

interface PointerEventInfo {
  point: Point;
}

type AnyPointerEvent = MouseEvent | TouchEvent | PointerEvent;

Usage Examples:

import { addDomEvent, addPointerEvent } from "@chakra-ui/utils";

// Basic event listener with cleanup
function useClickOutside(ref: React.RefObject<HTMLElement>, callback: () => void) {
  React.useEffect(() => {
    const cleanup = addDomEvent(document, "click", (event) => {
      if (ref.current && !ref.current.contains(event.target as Node)) {
        callback();
      }
    });

    return cleanup; // Automatic cleanup on unmount
  }, [ref, callback]);
}

// Pointer event handling
function useDrag(elementRef: React.RefObject<HTMLElement>) {
  React.useEffect(() => {
    if (!elementRef.current) return;

    const cleanupPointerDown = addPointerEvent(
      elementRef.current,
      "pointerdown",
      (event, info) => {
        console.log("Drag started at:", info.point);
        // Start drag logic
      }
    );

    const cleanupPointerMove = addPointerEvent(
      document,
      "pointermove",
      (event, info) => {
        console.log("Dragging to:", info.point);
        // Update drag position
      }
    );

    return () => {
      cleanupPointerDown();
      cleanupPointerMove();
    };
  }, []);
}

Event Point Extraction

Utilities for extracting coordinate information from various event types.

/**
 * Gets coordinate point from mouse, touch, or pointer events
 * @param event - Pointer event (mouse, touch, or pointer)
 * @param type - Coordinate type ("page" or "client")
 * @returns Point object with x and y coordinates
 */
function getEventPoint(event: AnyPointerEvent, type?: PointType): Point;

interface Point {
  x: number;
  y: number;
}

type PointType = "page" | "client";

Usage Examples:

import { getEventPoint } from "@chakra-ui/utils";

function handleInteraction(event: MouseEvent | TouchEvent) {
  // Get page coordinates (relative to document)
  const pagePoint = getEventPoint(event, "page");
  console.log("Page coordinates:", pagePoint.x, pagePoint.y);
  
  // Get client coordinates (relative to viewport)
  const clientPoint = getEventPoint(event, "client");
  console.log("Viewport coordinates:", clientPoint.x, clientPoint.y);
}

// React component example
function DraggableBox() {
  const [position, setPosition] = React.useState({ x: 0, y: 0 });
  
  const handleMouseMove = (event: MouseEvent) => {
    const point = getEventPoint(event, "client");
    setPosition(point);
  };
  
  return (
    <div
      onMouseMove={handleMouseMove}
      style={{ transform: `translate(${position.x}px, ${position.y}px)` }}
    >
      Draggable content
    </div>
  );
}

Event Type Detection

Utilities for detecting and handling different event types.

/**
 * Type guard that checks if an event is a MouseEvent
 * @param event - Event to check
 * @returns true if event is a MouseEvent
 */
function isMouseEvent(event: any): event is MouseEvent;

/**
 * Type guard that checks if an event is a TouchEvent
 * @param event - Pointer event to check
 * @returns true if event is a TouchEvent
 */
function isTouchEvent(event: AnyPointerEvent): event is TouchEvent;

/**
 * Checks if a touch event has multiple touch points
 * @param event - Pointer event to check
 * @returns true if event is a multi-touch event
 */
function isMultiTouchEvent(event: AnyPointerEvent): boolean;

Usage Examples:

import { isMouseEvent, isTouchEvent, isMultiTouchEvent } from "@chakra-ui/utils";

function handlePointerEvent(event: AnyPointerEvent) {
  if (isMouseEvent(event)) {
    // Handle mouse-specific logic
    console.log("Mouse button:", event.button);
    console.log("Ctrl key:", event.ctrlKey);
  } else if (isTouchEvent(event)) {
    if (isMultiTouchEvent(event)) {
      // Handle multi-touch gestures
      console.log("Touch count:", event.touches.length);
    } else {
      // Handle single touch
      console.log("Single touch at:", event.touches[0].clientX, event.touches[0].clientY);
    }
  }
}

Element Containment

Utilities for checking element relationships.

/**
 * Checks if a parent element contains a child element
 * @param parent - Parent element (can be null)
 * @param child - Child element to check
 * @returns true if parent contains child
 */
function contains(parent: HTMLElement | null, child: HTMLElement): boolean;

Usage Examples:

import { contains } from "@chakra-ui/utils";

function useOutsideClick(ref: React.RefObject<HTMLElement>, callback: () => void) {
  React.useEffect(() => {
    function handleClick(event: MouseEvent) {
      const target = event.target as HTMLElement;
      
      if (ref.current && !contains(ref.current, target)) {
        callback();
      }
    }
    
    document.addEventListener("click", handleClick);
    return () => document.removeEventListener("click", handleClick);
  }, [ref, callback]);
}

// Modal component with outside click detection
function Modal({ isOpen, onClose, children }: ModalProps) {
  const modalRef = React.useRef<HTMLDivElement>(null);
  
  useOutsideClick(modalRef, onClose);
  
  if (!isOpen) return null;
  
  return (
    <div className="modal-overlay">
      <div ref={modalRef} className="modal-content">
        {children}
      </div>
    </div>
  );
}

Window and Document Management

Utilities for accessing window and document objects across different contexts.

/**
 * Gets the owner window of an element
 * @param node - Element to get window for (optional)
 * @returns Window object (globalThis if no element provided)
 */
function getOwnerWindow(node?: Element | null): typeof globalThis;

/**
 * Gets the owner document of an element
 * @param node - Element to get document for (optional)
 * @returns Document object
 */
function getOwnerDocument(node?: Element | null): Document;

/**
 * Gets the window object from an event
 * @param event - Event to extract window from
 * @returns Window object
 */
function getEventWindow(event: Event): typeof window;

/**
 * Gets the currently active element in a document
 * @param node - Optional element to get active element relative to
 * @returns Currently focused element
 */
function getActiveElement(node?: HTMLElement): HTMLElement;

Usage Examples:

import { 
  getOwnerWindow, 
  getOwnerDocument, 
  getEventWindow,
  getActiveElement 
} from "@chakra-ui/utils";

// Cross-frame compatible utilities
function scrollToTop(element?: HTMLElement) {
  const window = getOwnerWindow(element);
  const document = getOwnerDocument(element);
  
  window.scrollTo({
    top: 0,
    left: 0,
    behavior: "smooth"
  });
}

// Focus management
function saveFocus() {
  const activeElement = getActiveElement();
  
  return () => {
    if (activeElement && activeElement.focus) {
      activeElement.focus();
    }
  };
}

// Event window detection
function handleWindowEvent(event: Event) {
  const eventWindow = getEventWindow(event);
  
  if (eventWindow !== window) {
    console.log("Event from different window/frame");
  }
}

// Portal-compatible hook
function usePortalCompatibleEffect(
  callback: (window: Window, document: Document) => void,
  deps: any[],
  portalContainer?: HTMLElement
) {
  React.useEffect(() => {
    const window = getOwnerWindow(portalContainer);
    const document = getOwnerDocument(portalContainer);
    
    callback(window, document);
  }, deps);
}

Scroll Parent Detection

Utility for finding scrollable parent elements.

/**
 * Finds the nearest scrollable parent element
 * @param el - Element to find scroll parent for
 * @returns Nearest scrollable parent element
 */
function getScrollParent(el: HTMLElement): HTMLElement;

Usage Examples:

import { getScrollParent } from "@chakra-ui/utils";

// Scroll element into view within its scroll container
function scrollIntoView(element: HTMLElement) {
  const scrollParent = getScrollParent(element);
  const elementRect = element.getBoundingClientRect();
  const parentRect = scrollParent.getBoundingClientRect();
  
  if (elementRect.top < parentRect.top) {
    // Element is above visible area
    scrollParent.scrollTop -= (parentRect.top - elementRect.top);
  } else if (elementRect.bottom > parentRect.bottom) {
    // Element is below visible area
    scrollParent.scrollTop += (elementRect.bottom - parentRect.bottom);
  }
}

// Virtual scrolling helper
function useScrollParent(ref: React.RefObject<HTMLElement>) {
  const [scrollParent, setScrollParent] = React.useState<HTMLElement | null>(null);
  
  React.useEffect(() => {
    if (ref.current) {
      setScrollParent(getScrollParent(ref.current));
    }
  }, [ref]);
  
  return scrollParent;
}