0
# React Components
1
2
React integration providing UI components, hooks, and state management for media interactions. Includes plugin wrappers, specialized components for media control, and comprehensive state management systems.
3
4
## Capabilities
5
6
### React Plugin Wrappers
7
8
React-wrapped versions of the base plugins with enhanced UI integration.
9
10
```typescript { .api }
11
/**
12
* React-wrapped image plugin with UI components and hooks
13
*/
14
const ImagePlugin: TPlatePlugin<ImageConfig>;
15
16
/**
17
* React-wrapped media embed plugin with UI integration
18
*/
19
const MediaEmbedPlugin: TPlatePlugin<MediaEmbedConfig>;
20
21
/**
22
* React-wrapped audio plugin
23
*/
24
const AudioPlugin: TPlatePlugin<AudioConfig>;
25
26
/**
27
* React-wrapped file plugin
28
*/
29
const FilePlugin: TPlatePlugin<FileConfig>;
30
31
/**
32
* React-wrapped video plugin
33
*/
34
const VideoPlugin: TPlatePlugin<VideoConfig>;
35
```
36
37
**Usage Example:**
38
39
```typescript
40
import {
41
ImagePlugin,
42
MediaEmbedPlugin,
43
AudioPlugin
44
} from "@udecode/plate-media/react";
45
import { createPlateEditor } from "@udecode/plate";
46
47
const editor = createPlateEditor({
48
plugins: [
49
ImagePlugin.configure({
50
options: {
51
uploadImage: async (file) => {
52
const formData = new FormData();
53
formData.append('file', file);
54
const response = await fetch('/upload', {
55
method: 'POST',
56
body: formData
57
});
58
const data = await response.json();
59
return data.url;
60
}
61
}
62
}),
63
MediaEmbedPlugin,
64
AudioPlugin,
65
VideoPlugin,
66
FilePlugin
67
]
68
});
69
```
70
71
## Media State Management
72
73
Comprehensive state management for media elements with React integration.
74
75
### Media Store
76
77
Global state management for media element visibility and captions.
78
79
```typescript { .api }
80
/**
81
* Atom store for media state management
82
*/
83
interface MediaStore {
84
/** Whether captions are visible */
85
showCaption: boolean;
86
}
87
88
/**
89
* Provider component for media store context
90
*/
91
const MediaProvider: React.ComponentType<{ children: React.ReactNode }>;
92
93
/**
94
* Hook to access the entire media store
95
*/
96
function useMediaStore(): MediaStore;
97
98
/**
99
* Hook to access specific media store values
100
*/
101
function useMediaValue<T>(selector: (store: MediaStore) => T): T;
102
103
/**
104
* Hook to update media store values
105
*/
106
function useMediaSet(): (updates: Partial<MediaStore>) => void;
107
```
108
109
**Usage Example:**
110
111
```typescript
112
import {
113
MediaProvider,
114
useMediaValue,
115
useMediaSet
116
} from "@udecode/plate-media/react";
117
118
const MediaApp = () => {
119
return (
120
<MediaProvider>
121
<MediaControls />
122
<MediaContent />
123
</MediaProvider>
124
);
125
};
126
127
const MediaControls = () => {
128
const showCaption = useMediaValue(store => store.showCaption);
129
const setMediaState = useMediaSet();
130
131
return (
132
<button
133
onClick={() => setMediaState({ showCaption: !showCaption })}
134
>
135
{showCaption ? 'Hide' : 'Show'} Captions
136
</button>
137
);
138
};
139
```
140
141
### Media Element State
142
143
Comprehensive state hook for individual media elements.
144
145
```typescript { .api }
146
/**
147
* Provides comprehensive media element state including embed data and provider info
148
* @param options - Configuration with URL parsers
149
* @returns Complete media element state
150
*/
151
function useMediaState(options?: {
152
urlParsers?: EmbedUrlParser[]
153
}): MediaStateResult;
154
155
interface MediaStateResult {
156
// Element properties
157
id: string;
158
url: string;
159
align: string;
160
focused: boolean;
161
selected: boolean;
162
163
// Parsed embed data
164
embed: EmbedUrlData | null;
165
166
// Provider detection
167
isTweet: boolean;
168
isVideo: boolean;
169
isYoutube: boolean;
170
isVimeo: boolean;
171
172
// UI state
173
caption: string;
174
showCaption: boolean;
175
176
// Dimensions
177
width: number;
178
height: number;
179
aspectRatio: number;
180
}
181
```
182
183
**Usage Example:**
184
185
```typescript
186
import {
187
useMediaState,
188
parseVideoUrl,
189
parseTwitterUrl
190
} from "@udecode/plate-media/react";
191
192
const MediaElement = () => {
193
const mediaState = useMediaState({
194
urlParsers: [parseVideoUrl, parseTwitterUrl]
195
});
196
197
return (
198
<div className={`media-element ${mediaState.focused ? 'focused' : ''}`}>
199
{mediaState.isYoutube && (
200
<div>YouTube Video: {mediaState.embed?.id}</div>
201
)}
202
203
{mediaState.isTweet && (
204
<div>Tweet ID: {mediaState.embed?.id}</div>
205
)}
206
207
{mediaState.showCaption && (
208
<div className="caption">{mediaState.caption}</div>
209
)}
210
211
<div>
212
Dimensions: {mediaState.width}x{mediaState.height}
213
(Aspect Ratio: {mediaState.aspectRatio})
214
</div>
215
</div>
216
);
217
};
218
```
219
220
## Media Controller Components
221
222
UI components for controlling media elements with dropdown menus and toolbars.
223
224
### Media Controller
225
226
State management for media control dropdowns and interactions.
227
228
```typescript { .api }
229
/**
230
* Provides media control dropdown state management
231
* @returns Controller state and handlers
232
*/
233
function useMediaController(): {
234
isOpen: boolean;
235
open: () => void;
236
close: () => void;
237
toggle: () => void;
238
};
239
240
/**
241
* Controller state management hook
242
* @returns Detailed controller state
243
*/
244
function useMediaControllerState(): {
245
activeId: string | null;
246
isOpen: boolean;
247
setActiveId: (id: string | null) => void;
248
};
249
250
/**
251
* Dropdown menu state for media controller
252
* @returns Menu state and handlers
253
*/
254
function useMediaControllerDropDownMenu(): {
255
isOpen: boolean;
256
onOpenChange: (open: boolean) => void;
257
};
258
```
259
260
### Media Toolbar Button
261
262
Toolbar integration for media insertion buttons.
263
264
```typescript { .api }
265
/**
266
* Provides toolbar button props for media insertion
267
* @param options - Configuration options
268
* @returns Button props and handlers
269
*/
270
function useMediaToolbarButton(options?: {
271
nodeType?: string
272
}): {
273
pressed: boolean;
274
onClick: () => void;
275
disabled: boolean;
276
};
277
```
278
279
**Usage Example:**
280
281
```typescript
282
import {
283
useMediaToolbarButton,
284
useMediaController
285
} from "@udecode/plate-media/react";
286
287
const MediaToolbar = () => {
288
const imageButton = useMediaToolbarButton({ nodeType: 'image' });
289
const videoButton = useMediaToolbarButton({ nodeType: 'video' });
290
const controller = useMediaController();
291
292
return (
293
<div className="media-toolbar">
294
<button
295
{...imageButton}
296
className={imageButton.pressed ? 'active' : ''}
297
>
298
Insert Image
299
</button>
300
301
<button
302
{...videoButton}
303
className={videoButton.pressed ? 'active' : ''}
304
>
305
Insert Video
306
</button>
307
308
<div className="media-controller">
309
<button onClick={controller.toggle}>
310
Media Options
311
</button>
312
313
{controller.isOpen && (
314
<div className="dropdown">
315
<button onClick={() => {/* handle action */}}>
316
Edit Media
317
</button>
318
<button onClick={() => {/* handle action */}}>
319
Remove Media
320
</button>
321
</div>
322
)}
323
</div>
324
</div>
325
);
326
};
327
```
328
329
## Floating Media Components
330
331
Floating UI components for in-place media editing with URL input and validation.
332
333
### Floating Media Store
334
335
State management for floating media editing operations.
336
337
```typescript { .api }
338
/**
339
* Zustand store for floating media editing state
340
*/
341
interface FloatingMediaStore {
342
/** Whether editing mode is active */
343
isEditing: boolean;
344
/** Current URL being edited */
345
url: string;
346
347
/** Reset editing state */
348
reset(): void;
349
}
350
351
/**
352
* Hook to access floating media state
353
*/
354
function useFloatingMediaState(): FloatingMediaStore;
355
356
/**
357
* Hook to access floating media values
358
*/
359
function useFloatingMediaValue<T>(
360
selector: (store: FloatingMediaStore) => T
361
): T;
362
```
363
364
### Floating Media Components
365
366
React components for floating media editing interface.
367
368
```typescript { .api }
369
/**
370
* Container component with edit button and URL input
371
*/
372
const FloatingMedia: {
373
EditButton: React.ComponentType;
374
UrlInput: React.ComponentType;
375
};
376
377
/**
378
* Primitive edit button component
379
* Sets store to editing mode when clicked
380
*/
381
const FloatingMediaEditButton: React.ComponentType;
382
383
/**
384
* Primitive URL input component with validation
385
* Handles auto-focus and keyboard interactions
386
*/
387
const FloatingMediaUrlInput: React.ComponentType;
388
```
389
390
### Floating Media Hooks
391
392
Specialized hooks for floating media functionality.
393
394
```typescript { .api }
395
/**
396
* Hook for edit button functionality
397
* @returns Click handler that activates editing mode
398
*/
399
function useFloatingMediaEditButton(): {
400
onClick: () => void;
401
};
402
403
/**
404
* Hook for URL input state management
405
* @param options - Configuration options
406
* @returns Keyboard handling and state management
407
*/
408
function useFloatingMediaUrlInputState(options: {
409
plugin: any
410
}): {
411
onKeyDown: (event: KeyboardEvent) => void;
412
onEscape: () => void;
413
onEnter: () => void;
414
};
415
416
/**
417
* Hook for URL input props
418
* @param options - Configuration options
419
* @returns Input props and handlers
420
*/
421
function useFloatingMediaUrlInput(options: {
422
defaultValue?: string
423
}): {
424
value: string;
425
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
426
onBlur: () => void;
427
autoFocus: boolean;
428
};
429
```
430
431
### Floating Media Functions
432
433
Utility functions for floating media operations.
434
435
```typescript { .api }
436
/**
437
* Validates and updates media element URL
438
* @param editor - Slate editor instance
439
* @param options - Element and plugin configuration
440
* @returns Success status
441
*/
442
function submitFloatingMedia(
443
editor: SlateEditor,
444
options: {
445
element: TMediaElement;
446
plugin: any
447
}
448
): boolean;
449
```
450
451
**Usage Example:**
452
453
```typescript
454
import {
455
FloatingMedia,
456
useFloatingMediaState,
457
submitFloatingMedia,
458
useFloatingMediaUrlInput
459
} from "@udecode/plate-media/react";
460
461
const FloatingMediaEditor = ({ element, plugin }) => {
462
const { isEditing } = useFloatingMediaState();
463
const urlInput = useFloatingMediaUrlInput({
464
defaultValue: element.url
465
});
466
467
const handleSubmit = () => {
468
const success = submitFloatingMedia(editor, { element, plugin });
469
if (success) {
470
// Handle successful update
471
}
472
};
473
474
return (
475
<div className="floating-media">
476
{!isEditing ? (
477
<FloatingMedia.EditButton />
478
) : (
479
<div className="url-editor">
480
<input
481
{...urlInput}
482
placeholder="Enter media URL..."
483
/>
484
<button onClick={handleSubmit}>
485
Update
486
</button>
487
</div>
488
)}
489
</div>
490
);
491
};
492
493
// Using the compound component approach
494
const SimpleFloatingMedia = () => (
495
<FloatingMedia>
496
<FloatingMedia.EditButton />
497
<FloatingMedia.UrlInput />
498
</FloatingMedia>
499
);
500
```
501
502
## Image Preview System (React)
503
504
Advanced image preview system with React components and state management.
505
506
### Image Preview Access
507
508
```typescript { .api }
509
/**
510
* Hook to access ImagePreviewStore values
511
* @returns Current preview store state
512
*/
513
function useImagePreviewValue(): ImagePreviewStoreState;
514
```
515
516
### Image Preview Functions
517
518
```typescript { .api }
519
/**
520
* Opens image preview overlay for the specified image element
521
* @param editor - Slate editor instance
522
* @param element - Media element to preview
523
*/
524
function openImagePreview(editor: SlateEditor, element: TMediaElement): void;
525
```
526
527
### Image Components (React)
528
529
Specialized React components for image rendering and preview functionality.
530
531
```typescript { .api }
532
/**
533
* Primitive image component with drag and preview functionality
534
* Provides double-click to open preview and draggable behavior
535
*/
536
const Image: React.ComponentType;
537
538
/**
539
* Hook providing image component props and handlers
540
* @returns Props for image element including drag and preview handlers
541
*/
542
function useImage(): {
543
onDoubleClick: () => void;
544
draggable: boolean;
545
onDragStart: (event: DragEvent) => void;
546
};
547
548
/**
549
* Primitive component for preview overlay image
550
* Handles click-to-zoom and transform styles
551
*/
552
const PreviewImage: React.ComponentType;
553
554
/**
555
* Hook providing preview image props with zoom and transform functionality
556
* @returns Props for preview image including click handlers and styles
557
*/
558
function usePreviewImage(): {
559
onClick: () => void;
560
style: CSSProperties;
561
cursor: string;
562
};
563
```
564
565
**Complete React Integration Example:**
566
567
```typescript
568
import {
569
ImagePlugin,
570
MediaEmbedPlugin,
571
PlaceholderPlugin,
572
MediaProvider,
573
useMediaState,
574
useImagePreview,
575
openImagePreview,
576
Image,
577
PreviewImage
578
} from "@udecode/plate-media/react";
579
580
const MediaRichEditor = () => {
581
const editor = createPlateEditor({
582
plugins: [
583
ImagePlugin.configure({
584
options: {
585
uploadImage: async (file) => {
586
// Upload implementation
587
return await uploadToServer(file);
588
}
589
}
590
}),
591
MediaEmbedPlugin,
592
PlaceholderPlugin.configure({
593
options: {
594
uploadConfig: {
595
image: { mediaType: 'image', maxFileSize: '5MB' },
596
video: { mediaType: 'video', maxFileSize: '50MB' }
597
}
598
}
599
})
600
]
601
});
602
603
return (
604
<MediaProvider>
605
<PlateProvider editor={editor}>
606
<Plate>
607
<PlateContent />
608
<ImagePreviewOverlay />
609
</Plate>
610
</PlateProvider>
611
</MediaProvider>
612
);
613
};
614
615
const ImagePreviewOverlay = () => {
616
const previewControls = useImagePreview({ scrollSpeed: 0.1 });
617
618
return (
619
<div
620
className="image-preview-overlay"
621
onKeyDown={previewControls.onKeyDown}
622
onWheel={previewControls.onWheel}
623
tabIndex={0}
624
>
625
<PreviewImage />
626
627
<div className="preview-controls">
628
<button onClick={previewControls.zoomIn}>
629
Zoom In
630
</button>
631
<button onClick={previewControls.zoomOut}>
632
Zoom Out
633
</button>
634
<button onClick={previewControls.goPrevious}>
635
Previous
636
</button>
637
<button onClick={previewControls.goNext}>
638
Next
639
</button>
640
</div>
641
</div>
642
);
643
};
644
```
645
646
This React integration provides a complete media handling solution with:
647
648
1. **Plugin Integration**: Seamless integration with Plate editor plugins
649
2. **State Management**: Comprehensive state management with Zustand and Atom stores
650
3. **UI Components**: Pre-built components for common media interactions
651
4. **Upload System**: Advanced file upload with validation and progress tracking
652
5. **Preview System**: Full-featured image preview with zoom and navigation
653
6. **Floating Editors**: In-place editing capabilities for media URLs
654
7. **Toolbar Integration**: Ready-to-use toolbar buttons and controls