Cross-platform utilities for detecting DOM availability and accessing window/document objects safely across different JavaScript execution environments.
Boolean constant indicating whether DOM APIs are available in the current execution context. Essential for SSR compatibility and universal JavaScript applications.
/**
* Boolean constant indicating if DOM APIs are available
* Based on Facebook's React ExecutionEnvironment
*/
const canUseDOM: boolean;Usage Examples:
import { canUseDOM } from "@dnd-kit/utilities";
// Conditional DOM access
if (canUseDOM) {
// Safe to use DOM APIs
const element = document.getElementById("my-element");
const windowWidth = window.innerWidth;
console.log("Running in browser environment");
} else {
// Running in Node.js/SSR environment
console.log("Running in server environment");
}
// Feature detection
function setupBrowserFeatures() {
if (!canUseDOM) {
return; // Skip browser-only setup
}
// Set up event listeners, measurements, etc.
document.addEventListener("resize", handleResize);
setupIntersectionObserver();
}
// React SSR example
import React, { useEffect, useState } from "react";
function ClientOnlyComponent() {
const [mounted, setMounted] = useState(false);
useEffect(() => {
if (canUseDOM) {
setMounted(true);
}
}, []);
if (!mounted) {
return <div>Loading...</div>; // Server-side fallback
}
return <div>Client-side content with DOM access</div>;
}Returns the owner document for an event target, with robust handling of different target types including cross-frame scenarios.
/**
* Returns the owner document for an event target
* @param target - Event target (Window, Document, HTMLElement, SVGElement, Node, etc.)
* @returns The document that owns the target, or global document as fallback
*/
function getOwnerDocument(target: Event['target']): Document;Usage Examples:
import { getOwnerDocument } from "@dnd-kit/utilities";
// Event handling with document detection
function handleClick(event: MouseEvent) {
const doc = getOwnerDocument(event.target);
// Now you can safely use document methods
const selection = doc.getSelection();
const activeElement = doc.activeElement;
console.log("Document detected:", doc.title || "Unknown");
}
// Cross-frame compatibility
function setupCrossFrameHandler(iframe: HTMLIFrameElement) {
iframe.onload = () => {
const iframeDoc = iframe.contentDocument;
const button = iframeDoc?.getElementById("button");
if (button) {
button.addEventListener("click", (event) => {
// getOwnerDocument handles iframe documents correctly
const ownerDoc = getOwnerDocument(event.target);
console.log("Button clicked in:", ownerDoc === document ? "main frame" : "iframe");
});
}
};
}
// React drag and drop across frames
import React from "react";
function DragDropComponent() {
const handleDragStart = (event: React.DragEvent) => {
const target = event.target as HTMLElement;
const doc = getOwnerDocument(target);
// Create drag image in the correct document
const dragImage = doc.createElement("div");
dragImage.textContent = "Dragging...";
dragImage.style.position = "absolute";
dragImage.style.top = "-1000px";
doc.body.appendChild(dragImage);
event.dataTransfer.setDragImage(dragImage, 0, 0);
// Clean up after drag
setTimeout(() => doc.body.removeChild(dragImage), 0);
};
return (
<div draggable onDragStart={handleDragStart}>
Drag me across frames!
</div>
);
}Returns the window object for an event target, with robust handling of different execution contexts and cross-frame scenarios.
/**
* Returns the window object for an event target
* @param target - Event target (Window, Node, etc.)
* @returns The window object that contains the target, or global window as fallback
*/
function getWindow(target: Event['target']): typeof window;Usage Examples:
import { getWindow } from "@dnd-kit/utilities";
// Event handling with window detection
function handleMouseMove(event: MouseEvent) {
const win = getWindow(event.target);
// Use the correct window for measurements
const viewport = {
width: win.innerWidth,
height: win.innerHeight,
scrollX: win.scrollX,
scrollY: win.scrollY
};
console.log("Viewport dimensions:", viewport);
}
// Cross-frame positioning
function positionElementRelativeToTarget(element: HTMLElement, target: EventTarget | null) {
const targetWindow = getWindow(target);
const elementWindow = getWindow(element);
if (targetWindow !== elementWindow) {
console.log("Cross-frame positioning detected");
// Handle cross-frame coordinate transformation
}
// Get scroll position from correct window
const scrollX = targetWindow.scrollX;
const scrollY = targetWindow.scrollY;
// Position element accounting for scroll
element.style.left = `${100 + scrollX}px`;
element.style.top = `${100 + scrollY}px`;
}
// React portal example with correct window
import React, { useEffect, useState } from "react";
import { createPortal } from "react-dom";
function CrossFramePortal({ children, targetElement }: {
children: React.ReactNode;
targetElement: HTMLElement | null;
}) {
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);
useEffect(() => {
if (!targetElement) return;
// Get the correct window for the target
const targetWindow = getWindow(targetElement);
const targetDocument = targetWindow.document;
// Create portal container in the target document
const container = targetDocument.createElement("div");
container.className = "portal-container";
targetDocument.body.appendChild(container);
setPortalContainer(container);
return () => {
if (container.parentNode) {
container.parentNode.removeChild(container);
}
};
}, [targetElement]);
if (!portalContainer) return null;
return createPortal(children, portalContainer);
}
// Window-aware global event handling
function setupGlobalEventHandler(target: EventTarget | null) {
const targetWindow = getWindow(target);
const handleGlobalClick = (event: MouseEvent) => {
console.log("Global click in window:", targetWindow === window ? "main" : "iframe");
};
// Add listener to the correct window
targetWindow.addEventListener("click", handleGlobalClick);
return () => {
targetWindow.removeEventListener("click", handleGlobalClick);
};
}