0
# Editor Transforms
1
2
Functions for manipulating editor state during drag-and-drop operations. These transforms handle block selection, movement, focus management, and the core logic for processing drop operations within the Plate editor.
3
4
## Capabilities
5
6
### Block Selection Functions
7
8
Functions for selecting and focusing specific blocks within the editor during drag-and-drop operations.
9
10
### selectBlocksBySelectionOrId
11
12
Intelligently selects blocks based on current selection or by specific ID, providing contextual selection behavior.
13
14
```typescript { .api }
15
/**
16
* Select blocks by selection or by id
17
* If the block with id is not selected, select the block with id
18
* Else, select the blocks above the selection
19
* @param editor - The Plate editor instance
20
* @param id - The ID of the block to select
21
*/
22
export function selectBlocksBySelectionOrId(
23
editor: PlateEditor,
24
id: string
25
): void;
26
```
27
28
**Usage Examples:**
29
30
```typescript
31
import { selectBlocksBySelectionOrId } from "@udecode/plate-dnd";
32
33
// In a drag operation handler
34
function handleDragStart(editor: PlateEditor, blockId: string) {
35
// Select the dragged block or maintain current selection
36
selectBlocksBySelectionOrId(editor, blockId);
37
}
38
39
// In a drop handler
40
function handleBlockDrop(editor: PlateEditor, droppedBlockId: string) {
41
// Ensure proper selection after drop
42
selectBlocksBySelectionOrId(editor, droppedBlockId);
43
}
44
```
45
46
### selectBlockById
47
48
Selects a specific block by its ID and focuses the editor.
49
50
```typescript { .api }
51
/**
52
* Select the block above the selection by id and focus the editor
53
* @param editor - The editor instance
54
* @param id - The ID of the block to select
55
*/
56
export function selectBlockById(editor: Editor, id: string): void;
57
```
58
59
**Usage Examples:**
60
61
```typescript
62
import { selectBlockById } from "@udecode/plate-dnd";
63
64
// Select a specific block
65
function selectSpecificBlock(editor: Editor, blockId: string) {
66
selectBlockById(editor, blockId);
67
}
68
69
// In a component that needs to highlight a block
70
function HighlightableBlock({ blockId, children }) {
71
const editor = useEditorRef();
72
73
const handleClick = () => {
74
selectBlockById(editor, blockId);
75
};
76
77
return (
78
<div onClick={handleClick}>
79
{children}
80
</div>
81
);
82
}
83
```
84
85
### focusBlockStartById
86
87
Focuses the start of a specific block by its ID.
88
89
```typescript { .api }
90
/**
91
* Select the start of a block by id and focus the editor
92
* @param editor - The editor instance
93
* @param id - The ID of the block to focus
94
*/
95
export function focusBlockStartById(editor: Editor, id: string): void;
96
```
97
98
**Usage Examples:**
99
100
```typescript
101
import { focusBlockStartById } from "@udecode/plate-dnd";
102
103
// Focus at the beginning of a block after operation
104
function focusBlock(editor: Editor, blockId: string) {
105
focusBlockStartById(editor, blockId);
106
}
107
108
// In a navigation function
109
function navigateToBlock(editor: Editor, targetBlockId: string) {
110
focusBlockStartById(editor, targetBlockId);
111
}
112
```
113
114
### Block Removal Functions
115
116
Functions for removing blocks while maintaining proper editor focus and state.
117
118
### removeBlocksAndFocus
119
120
Removes blocks with specific IDs and maintains editor focus.
121
122
```typescript { .api }
123
/**
124
* Remove blocks with an id and focus the editor
125
* @param editor - The editor instance
126
* @param options - Options for finding blocks to remove
127
*/
128
export function removeBlocksAndFocus<E extends Editor = Editor>(
129
editor: E,
130
options: EditorNodesOptions<ValueOf<E>>
131
): void;
132
```
133
134
**Usage Examples:**
135
136
```typescript
137
import { removeBlocksAndFocus } from "@udecode/plate-dnd";
138
139
// Remove selected blocks
140
function removeSelectedBlocks(editor: Editor) {
141
if (!editor.selection) return;
142
143
removeBlocksAndFocus(editor, {
144
at: editor.selection
145
});
146
}
147
148
// Remove blocks of a specific type
149
function removeBlocksByType(editor: Editor, blockType: string) {
150
removeBlocksAndFocus(editor, {
151
match: n => n.type === blockType
152
});
153
}
154
155
// In a delete handler
156
function handleDeleteBlocks(editor: Editor, blockIds: string[]) {
157
removeBlocksAndFocus(editor, {
158
match: n => blockIds.includes(n.id as string)
159
});
160
}
161
```
162
163
### Drop Operation Functions
164
165
Core functions that handle the drag-and-drop logic, including path calculation and node movement.
166
167
### onDropNode
168
169
Handles the actual drop operation when a dragged node is dropped onto a target.
170
171
```typescript { .api }
172
/**
173
* Handles drop operations for dragged nodes
174
* Calculates drop paths and moves nodes to new positions
175
* @param editor - The Plate editor instance
176
* @param options - Drop operation configuration
177
*/
178
export function onDropNode(
179
editor: PlateEditor,
180
options: OnDropNodeOptions
181
): void;
182
183
export interface OnDropNodeOptions {
184
/** Function to validate if drop is allowed */
185
canDropNode?: CanDropCallback;
186
/** The dragged item data */
187
dragItem: ElementDragItemNode;
188
/** The target element */
189
element: TElement;
190
/** React DnD monitor for drop state */
191
monitor: DropTargetMonitor<DragItemNode, unknown>;
192
/** Reference to the DOM node */
193
nodeRef: any;
194
/** Orientation of the drop operation */
195
orientation?: 'horizontal' | 'vertical';
196
}
197
```
198
199
**Usage Examples:**
200
201
```typescript
202
import { onDropNode } from "@udecode/plate-dnd";
203
204
// In a custom drop handler
205
function customDropHandler(
206
editor: PlateEditor,
207
dragItem: ElementDragItemNode,
208
targetElement: TElement,
209
monitor: DropTargetMonitor,
210
nodeRef: React.RefObject<HTMLElement>
211
) {
212
onDropNode(editor, {
213
dragItem,
214
element: targetElement,
215
monitor,
216
nodeRef,
217
orientation: 'vertical',
218
canDropNode: ({ dragEntry, dropEntry }) => {
219
// Custom validation: prevent dropping on itself
220
return dragEntry[0].id !== dropEntry[0].id;
221
}
222
});
223
}
224
225
// With custom validation
226
function restrictedDropHandler(editor: PlateEditor, options: OnDropNodeOptions) {
227
const restrictedTypes = ['heading', 'code-block'];
228
229
onDropNode(editor, {
230
...options,
231
canDropNode: ({ dragEntry, dropEntry }) => {
232
// Prevent moving restricted types
233
return !restrictedTypes.includes(dragEntry[0].type as string);
234
}
235
});
236
}
237
```
238
239
### getDropPath
240
241
Calculates the appropriate drop path for a drag operation, determining where the dragged item should be placed.
242
243
```typescript { .api }
244
/**
245
* Calculates drop paths for drag operations
246
* Determines source and target paths for node movement
247
* @param editor - The Plate editor instance
248
* @param options - Path calculation options
249
* @returns Drop operation result with paths or null if invalid
250
*/
251
export function getDropPath(
252
editor: PlateEditor,
253
options: GetDropPathOptions
254
): DropPathResult | null;
255
256
export interface GetDropPathOptions {
257
canDropNode?: CanDropCallback;
258
dragItem: DragItemNode;
259
element: TElement;
260
monitor: DropTargetMonitor<DragItemNode, unknown>;
261
nodeRef: any;
262
orientation?: 'horizontal' | 'vertical';
263
}
264
265
export interface DropPathResult {
266
/** Source path of the dragged item */
267
from: Path;
268
/** Target path for the drop */
269
to: Path;
270
}
271
```
272
273
**Usage Examples:**
274
275
```typescript
276
import { getDropPath } from "@udecode/plate-dnd";
277
278
// Calculate drop path before performing operation
279
function calculateAndExecuteDrop(
280
editor: PlateEditor,
281
dragItem: DragItemNode,
282
targetElement: TElement,
283
monitor: DropTargetMonitor,
284
nodeRef: React.RefObject<HTMLElement>
285
) {
286
const result = getDropPath(editor, {
287
dragItem,
288
element: targetElement,
289
monitor,
290
nodeRef,
291
orientation: 'vertical'
292
});
293
294
if (result) {
295
// Perform custom operations before/after move
296
console.log('Moving from', result.from, 'to', result.to);
297
298
// Move the node
299
editor.tf.moveNodes({
300
at: result.from,
301
to: result.to
302
});
303
}
304
}
305
306
// Validation before drop
307
function validateDrop(
308
editor: PlateEditor,
309
dragItem: DragItemNode,
310
targetElement: TElement,
311
monitor: DropTargetMonitor,
312
nodeRef: React.RefObject<HTMLElement>
313
): boolean {
314
const result = getDropPath(editor, {
315
dragItem,
316
element: targetElement,
317
monitor,
318
nodeRef,
319
canDropNode: ({ dragEntry, dropEntry }) => {
320
// Custom validation logic
321
return dragEntry[0].type === dropEntry[0].type;
322
}
323
});
324
325
return result !== null;
326
}
327
```
328
329
### onHoverNode
330
331
Handles hover events during drag operations, managing visual feedback and drop target state.
332
333
```typescript { .api }
334
/**
335
* Handles hover events during drag operations
336
* Manages drop target state and visual feedback
337
* @param editor - The Plate editor instance
338
* @param options - Hover handling options
339
*/
340
export function onHoverNode(
341
editor: PlateEditor,
342
options: OnHoverNodeOptions
343
): void;
344
345
export interface OnHoverNodeOptions {
346
canDropNode?: CanDropCallback;
347
dragItem: DragItemNode;
348
element: TElement;
349
monitor: DropTargetMonitor<DragItemNode, unknown>;
350
nodeRef: any;
351
orientation?: 'horizontal' | 'vertical';
352
}
353
```
354
355
**Usage Examples:**
356
357
```typescript
358
import { onHoverNode } from "@udecode/plate-dnd";
359
360
// In a custom hover handler
361
function customHoverHandler(
362
editor: PlateEditor,
363
dragItem: DragItemNode,
364
targetElement: TElement,
365
monitor: DropTargetMonitor,
366
nodeRef: React.RefObject<HTMLElement>
367
) {
368
onHoverNode(editor, {
369
dragItem,
370
element: targetElement,
371
monitor,
372
nodeRef,
373
orientation: 'vertical'
374
});
375
376
// Additional custom hover logic
377
if (monitor.isOver({ shallow: true })) {
378
console.log('Hovering over target element');
379
}
380
}
381
```
382
383
## Types
384
385
```typescript { .api }
386
export type CanDropCallback = (args: {
387
dragEntry: NodeEntry<TElement>;
388
dragItem: DragItemNode;
389
dropEntry: NodeEntry<TElement>;
390
editor: PlateEditor;
391
}) => boolean;
392
393
export interface ElementDragItemNode {
394
id: string;
395
element: TElement;
396
[key: string]: unknown;
397
}
398
399
export type EditorNodesOptions<T> = {
400
at?: Location;
401
match?: (node: T) => boolean;
402
mode?: 'all' | 'highest' | 'lowest';
403
universal?: boolean;
404
reverse?: boolean;
405
voids?: boolean;
406
};
407
```