Primitive React components and hooks for implementing caption functionality in Plate rich-text editors.
—
React hooks and utility functions for managing caption state and providing programmatic control over caption functionality.
Extracts and returns the caption text from the current element context.
/**
* Hook that extracts caption text from current element
* @returns String content of the element's caption
*/
function useCaptionString(): string;Usage Examples:
import { useCaptionString } from "@udecode/plate-caption/react";
function CaptionDisplay() {
const captionText = useCaptionString();
return (
<div className="caption-preview">
{captionText ? (
<p>Caption: {captionText}</p>
) : (
<p>No caption available</p>
)}
</div>
);
}
// In a custom caption component
function CustomCaptionComponent() {
const captionString = useCaptionString();
const isEmpty = captionString.length === 0;
return (
<figcaption className={isEmpty ? 'empty-caption' : 'has-caption'}>
{captionString || 'Click to add caption...'}
</figcaption>
);
}Hooks for managing component state in custom caption implementations.
/**
* State hook for Caption component functionality
* @param options - Optional configuration for caption behavior
* @returns State object with caption data and flags
*/
function useCaptionState(options?: CaptionOptions): {
captionString: string;
hidden: boolean;
readOnly: boolean;
selected: boolean;
};
/**
* Props hook for Caption component
* @param state - State object from useCaptionState
* @returns Props object for caption element
*/
function useCaption(
state: ReturnType<typeof useCaptionState>
): {
hidden: boolean;
};
interface CaptionOptions {
readOnly?: boolean;
}Usage Examples:
import { useCaptionState, useCaption } from "@udecode/plate-caption/react";
function CustomCaption({ children, ...props }) {
const state = useCaptionState({ readOnly: false });
const captionProps = useCaption(state);
if (captionProps.hidden) {
return null;
}
return (
<figcaption
{...props}
className={`caption ${state.selected ? 'selected' : ''}`}
data-readonly={state.readOnly}
>
{children}
{state.captionString && (
<span className="caption-text">{state.captionString}</span>
)}
</figcaption>
);
}Specialized hooks for caption textarea functionality.
/**
* State hook for CaptionTextarea component
* @returns Complete state object for textarea functionality
*/
function useCaptionTextareaState(): {
captionValue: string;
element: TCaptionElement;
readOnly: boolean;
textareaRef: React.RefObject<HTMLTextAreaElement>;
handleChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
handleCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
handleCompositionStart: () => void;
};
/**
* Props hook for CaptionTextarea component
* @param state - State from useCaptionTextareaState
* @returns Props and ref for textarea element
*/
function useCaptionTextarea(
state: ReturnType<typeof useCaptionTextareaState>
): {
props: {
readOnly: boolean;
value: string;
onBlur: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onCompositionEnd: (e: React.CompositionEvent<HTMLTextAreaElement>) => void;
onCompositionStart: () => void;
onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
};
ref: React.RefObject<HTMLTextAreaElement>;
};
/**
* Focus management hook for caption textarea
* @param textareaRef - Reference to textarea element
*/
function useCaptionTextareaFocus(
textareaRef: React.RefObject<HTMLTextAreaElement | null>
): void;Usage Examples:
import {
useCaptionTextareaState,
useCaptionTextarea,
useCaptionTextareaFocus
} from "@udecode/plate-caption/react";
function CustomCaptionTextarea() {
const state = useCaptionTextareaState();
const { props, ref } = useCaptionTextarea(state);
// Focus hook is automatically called in useCaptionTextareaState
// but can be used separately if needed
return (
<div className="caption-input-wrapper">
<textarea
{...props}
ref={ref}
className="custom-caption-textarea"
placeholder="Enter caption..."
/>
{state.readOnly && (
<div className="readonly-indicator">Read Only</div>
)}
</div>
);
}
// Manual focus management
function ManualFocusTextarea() {
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Apply focus management manually
useCaptionTextareaFocus(textareaRef);
return (
<textarea
ref={textareaRef}
placeholder="Caption with manual focus management"
/>
);
}Hooks for caption button functionality.
/**
* State hook for caption button components
* @returns State with editor and element references
*/
function useCaptionButtonState(): {
editor: SlateEditor;
element: TElement;
};
/**
* Props hook for caption button components
* @param state - State from useCaptionButtonState
* @returns Props object with click handler
*/
function useCaptionButton(
state: ReturnType<typeof useCaptionButtonState>
): {
props: {
onClick: () => void;
};
};Usage Examples:
import { useCaptionButtonState, useCaptionButton } from "@udecode/plate-caption/react";
function CaptionToggleButton() {
const state = useCaptionButtonState();
const { props } = useCaptionButton(state);
return (
<button
{...props}
className="caption-toggle-btn"
type="button"
>
Add Caption
</button>
);
}
// Custom button with additional logic
function SmartCaptionButton() {
const state = useCaptionButtonState();
const { props } = useCaptionButton(state);
const handleClick = () => {
// Custom logic before showing caption
console.log('Opening caption for element:', state.element.id);
// Call the original handler
props.onClick();
// Custom logic after showing caption
setTimeout(() => {
console.log('Caption should now be visible');
}, 100);
};
return (
<button
onClick={handleClick}
className="smart-caption-btn"
disabled={!state.element}
>
📝 Caption
</button>
);
}Utility function for programmatically showing and focusing captions.
/**
* Utility function to show caption for a specific element
* @param editor - Slate editor instance
* @param element - Element to show caption for
*/
function showCaption(editor: SlateEditor, element: TElement): void;Usage Examples:
import { showCaption } from "@udecode/plate-caption/react";
import { useEditorRef } from "@udecode/plate/react";
function MediaComponent({ element }) {
const editor = useEditorRef();
const handleAddCaption = () => {
showCaption(editor, element);
};
const handleDoubleClick = () => {
// Show caption on double-click
showCaption(editor, element);
};
return (
<div onDoubleClick={handleDoubleClick}>
<img src={element.url} alt="" />
<button onClick={handleAddCaption}>
Add Caption
</button>
</div>
);
}
// Programmatic caption management
function CaptionManager() {
const editor = useEditorRef();
const showCaptionForImage = (imageId: string) => {
const element = editor.api.node({
match: { id: imageId }
});
if (element) {
showCaption(editor, element[0]);
}
};
return (
<div>
<button onClick={() => showCaptionForImage('img-123')}>
Show Caption for Image 123
</button>
</div>
);
}Using hooks to create completely custom caption components:
import {
useCaptionString,
useCaptionState,
showCaption
} from "@udecode/plate-caption/react";
import { useEditorRef, useElement } from "@udecode/plate/react";
function AdvancedCaption() {
const editor = useEditorRef();
const element = useElement();
const captionString = useCaptionString();
const state = useCaptionState();
const [isEditing, setIsEditing] = useState(false);
const handleStartEdit = () => {
showCaption(editor, element);
setIsEditing(true);
};
const handleFinishEdit = () => {
setIsEditing(false);
};
if (state.hidden && !captionString) {
return (
<button onClick={handleStartEdit} className="add-caption-btn">
+ Add Caption
</button>
);
}
return (
<figcaption className="advanced-caption">
{isEditing ? (
<div>
<CaptionTextarea onBlur={handleFinishEdit} />
<button onClick={handleFinishEdit}>Done</button>
</div>
) : (
<div onClick={handleStartEdit}>
{captionString || 'Click to add caption...'}
</div>
)}
</figcaption>
);
}Using hooks for internationalized caption functionality:
function I18nCaption({ locale = 'en' }) {
const captionString = useCaptionString();
const state = useCaptionState();
const placeholder = {
en: 'Add caption...',
es: 'Añadir descripción...',
fr: 'Ajouter une légende...'
}[locale] || 'Add caption...';
return (
<Caption>
<CaptionTextarea
placeholder={placeholder}
lang={locale}
/>
</Caption>
);
}Install with Tessl CLI
npx tessl i tessl/npm-udecode--plate-caption