Context Types
Complete type definitions for context and provider components.
Type Aliases
DropAlignment
Alignment options for positioning dropped items within a droppable area.
type DropAlignment =
| "center"
| "top-left" | "top-center" | "top-right"
| "center-left" | "center-right"
| "bottom-left" | "bottom-center" | "bottom-right";
Values
center
: Center the dropped item (default)top-left
: Position at top-left cornertop-center
: Position at top edge, centered horizontallytop-right
: Position at top-right cornercenter-left
: Position at left edge, centered verticallycenter-right
: Position at right edge, centered verticallybottom-left
: Position at bottom-left cornerbottom-center
: Position at bottom edge, centered horizontallybottom-right
: Position at bottom-right corner
Usage Examples
// Center the dropped item (default)
const centerAlignment: DropAlignment = 'center';
// Position at top-left corner
const topLeftAlignment: DropAlignment = 'top-left';
// Position at bottom edge, centered horizontally
const bottomCenterAlignment: DropAlignment = 'bottom-center';
PositionUpdateListener
Callback function type for position update notifications.
type PositionUpdateListener = () => void;
Description
Function called when position updates are triggered. Used internally by components to recalculate positions after layout changes.
Interfaces
DropOffset
Pixel offset to apply after alignment positioning.
interface DropOffset {
x: number;
y: number;
}
Properties
x
- Type:
number
- Description: Horizontal offset in pixels (positive = right, negative = left)
y
- Type:
number
- Description: Vertical offset in pixels (positive = down, negative = up)
Usage Examples
// No offset (default)
const noOffset: DropOffset = { x: 0, y: 0 };
// Move 10px right and 5px down from aligned position
const customOffset: DropOffset = { x: 10, y: 5 };
// Move 20px left from aligned position
const leftOffset: DropOffset = { x: -20, y: 0 };
DroppedItemsMap<TData>
Mapping of draggable items to their drop locations.
interface DroppedItemsMap<TData = unknown> {
[draggableId: string]: {
droppableId: string;
data: TData;
};
}
Properties
- Key:
string
- The unique ID of the draggable item - Value: Object containing:
droppableId
: ID of the droppable where the item was droppeddata
: The data associated with the dropped item
Usage Example
const droppedItems: DroppedItemsMap<TaskData> = {
'task-1': {
droppableId: 'completed-column',
data: { id: 'task-1', title: 'Complete project', status: 'done' }
},
'task-2': {
droppableId: 'in-progress-column',
data: { id: 'task-2', title: 'Review code', status: 'in-progress' }
}
};
DropSlot<TData>
Configuration for a single drop zone.
interface DropSlot<TData = unknown> {
id: string;
x: number;
y: number;
width: number;
height: number;
onDrop: (data: TData) => void;
dropAlignment?: DropAlignment;
dropOffset?: DropOffset;
capacity?: number;
}
Properties
id
- Type:
string
- Required: Yes
- Description: Unique identifier for the drop slot
x
- Type:
number
- Required: Yes
- Description: X coordinate of the drop slot
y
- Type:
number
- Required: Yes
- Description: Y coordinate of the drop slot
width
- Type:
number
- Required: Yes
- Description: Width of the drop slot
height
- Type:
number
- Required: Yes
- Description: Height of the drop slot
onDrop
- Type:
(data: TData) => void
- Required: Yes
- Description: Callback function called when an item is dropped
dropAlignment
- Type:
DropAlignment
- Required: No
- Description: How dropped items should be aligned within this slot
dropOffset
- Type:
DropOffset
- Required: No
- Description: Additional pixel offset to apply after alignment
capacity
- Type:
number
- Required: No
- Description: Maximum number of items this slot can hold
SlotsContextValue<TData>
The main context value interface providing drag-and-drop functionality.
interface SlotsContextValue<TData = unknown> {
// Drop zone management
register: (id: number, slot: DropSlot<TData>) => void;
unregister: (id: number) => void;
getSlots: () => Record<number, DropSlot<TData>>;
isRegistered: (id: number) => boolean;
// Active state management
setActiveHoverSlot: (id: number | null) => void;
activeHoverSlotId: number | null;
// Position updates
registerPositionUpdateListener: (id: string, listener: PositionUpdateListener) => void;
unregisterPositionUpdateListener: (id: string) => void;
requestPositionUpdate: () => void;
// Dropped items management
registerDroppedItem: (draggableId: string, droppableId: string, itemData: any) => void;
unregisterDroppedItem: (draggableId: string) => void;
getDroppedItems: () => DroppedItemsMap<any>;
// Capacity management
hasAvailableCapacity: (droppableId: string) => boolean;
// Event callbacks
onDragging?: (payload: DraggingPayload) => void;
onDragStart?: (data: any) => void;
onDragEnd?: (data: any) => void;
}
Drop Zone Management Methods
register(id, slot)
- Type:
(id: number, slot: DropSlot<TData>) => void
- Description: Registers a new drop zone with the context
- Parameters:
id
: Unique numeric identifier for the drop zoneslot
: Drop zone configuration object
unregister(id)
- Type:
(id: number) => void
- Description: Removes a drop zone from the context
- Parameters:
id
: Unique identifier of the drop zone to remove
getSlots()
- Type:
() => Record<number, DropSlot<TData>>
- Description: Returns all currently registered drop zones
- Returns: Object mapping slot IDs to their configurations
isRegistered(id)
- Type:
(id: number) => boolean
- Description: Checks if a drop zone is currently registered
- Parameters:
id
: Drop zone ID to check
- Returns: True if the drop zone is registered
Active State Management
setActiveHoverSlot(id)
- Type:
(id: number | null) => void
- Description: Sets the currently active (hovered) drop zone
- Parameters:
id
: ID of the active drop zone, or null for none
activeHoverSlotId
- Type:
number | null
- Description: The ID of the currently active drop zone
Position Update Methods
registerPositionUpdateListener(id, listener)
- Type:
(id: string, listener: PositionUpdateListener) => void
- Description: Registers a listener for position updates
- Parameters:
id
: Unique identifier for the listenerlistener
: Callback function to invoke on updates
unregisterPositionUpdateListener(id)
- Type:
(id: string) => void
- Description: Removes a position update listener
- Parameters:
id
: Unique identifier of the listener to remove
requestPositionUpdate()
- Type:
() => void
- Description: Triggers position updates for all registered listeners
Dropped Items Management
registerDroppedItem(draggableId, droppableId, itemData)
- Type:
(draggableId: string, droppableId: string, itemData: any) => void
- Description: Records that an item has been dropped in a specific zone
- Parameters:
draggableId
: ID of the draggable itemdroppableId
: ID of the drop zoneitemData
: Data associated with the dropped item
unregisterDroppedItem(draggableId)
- Type:
(draggableId: string) => void
- Description: Removes a dropped item from the registry
- Parameters:
draggableId
: ID of the draggable item to remove
getDroppedItems()
- Type:
() => DroppedItemsMap<any>
- Description: Returns the current mapping of dropped items
Capacity Management
hasAvailableCapacity(droppableId)
- Type:
(droppableId: string) => boolean
- Description: Checks if a drop zone has available capacity
- Parameters:
droppableId
: ID of the drop zone to check
- Returns: True if the drop zone can accept more items
Event Callbacks
onDragging
- Type:
(payload: DraggingPayload) => void
- Required: No
- Description: Global callback fired during drag operations
onDragStart
- Type:
(data: any) => void
- Required: No
- Description: Global callback fired when any drag operation starts
onDragEnd
- Type:
(data: any) => void
- Required: No
- Description: Global callback fired when any drag operation ends
DropProviderProps
Props for the DropProvider component.
interface DropProviderProps {
children: ReactNode;
onLayoutUpdateComplete?: () => void;
onDroppedItemsUpdate?: (droppedItems: DroppedItemsMap) => void;
onDragging?: (payload: DraggingPayload) => void;
onDragStart?: (data: any) => void;
onDragEnd?: (data: any) => void;
}
Properties
children
- Type:
ReactNode
- Required: Yes
- Description: The child components that will have access to the drag-and-drop context
onLayoutUpdateComplete
- Type:
() => void
- Required: No
- Description: Callback fired when layout updates are complete. Useful for triggering additional UI updates after position recalculations.
onDroppedItemsUpdate
- Type:
(droppedItems: DroppedItemsMap) => void
- Required: No
- Description: Callback fired when the dropped items mapping changes. Provides access to the current state of which items are dropped where.
onDragging
- Type:
(payload: DraggingPayload) => void
- Required: No
- Description: Global callback fired during drag operations. Receives position updates for all draggable items.
onDragStart
- Type:
(data: any) => void
- Required: No
- Description: Global callback fired when any drag operation starts.
onDragEnd
- Type:
(data: any) => void
- Required: No
- Description: Global callback fired when any drag operation ends.
DropProviderRef
Imperative handle interface for the DropProvider component.
interface DropProviderRef {
requestPositionUpdate: () => void;
getDroppedItems: () => DroppedItemsMap;
}
Methods
requestPositionUpdate()
- Type:
() => void
- Description: Manually trigger a position update for all registered droppables and draggables. Useful after layout changes or when positions may have become stale.
getDroppedItems()
- Type:
() => DroppedItemsMap
- Description: Get the current mapping of dropped items.
- Returns: Object mapping draggable IDs to their drop information
DraggingPayload
Payload object for drag event callbacks.
interface DraggingPayload {
x: number; // Original X position
y: number; // Original Y position
tx: number; // Current X translation
ty: number; // Current Y translation
itemData: any; // Data associated with the draggable item
}
Properties
x
: Original X position of the itemy
: Original Y position of the itemtx
: Current X translation from original positionty
: Current Y translation from original positionitemData
: The data associated with the draggable item
Usage Examples
Basic Context Usage
import { useContext } from 'react';
import { SlotsContext } from 'react-native-reanimated-dnd';
function MyComponent() {
const context = useContext(SlotsContext);
if (!context) {
throw new Error('Component must be used within a DropProvider');
}
const { getSlots, getDroppedItems, activeHoverSlotId } = context;
return (
<View>
<Text>Active Slots: {Object.keys(getSlots()).length}</Text>
<Text>Dropped Items: {Object.keys(getDroppedItems()).length}</Text>
<Text>Active Hover: {activeHoverSlotId || 'None'}</Text>
</View>
);
}
Custom Hook for Context Access
import { useContext } from 'react';
import { SlotsContext, SlotsContextValue } from 'react-native-reanimated-dnd';
function useDragDropContext<TData = unknown>(): SlotsContextValue<TData> {
const context = useContext(SlotsContext);
if (!context) {
throw new Error('useDragDropContext must be used within a DropProvider');
}
return context as SlotsContextValue<TData>;
}
// Usage
function TaskBoard() {
const { getDroppedItems, hasAvailableCapacity } = useDragDropContext<TaskData>();
const droppedItems = getDroppedItems();
const canDrop = hasAvailableCapacity('todo-column');
return (
<View>
<Text>Tasks: {Object.keys(droppedItems).length}</Text>
<Text>Can Drop: {canDrop ? 'Yes' : 'No'}</Text>
</View>
);
}
Provider with All Callbacks
import { DropProvider, DroppedItemsMap, DraggingPayload } from 'react-native-reanimated-dnd';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
function App() {
const handleDroppedItemsUpdate = (droppedItems: DroppedItemsMap<TaskData>) => {
console.log('Dropped items updated:', droppedItems);
// Sync with your state management
updateGlobalState(droppedItems);
};
const handleDragStart = (data: TaskData) => {
console.log('Drag started:', data.title);
hapticFeedback();
setDragIndicator(true);
};
const handleDragEnd = (data: TaskData) => {
console.log('Drag ended:', data.title);
setDragIndicator(false);
};
const handleDragging = ({ x, y, tx, ty, itemData }: DraggingPayload) => {
const currentX = x + tx;
const currentY = y + ty;
updateDragPosition(currentX, currentY, itemData);
};
return (
<GestureHandlerRootView style={styles.container}>
<DropProvider
onDroppedItemsUpdate={handleDroppedItemsUpdate}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragging={handleDragging}
onLayoutUpdateComplete={() => console.log('Layout updated')}
>
<TaskBoard />
</DropProvider>
</GestureHandlerRootView>
);
}
Advanced Context Integration
function AdvancedContextConsumer() {
const context = useDragDropContext<TaskData>();
const [analytics, setAnalytics] = useState({
totalSlots: 0,
activeSlots: 0,
droppedItems: 0,
capacityUtilization: 0
});
useEffect(() => {
const updateAnalytics = () => {
const slots = context.getSlots();
const droppedItems = context.getDroppedItems();
const totalSlots = Object.keys(slots).length;
const activeSlots = context.activeHoverSlotId ? 1 : 0;
const totalDroppedItems = Object.keys(droppedItems).length;
// Calculate capacity utilization
const totalCapacity = Object.values(slots).reduce(
(sum, slot) => sum + (slot.capacity || 1), 0
);
const capacityUtilization = totalCapacity > 0
? (totalDroppedItems / totalCapacity) * 100
: 0;
setAnalytics({
totalSlots,
activeSlots,
droppedItems: totalDroppedItems,
capacityUtilization
});
};
const interval = setInterval(updateAnalytics, 1000);
return () => clearInterval(interval);
}, [context]);
return (
<View style={styles.analytics}>
<Text>Total Drop Zones: {analytics.totalSlots}</Text>
<Text>Active Zones: {analytics.activeSlots}</Text>
<Text>Dropped Items: {analytics.droppedItems}</Text>
<Text>Capacity Usage: {analytics.capacityUtilization.toFixed(1)}%</Text>
</View>
);
}
Custom Drop Slot Registration
function CustomDroppable({ onDrop, children }: { onDrop: (data: TaskData) => void; children: ReactNode }) {
const context = useDragDropContext<TaskData>();
const viewRef = useRef<View>(null);
const slotId = useRef(Math.random());
useEffect(() => {
const measureAndRegister = () => {
viewRef.current?.measure((x, y, width, height, pageX, pageY) => {
const slot: DropSlot<TaskData> = {
id: 'custom-droppable',
x: pageX,
y: pageY,
width,
height,
onDrop,
dropAlignment: 'center',
dropOffset: { x: 0, y: 0 },
capacity: 5
};
context.register(slotId.current, slot);
});
};
measureAndRegister();
return () => context.unregister(slotId.current);
}, [context, onDrop]);
return (
<View ref={viewRef} onLayout={measureAndRegister}>
{children}
</View>
);
}
Position Update Listener
function ResponsiveComponent() {
const { registerPositionUpdateListener, unregisterPositionUpdateListener } = useDragDropContext();
const listenerId = useRef(`listener-${Math.random()}`);
useEffect(() => {
const handlePositionUpdate = () => {
// Re-measure and update positions
console.log('Position update triggered');
remeasureComponent();
};
registerPositionUpdateListener(listenerId.current, handlePositionUpdate);
return () => {
unregisterPositionUpdateListener(listenerId.current);
};
}, [registerPositionUpdateListener, unregisterPositionUpdateListener]);
return <View>{/* Your component */}</View>;
}
Capacity Management
function CapacityManager() {
const { hasAvailableCapacity, getDroppedItems } = useDragDropContext();
const [capacityStatus, setCapacityStatus] = useState<Record<string, boolean>>({});
const dropZones = ['todo', 'in-progress', 'done'];
useEffect(() => {
const checkCapacities = () => {
const status: Record<string, boolean> = {};
dropZones.forEach(zoneId => {
status[zoneId] = hasAvailableCapacity(zoneId);
});
setCapacityStatus(status);
};
checkCapacities();
const interval = setInterval(checkCapacities, 1000);
return () => clearInterval(interval);
}, [hasAvailableCapacity]);
return (
<View>
{dropZones.map(zoneId => (
<View key={zoneId} style={styles.capacityIndicator}>
<Text>{zoneId}</Text>
<Text style={[
styles.status,
capacityStatus[zoneId] ? styles.available : styles.full
]}>
{capacityStatus[zoneId] ? 'Available' : 'Full'}
</Text>
</View>
))}
</View>
);
}
TypeScript Support
All context types are fully typed with generic support:
interface TaskData {
id: string;
title: string;
priority: 'low' | 'medium' | 'high';
}
// Typed context usage
const context = useContext(SlotsContext) as SlotsContextValue<TaskData>;
// Typed dropped items
const droppedItems: DroppedItemsMap<TaskData> = context.getDroppedItems();
// Typed drop slot
const slot: DropSlot<TaskData> = {
id: 'task-column',
x: 0,
y: 0,
width: 200,
height: 400,
onDrop: (data: TaskData) => {
// data is properly typed as TaskData
console.log(`Dropped task: ${data.title}`);
},
capacity: 10
};
See Also
- DropProvider Component - Provider component documentation
- DragDropContext - Context usage guide
- Draggable Types - Related draggable types
- Droppable Types - Related droppable types