0
# Hooks and Utilities
1
2
React hooks and utility functions for managing caption state and providing programmatic control over caption functionality.
3
4
## Capabilities
5
6
### useCaptionString Hook
7
8
Extracts and returns the caption text from the current element context.
9
10
```typescript { .api }
11
/**
12
* Hook that extracts caption text from current element
13
* @returns String content of the element's caption
14
*/
15
function useCaptionString(): string;
16
```
17
18
**Usage Examples:**
19
20
```typescript
21
import { useCaptionString } from "@udecode/plate-caption/react";
22
23
function CaptionDisplay() {
24
const captionText = useCaptionString();
25
26
return (
27
<div className="caption-preview">
28
{captionText ? (
29
<p>Caption: {captionText}</p>
30
) : (
31
<p>No caption available</p>
32
)}
33
</div>
34
);
35
}
36
37
// In a custom caption component
38
function CustomCaptionComponent() {
39
const captionString = useCaptionString();
40
const isEmpty = captionString.length === 0;
41
42
return (
43
<figcaption className={isEmpty ? 'empty-caption' : 'has-caption'}>
44
{captionString || 'Click to add caption...'}
45
</figcaption>
46
);
47
}
48
```
49
50
### Component State Hooks
51
52
Hooks for managing component state in custom caption implementations.
53
54
```typescript { .api }
55
/**
56
* State hook for Caption component functionality
57
* @param options - Optional configuration for caption behavior
58
* @returns State object with caption data and flags
59
*/
60
function useCaptionState(options?: CaptionOptions): {
61
captionString: string;
62
hidden: boolean;
63
readOnly: boolean;
64
selected: boolean;
65
};
66
67
/**
68
* Props hook for Caption component
69
* @param state - State object from useCaptionState
70
* @returns Props object for caption element
71
*/
72
function useCaption(
73
state: ReturnType<typeof useCaptionState>
74
): {
75
hidden: boolean;
76
};
77
78
interface CaptionOptions {
79
readOnly?: boolean;
80
}
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
import { useCaptionState, useCaption } from "@udecode/plate-caption/react";
87
88
function CustomCaption({ children, ...props }) {
89
const state = useCaptionState({ readOnly: false });
90
const captionProps = useCaption(state);
91
92
if (captionProps.hidden) {
93
return null;
94
}
95
96
return (
97
<figcaption
98
{...props}
99
className={`caption ${state.selected ? 'selected' : ''}`}
100
data-readonly={state.readOnly}
101
>
102
{children}
103
{state.captionString && (
104
<span className="caption-text">{state.captionString}</span>
105
)}
106
</figcaption>
107
);
108
}
109
```
110
111
### Textarea State Hooks
112
113
Specialized hooks for caption textarea functionality.
114
115
```typescript { .api }
116
/**
117
* State hook for CaptionTextarea component
118
* @returns Complete state object for textarea functionality
119
*/
120
function useCaptionTextareaState(): {
121
captionValue: string;
122
element: TCaptionElement;
123
readOnly: boolean;
124
textareaRef: React.RefObject<HTMLTextAreaElement>;
125
handleChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
126
handleCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
127
handleCompositionStart: () => void;
128
};
129
130
/**
131
* Props hook for CaptionTextarea component
132
* @param state - State from useCaptionTextareaState
133
* @returns Props and ref for textarea element
134
*/
135
function useCaptionTextarea(
136
state: ReturnType<typeof useCaptionTextareaState>
137
): {
138
props: {
139
readOnly: boolean;
140
value: string;
141
onBlur: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
142
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
143
onCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
144
onCompositionStart: () => void;
145
onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
146
};
147
ref: React.RefObject<HTMLTextAreaElement>;
148
};
149
150
/**
151
* Focus management hook for caption textarea
152
* @param textareaRef - Reference to textarea element
153
*/
154
function useCaptionTextareaFocus(
155
textareaRef: React.RefObject<HTMLTextAreaElement | null>
156
): void;
157
```
158
159
**Usage Examples:**
160
161
```typescript
162
import {
163
useCaptionTextareaState,
164
useCaptionTextarea,
165
useCaptionTextareaFocus
166
} from "@udecode/plate-caption/react";
167
168
function CustomCaptionTextarea() {
169
const state = useCaptionTextareaState();
170
const { props, ref } = useCaptionTextarea(state);
171
172
// Focus hook is automatically called in useCaptionTextareaState
173
// but can be used separately if needed
174
175
return (
176
<div className="caption-input-wrapper">
177
<textarea
178
{...props}
179
ref={ref}
180
className="custom-caption-textarea"
181
placeholder="Enter caption..."
182
/>
183
{state.readOnly && (
184
<div className="readonly-indicator">Read Only</div>
185
)}
186
</div>
187
);
188
}
189
190
// Manual focus management
191
function ManualFocusTextarea() {
192
const textareaRef = useRef<HTMLTextAreaElement>(null);
193
194
// Apply focus management manually
195
useCaptionTextareaFocus(textareaRef);
196
197
return (
198
<textarea
199
ref={textareaRef}
200
placeholder="Caption with manual focus management"
201
/>
202
);
203
}
204
```
205
206
### Button State Hooks
207
208
Hooks for caption button functionality.
209
210
```typescript { .api }
211
/**
212
* State hook for caption button components
213
* @returns State with editor and element references
214
*/
215
function useCaptionButtonState(): {
216
editor: SlateEditor;
217
element: TElement;
218
};
219
220
/**
221
* Props hook for caption button components
222
* @param state - State from useCaptionButtonState
223
* @returns Props object with click handler
224
*/
225
function useCaptionButton(
226
state: ReturnType<typeof useCaptionButtonState>
227
): {
228
props: {
229
onClick: () => void;
230
};
231
};
232
```
233
234
**Usage Examples:**
235
236
```typescript
237
import { useCaptionButtonState, useCaptionButton } from "@udecode/plate-caption/react";
238
239
function CaptionToggleButton() {
240
const state = useCaptionButtonState();
241
const { props } = useCaptionButton(state);
242
243
return (
244
<button
245
{...props}
246
className="caption-toggle-btn"
247
type="button"
248
>
249
Add Caption
250
</button>
251
);
252
}
253
254
// Custom button with additional logic
255
function SmartCaptionButton() {
256
const state = useCaptionButtonState();
257
const { props } = useCaptionButton(state);
258
259
const handleClick = () => {
260
// Custom logic before showing caption
261
console.log('Opening caption for element:', state.element.id);
262
263
// Call the original handler
264
props.onClick();
265
266
// Custom logic after showing caption
267
setTimeout(() => {
268
console.log('Caption should now be visible');
269
}, 100);
270
};
271
272
return (
273
<button
274
onClick={handleClick}
275
className="smart-caption-btn"
276
disabled={!state.element}
277
>
278
š Caption
279
</button>
280
);
281
}
282
```
283
284
### showCaption Utility
285
286
Utility function for programmatically showing and focusing captions.
287
288
```typescript { .api }
289
/**
290
* Utility function to show caption for a specific element
291
* @param editor - Slate editor instance
292
* @param element - Element to show caption for
293
*/
294
function showCaption(editor: SlateEditor, element: TElement): void;
295
```
296
297
**Usage Examples:**
298
299
```typescript
300
import { showCaption } from "@udecode/plate-caption/react";
301
import { useEditorRef } from "@udecode/plate/react";
302
303
function MediaComponent({ element }) {
304
const editor = useEditorRef();
305
306
const handleAddCaption = () => {
307
showCaption(editor, element);
308
};
309
310
const handleDoubleClick = () => {
311
// Show caption on double-click
312
showCaption(editor, element);
313
};
314
315
return (
316
<div onDoubleClick={handleDoubleClick}>
317
<img src={element.url} alt="" />
318
<button onClick={handleAddCaption}>
319
Add Caption
320
</button>
321
</div>
322
);
323
}
324
325
// Programmatic caption management
326
function CaptionManager() {
327
const editor = useEditorRef();
328
329
const showCaptionForImage = (imageId: string) => {
330
const element = editor.api.node({
331
match: { id: imageId }
332
});
333
334
if (element) {
335
showCaption(editor, element[0]);
336
}
337
};
338
339
return (
340
<div>
341
<button onClick={() => showCaptionForImage('img-123')}>
342
Show Caption for Image 123
343
</button>
344
</div>
345
);
346
}
347
```
348
349
## Advanced Usage Patterns
350
351
### Custom Caption Implementation
352
353
Using hooks to create completely custom caption components:
354
355
```typescript
356
import {
357
useCaptionString,
358
useCaptionState,
359
showCaption
360
} from "@udecode/plate-caption/react";
361
import { useEditorRef, useElement } from "@udecode/plate/react";
362
363
function AdvancedCaption() {
364
const editor = useEditorRef();
365
const element = useElement();
366
const captionString = useCaptionString();
367
const state = useCaptionState();
368
369
const [isEditing, setIsEditing] = useState(false);
370
371
const handleStartEdit = () => {
372
showCaption(editor, element);
373
setIsEditing(true);
374
};
375
376
const handleFinishEdit = () => {
377
setIsEditing(false);
378
};
379
380
if (state.hidden && !captionString) {
381
return (
382
<button onClick={handleStartEdit} className="add-caption-btn">
383
+ Add Caption
384
</button>
385
);
386
}
387
388
return (
389
<figcaption className="advanced-caption">
390
{isEditing ? (
391
<div>
392
<CaptionTextarea onBlur={handleFinishEdit} />
393
<button onClick={handleFinishEdit}>Done</button>
394
</div>
395
) : (
396
<div onClick={handleStartEdit}>
397
{captionString || 'Click to add caption...'}
398
</div>
399
)}
400
</figcaption>
401
);
402
}
403
```
404
405
### Multi-language Caption Support
406
407
Using hooks for internationalized caption functionality:
408
409
```typescript
410
function I18nCaption({ locale = 'en' }) {
411
const captionString = useCaptionString();
412
const state = useCaptionState();
413
414
const placeholder = {
415
en: 'Add caption...',
416
es: 'Añadir descripción...',
417
fr: 'Ajouter une lƩgende...'
418
}[locale] || 'Add caption...';
419
420
return (
421
<Caption>
422
<CaptionTextarea
423
placeholder={placeholder}
424
lang={locale}
425
/>
426
</Caption>
427
);
428
}
429
```