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

type-guards.mddocs/

Type Guards

Type-safe functions for determining DOM element types with cross-frame compatibility. Essential for building robust drag and drop interfaces that work across different execution contexts.

Capabilities

isDocument

Type guard that checks if a node is a Document. Uses cross-frame compatible detection to work with iframes and popup windows.

/**
 * Type guard for Document nodes with cross-frame compatibility
 * @param node - Node to check
 * @returns True if node is a Document
 */
function isDocument(node: Node): node is Document;

Usage Examples:

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

function handleNodeOperation(node: Node) {
  if (isDocument(node)) {
    // TypeScript knows this is a Document
    console.log("Document title:", node.title);
    console.log("Active element:", node.activeElement?.tagName);
    
    // Safe to use document-specific methods
    const selection = node.getSelection();
    const elementById = node.getElementById("my-element");
  }
}

// Cross-frame document detection
function setupCrossFrameHandler(iframe: HTMLIFrameElement) {
  iframe.onload = () => {
    const iframeDocument = iframe.contentDocument;
    if (iframeDocument && isDocument(iframeDocument)) {
      console.log("iframe document detected");
      // Handle iframe document safely
    }
  };
}

isHTMLElement

Type guard that checks if a node is an HTMLElement, excluding Window objects. Uses cross-frame compatible detection.

/**
 * Type guard for HTMLElement nodes with cross-frame compatibility
 * @param node - Node or Window to check
 * @returns True if node is an HTMLElement (excludes Window objects)
 */
function isHTMLElement(node: Node | Window): node is HTMLElement;

Usage Examples:

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

function handleDragTarget(target: EventTarget | null) {
  if (isHTMLElement(target)) {
    // TypeScript knows this is an HTMLElement
    console.log("Element tag:", target.tagName);
    console.log("Element ID:", target.id);
    
    // Safe to use HTMLElement properties and methods
    target.style.backgroundColor = "red";
    target.setAttribute("draggable", "true");
    
    const rect = target.getBoundingClientRect();
    console.log("Element bounds:", rect);
  }
}

// Event delegation with type safety
function setupEventDelegation(container: HTMLElement) {
  container.addEventListener("click", (event) => {
    const target = event.target;
    
    if (isHTMLElement(target)) {
      // Handle different element types
      if (target.tagName === "BUTTON") {
        console.log("Button clicked:", target.textContent);
      } else if (target.tagName === "A") {
        console.log("Link clicked:", target.href);
      }
      
      // Add visual feedback
      target.classList.add("clicked");
      setTimeout(() => target.classList.remove("clicked"), 200);
    }
  });
}

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

function DragDropComponent() {
  const handleDragStart = (event: React.DragEvent) => {
    const target = event.target;
    
    if (isHTMLElement(target)) {
      // Set up drag data
      event.dataTransfer.setData("text/plain", target.id);
      event.dataTransfer.effectAllowed = "move";
      
      // Add drag styling
      target.style.opacity = "0.5";
    }
  };
  
  const handleDragEnd = (event: React.DragEvent) => {
    const target = event.target;
    
    if (isHTMLElement(target)) {
      // Reset styling
      target.style.opacity = "";
    }
  };
  
  return (
    <div
      draggable
      onDragStart={handleDragStart}
      onDragEnd={handleDragEnd}
    >
      Drag me!
    </div>
  );
}

isNode

Type guard that checks if an object is a DOM Node. Uses simple property detection.

/**
 * Type guard for DOM Node objects
 * @param node - Object to check
 * @returns True if object is a DOM Node
 */
function isNode(node: Object): node is Node;

Usage Examples:

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

function processUnknownObject(obj: unknown) {
  if (isNode(obj)) {
    // TypeScript knows this is a Node
    console.log("Node type:", obj.nodeType);
    console.log("Node name:", obj.nodeName);
    
    // Safe to use Node properties
    if (obj.parentNode) {
      console.log("Has parent:", obj.parentNode.nodeName);
    }
    
    // Check for specific node types
    if (obj.nodeType === Node.ELEMENT_NODE) {
      console.log("This is an element node");
    } else if (obj.nodeType === Node.TEXT_NODE) {
      console.log("This is a text node:", obj.textContent);
    }
  }
}

// Safe node manipulation
function safelyAppendChild(parent: unknown, child: unknown) {
  if (isNode(parent) && isNode(child)) {
    try {
      parent.appendChild(child);
      console.log("Child appended successfully");
    } catch (error) {
      console.error("Failed to append child:", error);
    }
  } else {
    console.error("Invalid parent or child node");
  }
}

isSVGElement

Type guard that checks if a node is an SVGElement. Uses cross-frame compatible detection.

/**
 * Type guard for SVGElement nodes with cross-frame compatibility
 * @param node - Node to check
 * @returns True if node is an SVGElement
 */
function isSVGElement(node: Node): node is SVGElement;

Usage Examples:

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

function handleSVGInteraction(target: EventTarget | null) {
  if (isSVGElement(target)) {
    // TypeScript knows this is an SVGElement
    console.log("SVG element:", target.tagName);
    
    // Safe to use SVG-specific properties
    if (target.ownerSVGElement) {
      console.log("Part of SVG:", target.ownerSVGElement.tagName);
    }
    
    // SVG-specific styling
    target.style.fill = "red";
    target.style.stroke = "blue";
    
    // Get SVG-specific measurements
    if ('getBBox' in target) {
      const bbox = target.getBBox();
      console.log("SVG bounding box:", bbox);
    }
  }
}

// SVG drag and drop handling
function setupSVGDragDrop(svgContainer: SVGSVGElement) {
  svgContainer.addEventListener("mousedown", (event) => {
    const target = event.target;
    
    if (isSVGElement(target)) {
      // Handle SVG element dragging
      const startX = event.clientX;
      const startY = event.clientY;
      
      // Get current transform
      const transform = target.getAttribute("transform") || "";
      console.log("Starting SVG drag on:", target.tagName);
      
      const handleMouseMove = (moveEvent: MouseEvent) => {
        const deltaX = moveEvent.clientX - startX;
        const deltaY = moveEvent.clientY - startY;
        
        // Apply SVG transform
        target.setAttribute("transform", `translate(${deltaX}, ${deltaY})`);
      };
      
      const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
      };
      
      document.addEventListener("mousemove", handleMouseMove);
      document.addEventListener("mouseup", handleMouseUp);
    }
  });
}

// React SVG component example
import React from "react";

function InteractiveSVG() {
  const handleSVGClick = (event: React.MouseEvent<SVGSVGElement>) => {
    const target = event.target;
    
    if (isSVGElement(target)) {
      // Animate SVG element
      target.style.transition = "fill 0.3s ease";
      target.style.fill = target.style.fill === "red" ? "blue" : "red";
    }
  };
  
  return (
    <svg width="200" height="200" onClick={handleSVGClick}>
      <circle cx="50" cy="50" r="20" fill="blue" />
      <rect x="100" y="30" width="40" height="40" fill="green" />
      <path d="M 150 50 L 170 80 L 130 80 Z" fill="orange" />
    </svg>
  );
}

isWindow

Type guard that checks if an object is a Window. Handles both standard browser windows and Electron's global context.

/**
 * Type guard for Window objects
 * Handles both [object Window] and [object global] (Electron) contexts
 * @param element - Object to check
 * @returns True if object is a Window
 */
function isWindow(element: Object): element is typeof window;

Usage Examples:

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

function handleWindowOrElement(target: EventTarget | null) {
  if (isWindow(target)) {
    // TypeScript knows this is a Window
    console.log("Window dimensions:", target.innerWidth, target.innerHeight);
    console.log("Window location:", target.location.href);
    
    // Safe to use window-specific properties
    target.scrollTo(0, 0);
    const viewport = {
      width: target.innerWidth,
      height: target.innerHeight,
      scrollX: target.scrollX,
      scrollY: target.scrollY
    };
    
    console.log("Viewport info:", viewport);
  }
}

// Cross-frame window detection
function setupCrossFrameWindowHandler() {
  const iframe = document.createElement("iframe");
  iframe.src = "about:blank";
  document.body.appendChild(iframe);
  
  iframe.onload = () => {
    const iframeWindow = iframe.contentWindow;
    
    if (isWindow(iframeWindow)) {
      console.log("iframe window detected");
      console.log("iframe dimensions:", iframeWindow.innerWidth, iframeWindow.innerHeight);
      
      // Set up cross-frame communication
      iframeWindow.postMessage("Hello from parent", "*");
    }
  };
}

// Electron compatibility
function handleElectronWindow(globalContext: any) {
  if (isWindow(globalContext)) {
    // Works in both browser and Electron
    console.log("Running in window context");
    
    // Electron-specific features (if available)
    if ('require' in globalContext) {
      console.log("Electron environment detected");
    }
  }
}

// Event target resolution
function resolveEventContext(event: Event) {
  const target = event.target;
  const currentTarget = event.currentTarget;
  
  if (isWindow(target)) {
    console.log("Event originated from window");
    // Handle window-level events (resize, scroll, etc.)
  } else if (isWindow(currentTarget)) {
    console.log("Event bubbled to window");
    // Handle events that bubbled to window
  }
}

// React window event handler
import React, { useEffect } from "react";

function WindowAwareComponent() {
  useEffect(() => {
    const handleGlobalEvent = (event: Event) => {
      const target = event.target;
      
      if (isWindow(target)) {
        // Handle window-specific events
        console.log("Window event:", event.type);
        
        if (event.type === "resize") {
          console.log("Window resized to:", target.innerWidth, target.innerHeight);
        } else if (event.type === "scroll") {
          console.log("Window scrolled to:", target.scrollX, target.scrollY);
        }
      }
    };
    
    // Add listeners to window if available
    if (typeof window !== "undefined" && isWindow(window)) {
      window.addEventListener("resize", handleGlobalEvent);
      window.addEventListener("scroll", handleGlobalEvent);
      
      return () => {
        window.removeEventListener("resize", handleGlobalEvent);
        window.removeEventListener("scroll", handleGlobalEvent);
      };
    }
  }, []);
  
  return <div>Window-aware component</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