or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auto-scrolling.mdcomponent-utilities.mddrag-drop-hooks.mdeditor-transforms.mdindex.mdplugin-configuration.mdutility-functions.md

drag-drop-hooks.mddocs/

0

# Drag and Drop Hooks

1

2

React hooks for implementing drag-and-drop behavior on editor nodes. These hooks provide the core functionality for making blocks draggable and droppable, with support for visual feedback, state management, and event handling.

3

4

## Capabilities

5

6

### useDndNode

7

8

Combined hook that provides both drag and drop functionality for editor nodes. This is the main hook used for implementing drag-and-drop on blocks.

9

10

```typescript { .api }

11

/**

12

* Combined drag and drop hook for editor nodes

13

* Provides both dragging and dropping functionality with preview support

14

* @param options - Configuration options for drag and drop behavior

15

* @returns Object with drag ref, dragging state, and hover state

16

*/

17

export function useDndNode(options: UseDndNodeOptions): {

18

dragRef: ConnectDragSource;

19

isDragging: boolean;

20

isOver: boolean;

21

};

22

23

export type UseDndNodeOptions = Pick<UseDropNodeOptions, 'element'> &

24

Partial<Pick<UseDropNodeOptions, 'canDropNode' | 'nodeRef'>> &

25

Partial<Pick<UseDragNodeOptions, 'type'>> & {

26

/** Options passed to the drag hook */

27

drag?: Partial<Omit<UseDragNodeOptions, 'type'>>;

28

/** Options passed to the drop hook, excluding element, nodeRef */

29

drop?: Partial<

30

Omit<UseDropNodeOptions, 'canDropNode' | 'element' | 'nodeRef'>

31

>;

32

/** Orientation of the drag and drop interaction */

33

orientation?: 'horizontal' | 'vertical';

34

/** Preview configuration */

35

preview?: {

36

/** Whether to disable the preview */

37

disable?: boolean;

38

/** The reference to the preview element */

39

ref?: any;

40

};

41

/** Custom drop handler function */

42

onDropHandler?: (

43

editor: PlateEditor,

44

props: {

45

id: string;

46

dragItem: DragItemNode;

47

monitor: DropTargetMonitor<DragItemNode, unknown>;

48

nodeRef: any;

49

}

50

) => boolean | void;

51

};

52

```

53

54

**Usage Examples:**

55

56

```typescript

57

import { useDndNode } from "@udecode/plate-dnd";

58

import { useElement } from "@udecode/plate/react";

59

60

function DraggableBlock({ children }) {

61

const element = useElement();

62

const nodeRef = useRef<HTMLDivElement>(null);

63

64

const { dragRef, isDragging, isOver } = useDndNode({

65

element,

66

nodeRef,

67

orientation: 'vertical'

68

});

69

70

return (

71

<div

72

ref={dragRef}

73

style={{

74

opacity: isDragging ? 0.5 : 1,

75

backgroundColor: isOver ? '#f0f0f0' : 'transparent'

76

}}

77

>

78

{children}

79

</div>

80

);

81

}

82

83

// With custom drop handler

84

function CustomDraggableBlock({ children }) {

85

const element = useElement();

86

87

const { dragRef, isDragging } = useDndNode({

88

element,

89

onDropHandler: (editor, { id, dragItem }) => {

90

console.log('Custom drop handling for block:', id);

91

// Return true to prevent default drop behavior

92

return false;

93

}

94

});

95

96

return (

97

<div ref={dragRef} style={{ opacity: isDragging ? 0.5 : 1 }}>

98

{children}

99

</div>

100

);

101

}

102

```

103

104

### useDragNode

105

106

Hook specifically for making nodes draggable. Provides fine-grained control over drag behavior.

107

108

```typescript { .api }

109

/**

110

* Hook for making editor nodes draggable

111

* Manages drag state and provides drag source functionality

112

* @param editor - The Plate editor instance

113

* @param options - Drag configuration options

114

* @returns Tuple with drag state, drag ref, and preview ref

115

*/

116

export function useDragNode(

117

editor: PlateEditor,

118

options: UseDragNodeOptions

119

): [{ isDragging: boolean }, ConnectDragSource, ConnectDragPreview];

120

121

export interface UseDragNodeOptions

122

extends DragSourceHookSpec<DragItemNode, unknown, { isDragging: boolean }> {

123

/** The editor element to make draggable */

124

element: TElement;

125

}

126

```

127

128

**Usage Examples:**

129

130

```typescript

131

import { useDragNode } from "@udecode/plate-dnd";

132

import { useEditorRef, useElement } from "@udecode/plate/react";

133

134

function CustomDraggable({ children }) {

135

const editor = useEditorRef();

136

const element = useElement();

137

138

const [{ isDragging }, dragRef, preview] = useDragNode(editor, {

139

element,

140

type: 'custom-block',

141

item: { customData: 'example' }

142

});

143

144

// Custom preview setup

145

useEffect(() => {

146

const img = new Image();

147

img.src = 'data:image/png;base64,iV...'; // Custom drag image

148

preview(img);

149

}, [preview]);

150

151

return (

152

<div ref={dragRef} style={{ opacity: isDragging ? 0.3 : 1 }}>

153

{children}

154

</div>

155

);

156

}

157

```

158

159

### useDropNode

160

161

Hook specifically for making nodes accept drops. Provides drop zone functionality with hover detection.

162

163

```typescript { .api }

164

/**

165

* Hook for making editor nodes accept drops

166

* Manages drop state and handles drop operations

167

* @param editor - The Plate editor instance

168

* @param options - Drop configuration options

169

* @returns Tuple with drop state and drop target ref

170

*/

171

export function useDropNode(

172

editor: PlateEditor,

173

options: UseDropNodeOptions

174

): [{ isOver: boolean }, ConnectDropTarget];

175

176

export interface UseDropNodeOptions

177

extends DropTargetHookSpec<DragItemNode, unknown, { isOver: boolean }> {

178

/** The node to which the drop line is attached */

179

element: TElement;

180

/** The reference to the node being dragged */

181

nodeRef: any;

182

/** Intercepts the drop handling */

183

canDropNode?: CanDropCallback;

184

/** Orientation of drop operations */

185

orientation?: 'horizontal' | 'vertical';

186

/** Custom drop handler function */

187

onDropHandler?: (

188

editor: PlateEditor,

189

props: {

190

id: string;

191

dragItem: DragItemNode;

192

monitor: DropTargetMonitor<DragItemNode, unknown>;

193

nodeRef: any;

194

}

195

) => boolean | void;

196

}

197

198

export type CanDropCallback = (args: {

199

dragEntry: NodeEntry<TElement>;

200

dragItem: DragItemNode;

201

dropEntry: NodeEntry<TElement>;

202

editor: PlateEditor;

203

}) => boolean;

204

```

205

206

**Usage Examples:**

207

208

```typescript

209

import { useDropNode } from "@udecode/plate-dnd";

210

import { useEditorRef, useElement } from "@udecode/plate/react";

211

212

function DropZone({ children }) {

213

const editor = useEditorRef();

214

const element = useElement();

215

const nodeRef = useRef<HTMLDivElement>(null);

216

217

const [{ isOver }, dropRef] = useDropNode(editor, {

218

accept: ['block', 'custom-block'],

219

element,

220

nodeRef,

221

canDropNode: ({ dragItem, dropEntry }) => {

222

// Custom validation logic

223

return dragItem.id !== dropEntry[0].id;

224

}

225

});

226

227

// Combine refs

228

const combinedRef = useCallback((el: HTMLDivElement) => {

229

nodeRef.current = el;

230

dropRef(el);

231

}, [dropRef]);

232

233

return (

234

<div

235

ref={combinedRef}

236

style={{

237

border: isOver ? '2px dashed #007acc' : '2px solid transparent',

238

minHeight: '40px'

239

}}

240

>

241

{children}

242

</div>

243

);

244

}

245

```

246

247

## Types

248

249

```typescript { .api }

250

export type DragItemNode = ElementDragItemNode | FileDragItemNode;

251

252

export interface ElementDragItemNode {

253

id: string;

254

element: TElement;

255

[key: string]: unknown;

256

}

257

258

export interface FileDragItemNode {

259

dataTransfer: DataTransfer[];

260

files: FileList;

261

items: DataTransferItemList;

262

}

263

```