Entidadactivecreado Fri May 08#cuaderno#workspace#react#codemirror#markdown#frontend#editor#autosave
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
| Prop | Tipo | Descripción |
|---|---|---|
note | NotebookNote | Nota 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 | () => void | Abre el panel de selección de tema MD |
Estado interno relevante
| Estado | Tipo | Descripción |
|---|---|---|
title | string | Título en edición local (se persiste con debounce) |
saving | boolean | Indica si hay un auto-save en curso |
savedAt | number | Timestamp del último save (mostrado en Toolbar) |
editorView | EditorView | null | Referencia al editor CodeMirror activo |
viewMode | 'source' | 'split' | 'preview' | Modo de visualización activo, persistido en localStorage |
liveDoc | string | Snapshot 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 configurablesyntaxHighlighting,bracketMatching,closeBracketslineNumbers,highlightActiveLine,drawSelectionsearchKeymap,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
| Componente | Rol |
|---|---|
Toolbar | Barra de herramientas: inserciones MD, pin, archivo, tema, toggle de modo |
Consideraciones
- SSR safety:
viewModeusa un lazy initializer que guarda contypeof window === 'undefined'para evitar errores en SSR/build. - Key
note.id: al cambiar de nota,liveDocse reinicia connote.contenten eluseEffectque 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]]