CreaRack-SL

NoteEditor — Componente React del editor de notas (Cuaderno)

Descripción

NoteEditor es el componente React raíz del módulo Cuaderno del Workspace. Gestiona el ciclo de vida completo de una nota: carga inicial, edición en CodeMirror, auto-save con debounce, toggle de modo de vista y apertura del selector de tema.

Localización

src/components/notebook/NoteEditor.tsx

Props

PropTipoDescripción
noteNotebookNoteNota activa (incluye id, title, content, pinned, archived_at, word_count)
onPersist(patch: Partial<NotebookNote>) => Promise<void>Callback para persistir cambios parciales en la nota
onOpenTheme() => voidAbre el panel de selección de tema MD

Estado interno relevante

EstadoTipoDescripción
titlestringTítulo en edición local (se persiste con debounce)
savingbooleanIndica si hay un auto-save en curso
savedAtnumberTimestamp del último save (mostrado en Toolbar)
editorViewEditorView | nullReferencia al editor CodeMirror activo
viewMode'source' | 'split' | 'preview'Modo de visualización activo, persistido en localStorage
liveDocstringSnapshot del documento actualizado en cada keystroke para el preview

Flujo de auto-save

keystroke → updateListener (docChanged)
  → setLiveDoc(content)           ← inmediato (para el preview)
  → clearTimeout + setTimeout(1s) ← debounce
      → setSaving(true)
      → onPersist({ content, word_count })
      → setSaving(false), setSavedAt(Date.now())

El título tiene su propio debounce independiente vía titleTimer.

Integración con CodeMirror

La instancia de EditorView se crea en un useEffect que monta el editor en containerRef. La configuración incluye:

  • markdown + markdownLanguage (lang-markdown)
  • buildMarkdownTheme() — tema visual configurable
  • syntaxHighlighting, bracketMatching, closeBrackets
  • lineNumbers, highlightActiveLine, drawSelection
  • searchKeymap, closeBracketsKeymap

El editor se destruye y recrea cuando cambia note.id (cambio de nota activa).

Renderizado de preview

Cuando viewMode !== 'source', el useMemo de previewHtml ejecuta marked.parse(liveDoc, { async: false }). El HTML resultante se inyecta en .cuaderno-preview vía dangerouslySetInnerHTML. Ver [[feature—cuaderno—vista-previa-toggle]] para detalles completos.

Layout condicional

<div className={`cuaderno-view cuaderno-view-${viewMode}`}>
  {viewMode !== 'preview' && <div ref={containerRef} className="cuaderno-cm-container" />}
  {viewMode !== 'source'  && <div className="cuaderno-preview" dangerouslySetInnerHTML=... />}
</div>

Componentes hijos

ComponenteRol
ToolbarBarra de herramientas: inserciones MD, pin, archivo, tema, toggle de modo

Consideraciones

  • SSR safety: viewMode usa un lazy initializer que guarda con typeof window === 'undefined' para evitar errores en SSR/build.
  • Key note.id: al cambiar de nota, liveDoc se reinicia con note.content en el useEffect que observa [note.id, note.title, note.content].

Véase también

  • [[feature—cuaderno—vista-previa-toggle]]
  • [[entity—cuaderno—component—toolbar]]
  • [[workspace—que-es-workspace]]
  • [[workspace—tareas-notas]]
  • [[workspace—informes]]