@bendyline/squisq-editor-react
v2.12.3
Published
React editor shell with raw/WYSIWYG/preview modes for Squisq documents
Maintainers
Readme
@bendyline/squisq-editor-react
React editor shell for Squisq documents with three integrated views: a Monaco-powered raw Markdown editor, a Tiptap WYSIWYG rich text editor, and a live block preview. Switching between views keeps the document in sync automatically.
Part of the Squisq monorepo.
Install
npm install @bendyline/squisq-editor-react @bendyline/squisq @bendyline/squisq-react monaco-editorPeer dependencies: react and react-dom (v18 or v19), plus
monaco-editor (~0.50.0). Monaco is loaded lazily at runtime, but it is a
required peer because the package's public TypeScript declarations expose
Monaco editor types. Tiptap is bundled as a regular dependency — you don't
need to install it yourself.
Quick Start
import { EditorShell } from '@bendyline/squisq-editor-react';
import '@bendyline/squisq-editor-react/styles';
function App() {
return <EditorShell initialMarkdown="# Hello World" />;
}Editor Views
| View | Powered By | Description | | ----------- | ------------- | ----------------------------------------------------- | | Raw | Monaco Editor | Full Markdown source editing with syntax highlighting | | WYSIWYG | Tiptap | Rich text editing with a formatting toolbar | | Preview | DocPlayer | Live rendered block preview with theme selection |
Components
| Component | Description |
| ---------------------------------------------------- | ---------------------------------------------------------------- |
| EditorShell | Top-level editor — combines all three views with a view switcher |
| EditorProvider | Context provider for editor state management |
| RawEditor / WysiwygEditor / PreviewPanel | The individual views, exported for custom layouts |
| JsonEditor | Editable form for JSON values bound to a Squisq-annotated schema |
| ImageEditor / ImageViewer | Layered raster authoring surface + read-only viewer |
| RecorderPanel / RecorderButton / RecorderModal | Browser audio/camera/screen recording (MediaRecorder) |
| FolderView | Standalone folder browser surface |
Beyond components, the package also exports Tiptap extensions for authored
ASCII diagrams, trees, and timelines. Timeline fences become a shared-scale
rail canvas in WYSIWYG mode: click the line or a keyboard-accessible Add button
to add a point, select any dot to edit its label/callout, and keep multiple
tracks and branches visible. Every safe edit is written back as regenerated,
verified fence text, so Raw Markdown stays the source of truth; visual mutation
pauses if unmodeled source would be lost. The package also exports heading template annotations, the markdown ↔ Tiptap bridge
(markdownToTiptap / tiptapToMarkdown), drag-and-drop helpers
(useFileDrop, processMediaFiles), file-kind detection (resolveFileKind),
and block-at-a-time / timeline editing primitives (useBlockNavigator,
BlockCardView, TimelineTrack).
Notable EditorShell features
- Versioning — pass
allowVersioning+workspaceContainerto auto-save snapshots on idle (versioningAutoSaveIdleMs, default 5000ms) with pruning (versioningPrunePolicy, default keep-last-50); a Version History panel appears in the toolbar. - Recording — with a
mediaProviderwired, a record button appears in the toolbar (allowRecording, defaulttrue). Screen capture exposes What to record above Advanced settings: a surface preference, a screen/window picker action, and whole-surface or coordinate-region capture. Coordinates are pixels relative to the chosen surface's top-left; the live preview and encoded video use the same crop, leaving audio unchanged. Invalid or out-of-bounds regions fail visibly and release capture. Region recording uses a canvas at 30 fps; shrinking a window past the region or stopping screen sharing ends the take. The browser or host still owns the source picker and available surface types. The recorder's Advanced device settings expando discovers microphones/cameras, shows only capture constraints advertised by the browser, separates camera and screen constraints for dual recordings, and exposes MediaRecorder codec, bitrate, and keyframe hints. Preferred constraints use the closest available setting; Required microphone/camera constraints fail when the selected input cannot satisfy them (screen settings remain preferences, as required bygetDisplayMedia). - Presentation mode — every Use view can fill the Squisq control, open a synchronized audience window, or take over the entire screen. Slideshow/video playback, Page/Document scrolling, and the Narrate surface remain linked to the main view.
- Flashcards mode — the Use menu can project the original nested block tree
as progressively revealed study cards and multiple-choice quizzes. Ordinary
headings are inferred automatically;
{study=flashcard}disambiguates a card boundary and{study=multiple-choice-flashcard}makes child one the question, child two the default correct answer, and remaining children distractors. - Panels —
outline(heading outline pane) andinlinePreview(per-block SVG preview gutter,inlinePreviewWidthdefault 320). - Code & image modes — pass
fileName/languageto get a Monaco-only code editor, orimageSrc(+imageMode: 'edit') for the image surface..jsoncfiles,language="jsonc", and fencedjsoncsnippets use JSON highlighting with line and block comment support. - Host-triggered Find mode — control
findModeandonFindModeChange(or callsetFindModefrom context) to replace the toolbar's editing actions with live search, Match case / Whole word, previous/next navigation, highlighted matches, and Replace / Replace all in editable documents.findRequestopens Find at a given query and match;findShortcutopts in to Ctrl/Cmd+F and Ctrl+H (Cmd+Option+F on Apple). No Find trigger button is added unless the host supplies one. - Embedding —
readOnly,placeholder,submitOnEnter,fullWidth,thinMargins,minHeight/maxHeightauto-grow for chat-composer use, plus host-controlled Write typography throughwriteCanvasSettings(textSizeandlineSpacing). SethostMode="chat"to keep the shell in Write view, remove its view tabs, and hide Custom layouts, Transform, View options, and Document settings.showCodeCopyButtonopts Document/Page previews into a subtle fenced-code Copy control; useonCopyCodeto bridge clipboard writes in Electron or native hosts (browser hosts fall back tonavigator.clipboard.writeText). - Color scheme — pass
colorScheme="light" | "dark"for the editor chrome (v1.5: renamed from the oldthemeprop;RawEditor's ownthemeprop is nowmonacoTheme).
Also exported (v1.5): useMonacoLoader (share the load-once Monaco bootstrap),
and the custom theme / template provider stacks — CustomThemeProvider /
useCustomThemes / useDocCustomThemes and CustomTemplateProvider /
useCustomTemplates / useDocCustomTemplates.
Context API
Use useEditorContext() to access editor state and actions from child
components. The context value is flat — state fields and action methods live
side by side:
import { useEditorContext } from '@bendyline/squisq-editor-react';
function MyComponent() {
const { markdownSource, doc, activeView, setMarkdownSource, setActiveView, setFindMode } =
useEditorContext();
// markdownSource: string, doc: Doc | null, activeView: 'raw' | 'wysiwyg' | 'preview'
}Styles
Import the editor CSS:
import '@bendyline/squisq-editor-react/styles';Full API Reference
See docs/API.md
for the complete EditorShellProps reference, context API, and every exported
component, hook, and helper.
Related Packages
| Package | Description | | ------------------------------------------------------------------------------------ | -------------------------------------------------------------- | | @bendyline/squisq | Headless core — schemas, templates, spatial, markdown, storage | | @bendyline/squisq-react | React components for rendering docs | | @bendyline/squisq-formats | DOCX, PDF, HTML import/export |
