171 lines
5.1 KiB
TypeScript
171 lines
5.1 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useRef, useState, type ReactNode } from "react"
|
|
import type { Editor } from "@tiptap/react"
|
|
import { DocsPageView } from "@/components/drive/richtext/docs-page-view"
|
|
import {
|
|
DocsRulerToolbarRow,
|
|
DocsRulersLeftRail,
|
|
} from "@/components/drive/richtext/docs-rulers-chrome"
|
|
import type { DocPageLayout } from "@/lib/drive/doc-page-setup"
|
|
import { DOCS_VERTICAL_RULER_WIDTH_PX } from "@/lib/drive/docs-page-layout-constants"
|
|
import { docsZoomToScale } from "@/lib/drive/docs-ruler-scale"
|
|
import { useDocsRulerSync } from "@/lib/drive/use-docs-ruler-sync"
|
|
import { useDocsRulerMarginDrag } from "@/components/drive/richtext/use-docs-ruler-margin-drag"
|
|
import { DocsRulerMarginDragTooltip } from "@/components/drive/richtext/docs-ruler-markers"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
export function DocsEditorWorkspace({
|
|
editor,
|
|
pageLayout,
|
|
zoom,
|
|
editable,
|
|
showLayout,
|
|
showRuler,
|
|
showNonPrintableChars,
|
|
editorMode,
|
|
outlineExpanded,
|
|
onToggleOutline,
|
|
onPageCountChange,
|
|
onCurrentPageChange,
|
|
toolbar,
|
|
toolbarShellClassName,
|
|
onRegionContentChange,
|
|
onPageSetupChange,
|
|
onRegionEditorChange,
|
|
}: {
|
|
editor: Editor
|
|
pageLayout: DocPageLayout
|
|
zoom: number
|
|
editable: boolean
|
|
showLayout: boolean
|
|
showRuler: boolean
|
|
showNonPrintableChars: boolean
|
|
editorMode: "edit" | "suggest" | "view"
|
|
outlineExpanded?: boolean
|
|
onToggleOutline?: () => void
|
|
onPageCountChange?: (count: number) => void
|
|
onCurrentPageChange?: (page: number) => void
|
|
toolbar?: ReactNode
|
|
toolbarShellClassName?: string
|
|
onRegionContentChange?: (
|
|
region: "header" | "footer",
|
|
content: Record<string, unknown>,
|
|
meta: { pageIndex: number; contentHeightPx: number }
|
|
) => void
|
|
onPageSetupChange?: (
|
|
patch: Partial<import("@/lib/drive/doc-page-setup").DocPageSetup>,
|
|
options?: { immediate?: boolean }
|
|
) => void
|
|
onRegionEditorChange?: (editor: import("@tiptap/react").Editor | null) => void
|
|
}) {
|
|
const canvasRef = useRef<HTMLDivElement>(null)
|
|
const rulerTrackRef = useRef<HTMLDivElement>(null)
|
|
const [pageCount, setPageCount] = useState(1)
|
|
const [narrowViewport, setNarrowViewport] = useState(false)
|
|
|
|
const rulersVisible = showLayout && showRuler
|
|
const scale = docsZoomToScale(zoom)
|
|
const showToolbarShell = Boolean(toolbar) || rulersVisible
|
|
const marginsEditable = editable && editorMode !== "view"
|
|
|
|
const {
|
|
pageLayoutWithMargins,
|
|
beginMarginDrag,
|
|
moveMarginDrag,
|
|
endMarginDrag,
|
|
dragTooltip,
|
|
} = useDocsRulerMarginDrag({
|
|
pageLayout,
|
|
editable: marginsEditable,
|
|
onPageSetupChange,
|
|
})
|
|
|
|
const rulerSync = useDocsRulerSync({
|
|
canvasRef,
|
|
rulerTrackRef,
|
|
editor,
|
|
pageLayout: pageLayoutWithMargins,
|
|
zoom,
|
|
pageCount,
|
|
narrowViewport,
|
|
})
|
|
|
|
useEffect(() => {
|
|
onCurrentPageChange?.(rulerSync.currentPage + 1)
|
|
}, [onCurrentPageChange, rulerSync.currentPage])
|
|
|
|
return (
|
|
<div className="docs-editor-workspace flex min-h-0 flex-1 flex-col">
|
|
<DocsRulerMarginDragTooltip tooltip={dragTooltip} />
|
|
{showToolbarShell ? (
|
|
<div
|
|
className={cn(
|
|
"docs-toolbar-shell shrink-0",
|
|
toolbarShellClassName
|
|
)}
|
|
>
|
|
{toolbar}
|
|
{rulersVisible ? (
|
|
<DocsRulerToolbarRow
|
|
pageLayout={pageLayoutWithMargins}
|
|
scale={scale}
|
|
rulerSync={rulerSync}
|
|
rulerTrackRef={rulerTrackRef}
|
|
outlineExpanded={outlineExpanded}
|
|
onToggleOutline={onToggleOutline}
|
|
editable={marginsEditable}
|
|
onMarginDragStart={beginMarginDrag}
|
|
onMarginDrag={moveMarginDrag}
|
|
onMarginDragEnd={endMarginDrag}
|
|
/>
|
|
) : null}
|
|
</div>
|
|
) : null}
|
|
|
|
<div className="relative min-h-0 flex-1 overflow-hidden">
|
|
{rulersVisible ? (
|
|
<DocsRulersLeftRail
|
|
pageLayout={pageLayoutWithMargins}
|
|
scale={scale}
|
|
rulerSync={rulerSync}
|
|
editable={marginsEditable}
|
|
onMarginDragStart={beginMarginDrag}
|
|
onMarginDrag={moveMarginDrag}
|
|
onMarginDragEnd={endMarginDrag}
|
|
/>
|
|
) : null}
|
|
|
|
<div
|
|
className="flex h-full min-h-0 flex-col"
|
|
style={
|
|
rulersVisible
|
|
? { paddingLeft: DOCS_VERTICAL_RULER_WIDTH_PX }
|
|
: undefined
|
|
}
|
|
>
|
|
<DocsPageView
|
|
editor={editor}
|
|
pageLayout={pageLayoutWithMargins}
|
|
zoom={zoom}
|
|
editable={editable}
|
|
showLayout={showLayout}
|
|
showRuler={false}
|
|
showNonPrintableChars={showNonPrintableChars}
|
|
editorMode={editorMode}
|
|
canvasRef={canvasRef}
|
|
onPageCountChange={(count) => {
|
|
setPageCount(count)
|
|
onPageCountChange?.(count)
|
|
}}
|
|
onNarrowViewportChange={setNarrowViewport}
|
|
onRegionContentChange={onRegionContentChange}
|
|
onPageSetupChange={onPageSetupChange}
|
|
onRegionEditorChange={onRegionEditorChange}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|