or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

coordinates.mdcss-utilities.mdevent-handling.mdexecution-context.mdfocus-management.mdhooks.mdindex.mdmath-operations.mdtype-guards.mdtypescript-utilities.md
tile.json

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