CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-udecode--plate-caption

Primitive React components and hooks for implementing caption functionality in Plate rich-text editors.

Pending
Overview
Eval results
Files

react-components.mddocs/

React Components

React components provide the UI layer for caption functionality with primitive, unstyled components that can be fully customized and themed.

Capabilities

CaptionPlugin

React-compatible version of BaseCaptionPlugin for use in React Plate editors.

/**
 * React plugin wrapper for caption functionality
 */
const CaptionPlugin = toPlatePlugin(BaseCaptionPlugin);

Usage Examples:

import { createPlateEditor } from "@udecode/plate/react";
import { CaptionPlugin } from "@udecode/plate-caption/react";

const editor = createPlateEditor({
  plugins: [
    CaptionPlugin.configure({
      options: {
        query: { allow: ['img', 'media'] }
      }
    })
  ]
});

Caption Container

Main caption container component that renders as a figcaption element with visibility and state management.

/**
 * Caption container component
 * @param props - Standard figcaption props plus caption options
 * @returns JSX.Element or null if hidden
 */
function Caption(props: CaptionProps): JSX.Element;

interface CaptionProps extends React.ComponentPropsWithoutRef<'figcaption'> {
  options?: CaptionOptions;
}

interface CaptionOptions {
  readOnly?: boolean;
}

/**
 * State hook for Caption component
 * @param options - Caption configuration options
 * @returns State object with caption data and visibility flags
 */
function useCaptionState(options?: CaptionOptions): {
  captionString: string;
  hidden: boolean;
  readOnly: boolean;
  selected: boolean;
};

/**
 * Props hook for Caption component
 * @param state - State from useCaptionState
 * @returns Props object for caption element
 */
function useCaption(state: ReturnType<typeof useCaptionState>): {
  hidden: boolean;
};

Usage Examples:

import { Caption } from "@udecode/plate-caption/react";

// Basic usage
function ImageWithCaption() {
  return (
    <div>
      <img src="example.jpg" />
      <Caption className="image-caption">
        Caption content here
      </Caption>
    </div>
  );
}

// With read-only option
function ReadOnlyCaption() {
  return (
    <Caption options={{ readOnly: true }}>
      This caption cannot be edited
    </Caption>
  );
}

// Custom styling
function StyledCaption() {
  return (
    <Caption 
      style={{ fontStyle: 'italic', color: '#666' }}
      className="custom-caption"
    >
      Styled caption content
    </Caption>
  );
}

CaptionTextarea

Editable textarea component for caption text with auto-resizing, focus management, and keyboard navigation.

/**
 * Auto-resizing textarea for caption editing
 * @param props - TextareaAutosize props
 * @returns JSX.Element
 */
function CaptionTextarea(
  props: React.ComponentProps<typeof TextareaAutosize>
): JSX.Element;

/**
 * State hook for CaptionTextarea component
 * @returns State object with handlers and refs
 */
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 - Ref to textarea element
 */
function useCaptionTextareaFocus(
  textareaRef: React.RefObject<HTMLTextAreaElement | null>
): void;

Key Features:

  • Auto-resize: Automatically adjusts height based on content
  • Focus Management: Integrates with plugin focus path system
  • Keyboard Navigation: Up/down arrows move between editor and caption
  • Composition Handling: Proper support for IME input methods
  • Auto-save: Changes are automatically saved to editor state

Usage Examples:

import { CaptionTextarea } from "@udecode/plate-caption/react";

// Basic usage
function EditableCaption() {
  return (
    <CaptionTextarea 
      placeholder="Enter image caption..."
      className="caption-input"
    />
  );
}

// With custom props
function CustomCaption() {
  return (
    <CaptionTextarea
      placeholder="Describe this image..."
      maxRows={3}
      style={{ 
        border: '1px solid #ccc',
        borderRadius: '4px',
        padding: '8px'
      }}
    />
  );
}

// In combination with Caption container
function CompleteCaption() {
  return (
    <Caption>
      <CaptionTextarea placeholder="Add caption..." />
    </Caption>
  );
}

TextareaAutosize

Auto-resizing textarea primitive with SSR compatibility.

/**
 * Auto-resizing textarea component
 * @param props - Standard textarea props plus autosize options
 * @param ref - Ref to textarea element
 * @returns JSX.Element or null during SSR
 */
const TextareaAutosize = React.forwardRef<
  HTMLTextAreaElement,
  TextareaAutosizeProps
>((props, ref) => JSX.Element);

interface TextareaAutosizeProps {
  maxRows?: number;
  minRows?: number;
  onHeightChange?: (height: number, meta: { rowHeight: number }) => void;
  cacheMeasurements?: boolean;
  [key: string]: any; // Standard textarea props
}

Usage Examples:

import { TextareaAutosize } from "@udecode/plate-caption/react";

// Basic auto-resize textarea
function AutoTextarea() {
  return (
    <TextareaAutosize
      placeholder="Type here..."
      minRows={2}
      maxRows={8}
    />
  );
}

// With height change callback
function MonitoredTextarea() {
  const handleHeightChange = (height: number) => {
    console.log('Textarea height changed to:', height);
  };

  return (
    <TextareaAutosize
      onHeightChange={handleHeightChange}
      placeholder="Resizing textarea..."
    />
  );
}

Caption Button Components

Utility components for caption interaction buttons.

/**
 * State hook for caption button functionality
 * @returns State with editor and element references
 */
function useCaptionButtonState(): {
  editor: SlateEditor;
  element: TElement;
};

/**
 * Props hook for caption button
 * @param state - State from useCaptionButtonState
 * @returns Props with click handler
 */
function useCaptionButton(
  state: ReturnType<typeof useCaptionButtonState>
): {
  props: {
    onClick: () => void;
  };
};

Usage Examples:

import { useCaptionButton, useCaptionButtonState } from "@udecode/plate-caption/react";

function CaptionToggleButton() {
  const state = useCaptionButtonState();
  const { props } = useCaptionButton(state);

  return (
    <button {...props} className="caption-toggle">
      Add Caption
    </button>
  );
}

Component Composition

Components are designed to be composed together for complete caption functionality:

import { 
  Caption, 
  CaptionTextarea,
  useCaptionButton,
  useCaptionButtonState 
} from "@udecode/plate-caption/react";

function MediaWithCaption({ src, alt }: { src: string; alt: string }) {
  const buttonState = useCaptionButtonState();
  const { props: buttonProps } = useCaptionButton(buttonState);

  return (
    <figure>
      <img src={src} alt={alt} />
      <Caption>
        <CaptionTextarea placeholder="Add a caption..." />
      </Caption>
      <button {...buttonProps} className="add-caption-btn">
        📝 Add Caption
      </button>
    </figure>
  );
}

Styling and Customization

All components are unstyled primitives that accept standard HTML props and can be fully customized:

// CSS-in-JS styling
const StyledCaption = styled(Caption)`
  font-style: italic;
  color: #666;
  text-align: center;
  margin-top: 8px;
`;

// Tailwind classes
<Caption className="text-sm text-gray-600 italic text-center">
  <CaptionTextarea className="w-full border rounded p-2" />
</Caption>

// Inline styles
<Caption style={{ fontFamily: 'Georgia, serif' }}>
  <CaptionTextarea style={{ backgroundColor: '#f9f9f9' }} />
</Caption>

Install with Tessl CLI

npx tessl i tessl/npm-udecode--plate-caption

docs

core-plugin.md

hooks-and-utilities.md

index.md

react-components.md

tile.json