Automerge backed Markdown editor for the Atmosphere
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182// src/layout/MainAreaViewContainer.tsximport { Profiler, useContext, useEffect, useMemo, useRef } from 'react'import type { App } from '../plugin/app'import type { WorkspaceLeaf } from '../plugin/workspace'import { isReactItemView, type ReactItemView } from '../plugin/views/item-view'import { useActiveLeaf } from './hooks/useActiveLeaf'import { onRenderProfiler } from '../lib/perf-profile'import { MainAreaContext } from './MainAreaContext'import './MainAreaViewContainer.css'
/** * Generic per-leaf renderer for the main editor area. Mirrors * `SidebarViewContainer.LeafMount`: * - When the active leaf hosts a `ReactItemView`, render * `view.getReactComponent()` inline (preserves React context). * - Otherwise mount `view.containerEl` into the wrapper via an effect. * * The wrapper carries `data-reams-view="<viewType>"` so invariant tests and * QA can identify the currently mounted view without inspecting view * internals. * * @internal Host-internal infrastructure for content-type routing (#406). */export function MainAreaViewContainer({ app }: { app: App }) { const activeLeaf = useActiveLeaf(app.workspace)
if (!activeLeaf || !activeLeaf.view) { return ( <div className="app-shell-empty"> Open a document to start editing </div> ) } return ( <Profiler id="MainAreaViewContainer" onRender={onRenderProfiler}> <LeafMount leaf={activeLeaf} /> </Profiler> )}
/** @internal Exported for tests; mounts a single leaf's view per the rules described above. */export function LeafMount({ leaf }: { leaf: WorkspaceLeaf }) { const onInitialViewReady = useContext(MainAreaContext)?.onInitialViewReady // Mirror SidebarViewContainer.LeafMount: hooks run unconditionally and // guard inside their bodies, so a leaf whose `view` transitions to null // mid-lifecycle never changes the hook count between renders. const containerRef = useRef<HTMLDivElement>(null) const view = leaf.view const isReact = view != null && isReactItemView(view) const reactComponent = useMemo( () => (isReact ? (view as unknown as ReactItemView).getReactComponent() : null), [view, isReact, leaf.file], )
useEffect(() => { const el = containerRef.current if (!el || !view || reactComponent) return el.appendChild(view.containerEl) return () => { if (el.contains(view.containerEl)) { el.removeChild(view.containerEl) } } }, [view, reactComponent])
useEffect(() => { if (view && view.getViewType() !== 'markdown') onInitialViewReady?.(leaf) }, [leaf, leaf.file, view, onInitialViewReady])
if (!view) return null
return ( <div ref={containerRef} className="main-area-leaf" data-reams-view={view.getViewType()} > {reactComponent} </div> )}