CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-chakra-ui--utils

Common utilities and types for Chakra UI providing type checking, object manipulation, DOM utilities, and React helpers

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

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;
}

Install with Tessl CLI

npx tessl i tessl/npm-chakra-ui--utils

docs

dom-events.md

dom-utilities.md

focus-accessibility.md

function-utilities.md

index.md

math-utilities.md

object-manipulation.md

react-utilities.md

responsive.md

type-checking.md

tile.json