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.
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
}
};
}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>
);
}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");
}
}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>
);
}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>;
}