CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-prosemirror-view

ProseMirror's view component that manages DOM structure and user interactions for rich text editing

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

index.mddocs/

ProseMirror View

ProseMirror's view component provides the DOM rendering and user interaction layer for rich text editors. It manages the DOM representation of documents, handles user input and events, and offers extensible APIs for custom node and mark rendering. The view bridges ProseMirror's abstract document model with the browser's contentEditable interface.

Package Information

  • Package Name: prosemirror-view
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install prosemirror-view

Core Imports

import { EditorView } from "prosemirror-view";

For decorations:

import { Decoration, DecorationSet } from "prosemirror-view";

For custom views:

import { NodeView, MarkView } from "prosemirror-view";

Basic Usage

import { EditorView } from "prosemirror-view";
import { EditorState } from "prosemirror-state";
import { Schema, DOMParser } from "prosemirror-model";
import { exampleSetup } from "prosemirror-example-setup";

// Create editor state
const schema = new Schema({
  nodes: {
    doc: { content: "paragraph+" },
    paragraph: { content: "text*", toDOM: () => ["p", 0] },
    text: {}
  }
});

const state = EditorState.create({
  schema,
  plugins: exampleSetup({ schema })
});

// Create editor view
const view = new EditorView(document.querySelector("#editor"), {
  state,
  dispatchTransaction(tr) {
    view.updateState(view.state.apply(tr));
  }
});

// Focus the editor
view.focus();

// Get position from coordinates
const pos = view.posAtCoords({ left: 100, top: 50 });
if (pos) {
  console.log("Document position:", pos.pos);
}

Architecture

ProseMirror View is built around several key components:

  • EditorView: Central class managing DOM structure and user interactions
  • Decoration System: Visual decorations for styling and annotations (widgets, inline, node)
  • Custom Views: Extensible NodeView and MarkView interfaces for custom rendering
  • Input Handling: Comprehensive event processing including keyboard, mouse, and composition
  • Coordinate Mapping: Bidirectional position conversion between document and DOM
  • DOM Observer: Change detection and state synchronization
  • Cross-browser Support: Unified behavior across different browsers and platforms

Capabilities

Core Editor View

The main EditorView class that manages the DOM structure representing an editable document and handles user interactions.

class EditorView {
  constructor(
    place: null | DOMNode | ((editor: HTMLElement) => void) | {mount: HTMLElement},
    props: DirectEditorProps
  );
  
  readonly state: EditorState;
  readonly dom: HTMLElement;
  readonly editable: boolean;
  readonly dragging: null | {slice: Slice, move: boolean};
  readonly composing: boolean;
  readonly props: DirectEditorProps;
  readonly root: Document | ShadowRoot;
  
  update(props: DirectEditorProps): void;
  setProps(props: Partial<DirectEditorProps>): void;
  updateState(state: EditorState): void;
  focus(): void;
  hasFocus(): boolean;
  destroy(): void;
  dispatch(tr: Transaction): void;
}

Core Editor View

Decoration System

Visual decorations that can be applied to document content for styling, annotations, and interactive elements.

class Decoration {
  readonly from: number;
  readonly to: number;
  readonly spec: any;
  
  static widget(pos: number, toDOM: WidgetConstructor, spec?: object): Decoration;
  static inline(from: number, to: number, attrs: DecorationAttrs, spec?: object): Decoration;
  static node(from: number, to: number, attrs: DecorationAttrs, spec?: object): Decoration;
}

class DecorationSet {
  static empty: DecorationSet;
  static create(doc: Node, decorations: readonly Decoration[]): DecorationSet;
  
  find(start?: number, end?: number, predicate?: (spec: any) => boolean): Decoration[];
  map(mapping: Mappable, doc: Node, options?: {onRemove?: (decorationSpec: any) => void}): DecorationSet;
  add(doc: Node, decorations: readonly Decoration[]): DecorationSet;
  remove(decorations: readonly Decoration[]): DecorationSet;
}

Decoration System

Custom Node and Mark Views

Extensible interfaces for custom rendering of document nodes and marks.

interface NodeView {
  dom: DOMNode;
  contentDOM?: HTMLElement | null;
  update?(node: Node, decorations: readonly Decoration[], innerDecorations: DecorationSource): boolean;
  selectNode?(): void;
  deselectNode?(): void;
  setSelection?(anchor: number, head: number, root: Document | ShadowRoot): void;
  stopEvent?(event: Event): boolean;
  ignoreMutation?(mutation: ViewMutationRecord): boolean;
  destroy?(): void;
}

interface MarkView {
  dom: DOMNode;
  contentDOM?: HTMLElement | null;
  ignoreMutation?(mutation: ViewMutationRecord): boolean;
  destroy?(): void;
}

Custom Views

Position and Coordinate Mapping

Utilities for converting between document positions and DOM coordinates.

class EditorView {
  posAtCoords(coords: {left: number, top: number}): {pos: number, inside: number} | null;
  coordsAtPos(pos: number, side?: number): {left: number, right: number, top: number, bottom: number};
  domAtPos(pos: number, side?: number): {node: DOMNode, offset: number};
  nodeDOM(pos: number): DOMNode | null;
  posAtDOM(node: DOMNode, offset: number, bias?: number): number;
  endOfTextblock(dir: "up" | "down" | "left" | "right" | "forward" | "backward", state?: EditorState): boolean;
}

Position Mapping

Editor Props and Configuration

Comprehensive configuration system for customizing editor behavior and handling events.

interface EditorProps<P = any> {
  handleDOMEvents?: {[event in keyof DOMEventMap]?: (this: P, view: EditorView, event: DOMEventMap[event]) => boolean | void};
  handleKeyDown?(this: P, view: EditorView, event: KeyboardEvent): boolean | void;
  handleTextInput?(this: P, view: EditorView, from: number, to: number, text: string, deflt: () => Transaction): boolean | void;
  handleClick?(this: P, view: EditorView, pos: number, event: MouseEvent): boolean | void;
  handlePaste?(this: P, view: EditorView, event: ClipboardEvent, slice: Slice): boolean | void;
  handleDrop?(this: P, view: EditorView, event: DragEvent, slice: Slice, moved: boolean): boolean | void;
  
  nodeViews?: {[node: string]: NodeViewConstructor};
  markViews?: {[mark: string]: MarkViewConstructor};
  decorations?(this: P, state: EditorState): DecorationSource | null | undefined;
  editable?(this: P, state: EditorState): boolean;
  attributes?: {[name: string]: string} | ((state: EditorState) => {[name: string]: string});
}

interface DirectEditorProps extends EditorProps {
  state: EditorState;
  plugins?: readonly Plugin[];
  dispatchTransaction?(tr: Transaction): void;
}

Editor Props

Input and Event Handling

Comprehensive input processing including keyboard events, mouse interactions, clipboard operations, and composition input.

class EditorView {
  pasteHTML(html: string, event?: ClipboardEvent): boolean;
  pasteText(text: string, event?: ClipboardEvent): boolean;
  serializeForClipboard(slice: Slice): {dom: HTMLElement, text: string, slice: Slice};
  dispatchEvent(event: Event): boolean;
}

Input Handling

Types

type NodeViewConstructor = (
  node: Node,
  view: EditorView,
  getPos: () => number | undefined,
  decorations: readonly Decoration[],
  innerDecorations: DecorationSource
) => NodeView;

type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => MarkView;

type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;

type DecorationAttrs = {
  nodeName?: string;
  class?: string;
  style?: string;
  [attribute: string]: string | undefined;
};

type ViewMutationRecord = MutationRecord | { type: "selection", target: DOMNode };

interface DOMEventMap extends HTMLElementEventMap {
  [event: string]: any;
}

interface DecorationSource {
  map(mapping: Mapping, node: Node): DecorationSource;
  forChild(offset: number, child: Node): DecorationSource;
  locals(node: Node): readonly Decoration[];
  eq(other: DecorationSource): boolean;
  forEachSet(f: (set: DecorationSet) => void): void;
}

Install with Tessl CLI

npx tessl i tessl/npm-prosemirror-view

docs

core-editor-view.md

custom-views.md

decoration-system.md

editor-props.md

index.md

input-handling.md

position-mapping.md

tile.json