CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-dnd-kit--utilities

Internal utilities shared between @dnd-kit packages providing React hooks, coordinate manipulation, and DOM utilities.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

event-handling.mddocs/

Event Handling

Type guards and utilities for working with DOM events, including touch and keyboard event detection with cross-frame compatibility.

Capabilities

hasViewportRelativeCoordinates

Type guard that checks if an event has viewport-relative coordinate properties (clientX and clientY).

/**
 * Type guard for events with viewport-relative coordinates
 * @param event - DOM event to check
 * @returns True if event has clientX and clientY properties
 */
function hasViewportRelativeCoordinates(
  event: Event
): event is Event & Pick<PointerEvent, 'clientX' | 'clientY'>;

Usage Examples:

import { hasViewportRelativeCoordinates } from "@dnd-kit/utilities";

function handleGenericEvent(event: Event) {
  if (hasViewportRelativeCoordinates(event)) {
    // TypeScript now knows event has clientX and clientY
    console.log(`Coordinates: ${event.clientX}, ${event.clientY}`);
    
    // Safe to use coordinate properties
    const rect = event.target?.getBoundingClientRect();
    if (rect) {
      const relativeX = event.clientX - rect.left;
      const relativeY = event.clientY - rect.top;
      console.log(`Relative: ${relativeX}, ${relativeY}`);
    }
  } else {
    console.log("Event does not have coordinate information");
  }
}

// Use with multiple event types
element.addEventListener("mousedown", handleGenericEvent);
element.addEventListener("touchstart", handleGenericEvent);
element.addEventListener("keydown", handleGenericEvent); // Won't have coordinates

isKeyboardEvent

Type guard that determines if an event is a KeyboardEvent. Uses cross-frame compatible detection.

/**
 * Type guard for KeyboardEvent with cross-frame compatibility
 * @param event - Event to check (can be undefined or null)
 * @returns True if event is a KeyboardEvent
 */
function isKeyboardEvent(event: Event | undefined | null): event is KeyboardEvent;

Usage Examples:

import { isKeyboardEvent } from "@dnd-kit/utilities";

function handleInteractionEvent(event: Event | null) {
  if (isKeyboardEvent(event)) {
    // TypeScript knows this is a KeyboardEvent
    console.log(`Key pressed: ${event.key}`);
    console.log(`Ctrl key: ${event.ctrlKey}`);
    console.log(`Key code: ${event.code}`);
    
    // Handle specific keys
    if (event.key === "Enter") {
      console.log("Enter key pressed");
    }
    
    if (event.key === "Escape") {
      console.log("Escape key pressed");
    }
  }
}

// React example
import React from "react";

function KeyboardAwareComponent() {
  const handleKeyEvent = (event: React.KeyboardEvent | Event) => {
    const nativeEvent = 'nativeEvent' in event ? event.nativeEvent : event;
    
    if (isKeyboardEvent(nativeEvent)) {
      // Handle keyboard-specific logic
      if (nativeEvent.key === "ArrowUp") {
        // Move up
      } else if (nativeEvent.key === "ArrowDown") {
        // Move down
      }
    }
  };
  
  return (
    <div tabIndex={0} onKeyDown={handleKeyEvent}>
      Press arrow keys to navigate
    </div>
  );
}

isTouchEvent

Type guard that determines if an event is a TouchEvent. Uses cross-frame compatible detection.

/**
 * Type guard for TouchEvent with cross-frame compatibility
 * @param event - Event to check (can be undefined or null)
 * @returns True if event is a TouchEvent
 */
function isTouchEvent(event: Event | undefined | null): event is TouchEvent;

Usage Examples:

import { isTouchEvent } from "@dnd-kit/utilities";

function handlePointerEvent(event: Event) {
  if (isTouchEvent(event)) {
    // TypeScript knows this is a TouchEvent
    console.log(`Number of touches: ${event.touches.length}`);
    
    // Access touch-specific properties
    if (event.touches.length > 0) {
      const firstTouch = event.touches[0];
      console.log(`Touch at: ${firstTouch.clientX}, ${firstTouch.clientY}`);
    }
    
    // Handle multi-touch
    if (event.touches.length > 1) {
      console.log("Multi-touch detected");
      const touch1 = event.touches[0];
      const touch2 = event.touches[1];
      const distance = Math.sqrt(
        Math.pow(touch2.clientX - touch1.clientX, 2) +
        Math.pow(touch2.clientY - touch1.clientY, 2)
      );
      console.log(`Distance between touches: ${distance}`);
    }
  } else {
    // Likely a mouse event
    console.log("Non-touch event detected");
  }
}

// Unified event handling
function createUnifiedHandler(element: HTMLElement) {
  const handleStart = (event: Event) => {
    if (isTouchEvent(event)) {
      // Touch-specific handling
      event.preventDefault(); // Prevent scrolling
      const touch = event.touches[0];
      startDrag(touch.clientX, touch.clientY);
    } else {
      // Mouse event handling
      const mouseEvent = event as MouseEvent;
      startDrag(mouseEvent.clientX, mouseEvent.clientY);
    }
  };
  
  element.addEventListener("touchstart", handleStart);
  element.addEventListener("mousedown", handleStart);
}

function startDrag(x: number, y: number) {
  console.log(`Starting drag at: ${x}, ${y}`);
}

// React drag and drop example
import React from "react";

function TouchAwareDraggable() {
  const handleDragStart = (event: React.TouchEvent | React.MouseEvent) => {
    const nativeEvent = event.nativeEvent;
    
    if (isTouchEvent(nativeEvent)) {
      // Touch drag
      const touch = nativeEvent.touches[0];
      console.log("Touch drag started at:", touch.clientX, touch.clientY);
    } else {
      // Mouse drag
      const mouseEvent = nativeEvent as MouseEvent;
      console.log("Mouse drag started at:", mouseEvent.clientX, mouseEvent.clientY);
    }
  };
  
  return (
    <div
      onTouchStart={handleDragStart}
      onMouseDown={handleDragStart}
      style={{ touchAction: "none" }} // Prevent default touch behaviors
    >
      Touch or click to drag
    </div>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-dnd-kit--utilities

docs

coordinates.md

css-utilities.md

event-handling.md

execution-context.md

focus-management.md

hooks.md

index.md

math-operations.md

type-guards.md

typescript-utilities.md

tile.json