edix
Version:
An experimental, type-safe, framework agnostic and small (5kB+) contenteditable state manager.
107 lines (106 loc) • 3.39 kB
TypeScript
import type { StandardSchemaV1 } from "@standard-schema/spec";
import type { DocNode, SelectionSnapshot } from "./doc/types.js";
import type { EditorCommand } from "./commands.js";
import { Transaction, type Operation } from "./doc/edit.js";
import type { EditorPlugin } from "./plugins/types.js";
import { type CopyHook, type PasteHook, type KeyboardHook } from "./hooks/index.js";
/**
* Options of {@link createEditor}.
*/
export interface EditorOptions<T extends DocNode, S extends StandardSchemaV1<T, T> | void = void> {
/**
* Optional [Standard Schema](https://github.com/standard-schema/standard-schema) to validate unsafe edits.
*/
schema?: S;
/**
* Initial document.
*/
doc: T;
/**
* The state editable or not.
*/
readonly?: boolean;
/**
* Functions to handle keyboard events.
*
* Return `true` if you want to stop propagation.
*/
keyboard?: KeyboardHook[];
/**
* Functions to handle copy events
* @default [plainCopy()]
*/
copy?: [CopyHook, ...rest: CopyHook[]];
/**
* Functions to handle paste / drop events
* @default [plainPaste()]
*/
paste?: [PasteHook, ...rest: PasteHook[]];
/**
* TODO
*/
isBlock?: (node: HTMLElement) => boolean;
/**
* Callback invoked when document changes.
*/
onChange: (doc: T) => void;
/**
* Callback invoked when errors happen.
*
* @default console.error
*/
onError?: (message: string) => void;
}
type EditorEventMap = {
change: () => void;
selectionchange: () => void;
readonly: () => void;
};
type EditorHookMap = {
apply: (op: Operation, next: (op?: Operation) => void) => void;
mount: (element: HTMLElement) => void | (() => void);
keyboard: KeyboardHook;
};
/**
* The editor instance.
*/
export interface Editor<T extends DocNode = DocNode> {
readonly doc: T;
readonly selection: SelectionSnapshot;
/**
* The getter/setter for the editor's read-only state.
* `true` to read-only. `false` to editable.
*/
readonly: boolean;
/**
* Dispatches editing operations.
* @param tr {@link Transaction} or {@link EditorCommand}
* @param args arguments of {@link EditorCommand}
*/
apply(tr: Transaction): this;
apply<A extends unknown[]>(fn: EditorCommand<A, T>, ...args: A): this;
/**
* A function to subscribe editor events.
* @returns cleanup function
*/
on<K extends keyof EditorEventMap>(key: K, callback: EditorEventMap[K]): () => void;
/**
* A function to register editor hooks.
* @returns cleanup function
*/
hook<K extends keyof EditorHookMap>(key: K, callback: EditorHookMap[K]): () => void;
/**
* A function to make DOM editable.
* @returns A function to stop subscribing DOM changes and restores previous DOM state.
*/
input: (element: HTMLElement) => () => void;
/**
* A function to use editor plugins.
*/
use<A extends unknown[]>(fn: EditorPlugin<A, T>, ...args: A): this;
}
/**
* A function to initialize {@link Editor}.
*/
export declare const createEditor: <T extends DocNode, S extends StandardSchemaV1<T, T> | void = void>({ doc, readonly, schema, keyboard, copy: copyHooks, paste: pasteHooks, isBlock, onChange, onError, }: EditorOptions<T, S>) => Editor<T>;
export {};