Web Components Basics¶
The @sciflow/editor-start package registers two custom elements:
| Element | Purpose |
|---|---|
<sciflow-editor> |
The full ProseMirror-powered editor surface. |
<sciflow-formatbar> |
Optional toolbar that issues editor commands. |
This chapter covers loading the bundle, understanding attributes and events, wiring the toolbar, and applying theme tokens.
Loading the Bundle¶
<script type="module" src="/node_modules/@sciflow/editor-start/dist/bundle/sciflow-editor.js"></script>
Self-host or CDN
For production builds you can copy the emitted bundle to your own CDN. The file is an ES module and can be tree-shaken by modern bundlers.
Core Properties¶
| Property | Type | Description |
|---|---|---|
doc |
SciFlowDocJSON \| null |
Sets the full document snapshot. Assign a new object to replace the content. |
initialContent |
ProseMirrorNode \| null |
Alternative way to seed the document with a ProseMirror node. |
placeholder |
string |
Placeholder string shown when the document is empty. |
headingText |
string |
Display heading for the built-in default document template. |
commands (getter) |
CommandRunner \| null |
Provides immediate commands plus flow helpers. |
editorView (getter) |
EditorView \| null |
Gives you direct access to ProseMirror for advanced use cases. |
Events¶
| Event | Fired when | Detail payload |
|---|---|---|
editor-ready |
Editor has mounted and commands/views become available. | { editor: SciFlowEditorElement } |
editor-change |
Document content changes. | { doc: SciFlowDocJSON, operations: Operation[] } |
editor-selection-change |
Selection/cursor changes. | { anchor: number, head: number } |
All events bubble across the shadow boundary so you can attach listeners to parent components or frameworks.
editor.addEventListener('editor-change', (event) => {
const { doc } = event.detail;
saveDraft(doc);
});
Connecting the Format Bar¶
1. Declarative (for attribute)¶
The toolbar auto-discovers the editor with that id once both elements are in the DOM.
2. Programmatic¶
const toolbar = document.querySelector('sciflow-formatbar');
const editor = document.querySelector('sciflow-editor');
editor.addEventListener('editor-ready', () => {
toolbar.editor = editor;
}, { once: true });
Material Symbols required
The toolbar uses Material Symbols. Include the font in your <head>:
Issuing Commands¶
const runner = editor.commands;
if (runner) {
runner.commands.focus();
runner.commands.insertText('Hello, world!');
runner.flow().toggleMark('strong').insertText(' bold text').run();
}
Use runner.available() to check capabilities before toggling marks or nodes.
Lists & Blockquotes¶
The list and blockquote features expose familiar commands that mirror the ProseMirror examples. Once those features are enabled (they are toggled on in the demo), you can drive them like any other command:
const commands = editor.commands?.commands;
// Toggle bullet/ordered lists
commands?.toggleBulletList?.();
commands?.toggleOrderedList?.();
// Nest or lift list items
commands?.sinkListItem?.();
commands?.liftListItem?.();
// Wrap/unwrap blockquotes
commands?.toggleBlockquote?.();
Each command returns true on success, so you can wire them into toolbars or keyboard shortcuts as needed.
Styling & Layout¶
- The editor exposes CSS custom properties such as
--sciflow-editor-borderand--sciflow-editor-focus-ring. Override them on the host element to match your design system. - Wrap the component inside any layout container; it behaves like a block element that expands to the width of its parent.
Keyboard focus
Call runner.commands.focus() after programmatic updates (e.g., clicking entries in your own outline) so screen readers and caret navigation keep working.
Custom Events & Integrations¶
The demo shows how to:
- Mirror the selection into a reference sidebar via
editor-selection-change. - Dispatch navigation requests (outline clicks →
commands.setSelection). - Drive custom insertions (
commands.insertFigure,commands.insertCitation).
Refer to the Customization Recipes for full walk-throughs.