Skip to content

Lexical Editor Component (components/Editor/lexicalEditor.tsx)

Overview

A comprehensive React component that implements a rich text editor using the Lexical framework. The component provides collaborative editing capabilities, evidence highlighting, and real-time state management with support for various plugins and features.

Features

  • Real-time collaboration
  • Evidence highlighting
  • Rich text editing
  • State persistence
  • Plugin architecture

Dependencies

import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { CollaborationPlugin } from '@lexical/react/LexicalCollaborationPlugin'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import * as Y from 'yjs'

Props

interface EditorProps {
  readOnly?: boolean;
  isFullView?: boolean;
  stateID?: string;
  state?: string;
  shouldExport?: boolean;
  citedEvidence?: citedEvidence;
  evidence_scale?: string;
  uuids?: string[];
  isInitialState?: boolean;
  editedState?: boolean;
  n_requests?: number;
  collaboratorID?: string;
  onStateChange?: (state: string) => void;
  onClicked?: () => void;
  clicked?: boolean;
}

Implementation

State Management

// State variables for managing dropdown, highlighting, and current index
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [isHighlighted, setIsHighlighted] = useState(false);
const [currentIndex, setCurrentIndex] = useState<number>(0);

// Configuration state for the Lexical editor
const [currentConfig, setCurrentConfig] = useState({
  ...initialConfig,
  editable: !props.readOnly,
});

Methods

// Toggles the dropdown menu for cited evidence
const toggleDropdown = () => {
  setIsDropdownOpen(prev => !prev);
};

// Toggles the highlighting state for evidence
const toggleHighlight = () => {
  setIsHighlighted(prev => !prev);
};

// Updates the current index for UUIDs
const handleIndexChange = (index: number) => {
  setCurrentIndex(index);
};

Unique Functionality

// Handles awareness updates for collaborative editing
const handleAwarenessUpdate = useCallback(() => {
  const awareness = yjsProvider!.awareness!;
  setActiveUsers(
    Array.from(awareness.getStates().entries()).map(
      (entry) => {
        const [userId, { color, name }] = entry as unknown as [string, { color: string; name: string }];
        return {
          color,
          name,
          userId,
        };
      },
    ),
  );
}, [yjsProvider]);

HTML Structure

// Main container for the Lexical editor
<div className="bg-white p-2 border rounded-lg relative">
  <LexicalComposer initialConfig={currentConfig}>
    {props.isFullView && <ToolbarPlugin />}
    <RichTextPlugin
      contentEditable={<ContentEditable />}
      ErrorBoundary={LexicalErrorBoundary}
    />
    <ChangeAnalysisPlugin 
      isInitialState={props.isInitialState} 
      onStateChange={props.onStateChange} 
    />
    <EditableWarningPlugin 
      isFullView={props.isFullView} 
      editedState={props.editedState} 
      clicked={props.clicked}  
      onClicked={props.onClicked} 
    />
    <HighlighterPlugin 
      isHighlighted={isHighlighted} 
      citedEvidence={props.citedEvidence} 
      uuids={props.uuids} 
      selectedUUIDIndex={currentIndex} 
    />
    <ExportEditorStatePlugin 
      stateID={props.stateID} 
      editedState={props.editedState}  
      shouldExport={props.shouldExport} 
      n_requests={props.n_requests}
    />
    <AutoFocusPlugin />
    {props.collaboratorID && (
      <CollaborationPlugin
        id={props.collaboratorID}
        providerFactory={providerFactory}
        shouldBootstrap={false}
        username={'Tyler'}
        cursorColor='blue'
        cursorsContainerRef={containerRef}
      />
    )}
  </LexicalComposer>
</div>

API Integration

  • No direct API integration; uses YJS for real-time collaboration.

Components Used

Notes

  • Implements real-time collaboration using YJS
  • Manages editor state persistence
  • Handles evidence highlighting
  • Supports plugin architecture
  • Provides user awareness features
  • Maintains responsive layout
  • Ensures accessibility
  • Manages state synchronization
  • Handles error boundaries
  • Supports custom configurations