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

hooks-and-utilities.mddocs/

Hooks and Utilities

React hooks and utility functions for managing caption state and providing programmatic control over caption functionality.

Capabilities

useCaptionString Hook

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>
  );
}

Component State Hooks

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>
  );
}

Textarea State Hooks

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"
    />
  );
}

Button State Hooks

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>
  );
}

showCaption Utility

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>
  );
}

Advanced Usage Patterns

Custom Caption Implementation

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>
  );
}

Multi-language Caption Support

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

docs

core-plugin.md

hooks-and-utilities.md

index.md

react-components.md

tile.json