Shared TypeScript type definitions for React Spectrum components and hooks, providing common interfaces for DOM interactions, styling, accessibility, internationalization, and component behavior across the React Spectrum ecosystem
—
DOM reference types and utilities for safe DOM node access and focus management with enhanced forwardRef support for generics.
Reference value interfaces that provide safe access to DOM nodes.
/**
* DOM ref value with safe DOM node access
* @template T The type of HTML element (defaults to HTMLElement)
*/
interface DOMRefValue<T extends HTMLElement = HTMLElement> {
/**
* Returns the DOM node or null if not available.
* Marked as UNSAFE to indicate direct DOM access should be used carefully.
*/
UNSAFE_getDOMNode(): T | null;
}
/**
* Focusable ref value with focus capabilities and DOM access
* @template T The type of HTML element for focus operations
* @template D The type of HTML element for DOM access (defaults to T)
*/
interface FocusableRefValue<T extends HTMLElement = HTMLElement, D extends HTMLElement = T>
extends DOMRefValue<D> {
/**
* Focus the element programmatically
*/
focus(): void;
}Type aliases for working with DOM and focusable references.
/**
* Ref type for DOM elements
* @template T The type of HTML element (defaults to HTMLElement)
*/
type DOMRef<T extends HTMLElement = HTMLElement> = Ref<DOMRefValue<T>>;
/**
* Ref type for focusable elements
* @template T The type of HTML element (defaults to HTMLElement)
*/
type FocusableRef<T extends HTMLElement = HTMLElement> = Ref<FocusableRefValue<T>>;
/**
* Enhanced ref object interface
* @template T The type of the ref value
*/
interface RefObject<T> {
/** The current ref value */
current: T;
}Enhanced forwardRef type declaration with proper generic support.
/**
* Enhanced forwardRef function declaration that preserves generics
* @template T The ref type
* @template P The props type
*/
declare function forwardRef<T, P = {}>(
render: (props: P, ref: Ref<T>) => ReactElement | null
): (props: P & RefAttributes<T>) => ReactElement | null;
/**
* Type alias for the enhanced forwardRef function
*/
type forwardRefType = typeof forwardRef;Usage Examples:
import {
DOMRef,
FocusableRef,
DOMRefValue,
FocusableRefValue,
forwardRefType
} from "@react-types/shared";
import { useRef, forwardRef, useImperativeHandle } from "react";
// Basic DOM ref usage
function ComponentWithDOMRef() {
const divRef = useRef<DOMRefValue<HTMLDivElement>>(null);
const handleClick = () => {
const domNode = divRef.current?.UNSAFE_getDOMNode();
if (domNode) {
console.log("DOM node:", domNode);
}
};
return <div ref={divRef} onClick={handleClick}>Click me</div>;
}
// Focusable ref usage
function ComponentWithFocusableRef() {
const buttonRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);
const focusButton = () => {
buttonRef.current?.focus();
};
return (
<>
<button ref={buttonRef}>Focusable Button</button>
<button onClick={focusButton}>Focus the button</button>
</>
);
}
// Component that accepts DOM ref
interface ComponentProps {
children: React.ReactNode;
}
const ComponentWithDOMRefProp = forwardRef<DOMRefValue<HTMLDivElement>, ComponentProps>(
({ children }, ref) => {
const divRef = useRef<HTMLDivElement>(null);
useImperativeHandle(ref, () => ({
UNSAFE_getDOMNode: () => divRef.current
}));
return <div ref={divRef}>{children}</div>;
}
);
// Component that accepts focusable ref
interface FocusableComponentProps {
children: React.ReactNode;
autoFocus?: boolean;
}
const FocusableComponent = forwardRef<FocusableRefValue<HTMLButtonElement>, FocusableComponentProps>(
({ children, autoFocus }, ref) => {
const buttonRef = useRef<HTMLButtonElement>(null);
useImperativeHandle(ref, () => ({
UNSAFE_getDOMNode: () => buttonRef.current,
focus: () => buttonRef.current?.focus()
}));
React.useEffect(() => {
if (autoFocus) {
buttonRef.current?.focus();
}
}, [autoFocus]);
return <button ref={buttonRef}>{children}</button>;
}
);
// Using the components
function App() {
const domRef = useRef<DOMRefValue<HTMLDivElement>>(null);
const focusableRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);
const handleDOMAccess = () => {
const node = domRef.current?.UNSAFE_getDOMNode();
console.log("DOM node:", node);
};
const handleFocus = () => {
focusableRef.current?.focus();
};
return (
<div>
<ComponentWithDOMRefProp ref={domRef}>
<p>Content</p>
</ComponentWithDOMRefProp>
<FocusableComponent ref={focusableRef}>
Button Text
</FocusableComponent>
<button onClick={handleDOMAccess}>Access DOM</button>
<button onClick={handleFocus}>Focus Button</button>
</div>
);
}
// Generic component with enhanced forwardRef
interface GenericComponentProps<T> {
value: T;
onChange: (value: T) => void;
}
const GenericComponent = forwardRef<HTMLInputElement, GenericComponentProps<string>>(
({ value, onChange }, ref) => {
return (
<input
ref={ref}
value={value}
onChange={(e) => onChange(e.target.value)}
/>
);
}
);Install with Tessl CLI
npx tessl i tessl/npm-react-types--shared