/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */
import type { EditorState, SerializedEditorState } from './LexicalEditorState';
import type { DOMConversion, DOMConversionMap, DOMExportOutput, DOMExportOutputMap, NodeKey } from './LexicalNode';
import { LexicalNode } from './LexicalNode';
import { SharedNodeState } from './LexicalNodeState';
import { UpdateTag } from './LexicalUpdateTags';
export type Spread<T1, T2> = Omit<T2, keyof T1> & T1;
export type KlassConstructor<Cls extends GenericConstructor<any>> = GenericConstructor<InstanceType<Cls>> & {
    [k in keyof Cls]: Cls[k];
};
type GenericConstructor<T> = new (...args: any[]) => T;
export type Klass<T extends LexicalNode> = InstanceType<T['constructor']> extends T ? T['constructor'] : GenericConstructor<T> & T['constructor'];
export type EditorThemeClassName = string;
export type TextNodeThemeClasses = {
    base?: EditorThemeClassName;
    bold?: EditorThemeClassName;
    code?: EditorThemeClassName;
    highlight?: EditorThemeClassName;
    italic?: EditorThemeClassName;
    lowercase?: EditorThemeClassName;
    uppercase?: EditorThemeClassName;
    capitalize?: EditorThemeClassName;
    strikethrough?: EditorThemeClassName;
    subscript?: EditorThemeClassName;
    superscript?: EditorThemeClassName;
    underline?: EditorThemeClassName;
    underlineStrikethrough?: EditorThemeClassName;
    [key: string]: EditorThemeClassName | undefined;
};
export type EditorUpdateOptions = {
    /**
     * A function to run once the update is complete. See also {@link $onUpdate}.
     */
    onUpdate?: () => void;
    /**
     * Setting this to true will suppress all node
     * transforms for this update cycle.
     * Useful for synchronizing updates in some cases.
     */
    skipTransforms?: true;
    /**
     * A tag to identify this update, in an update listener, for instance.
     * See also {@link $addUpdateTag}.
     */
    tag?: UpdateTag | UpdateTag[];
    /**
     * If true, prevents this update from being batched, forcing it to
     * run synchronously.
     */
    discrete?: true;
    /** @internal */
    event?: undefined | UIEvent | Event | null;
};
export type EditorSetOptions = {
    tag?: string;
};
export interface EditorFocusOptions {
    /**
     * Where to move selection when the editor is
     * focused. Can be rootStart, rootEnd, or undefined. Defaults to rootEnd.
     */
    defaultSelection?: 'rootStart' | 'rootEnd';
}
export type EditorThemeClasses = {
    blockCursor?: EditorThemeClassName;
    characterLimit?: EditorThemeClassName;
    code?: EditorThemeClassName;
    codeHighlight?: Record<string, EditorThemeClassName>;
    hashtag?: EditorThemeClassName;
    specialText?: EditorThemeClassName;
    heading?: {
        h1?: EditorThemeClassName;
        h2?: EditorThemeClassName;
        h3?: EditorThemeClassName;
        h4?: EditorThemeClassName;
        h5?: EditorThemeClassName;
        h6?: EditorThemeClassName;
    };
    hr?: EditorThemeClassName;
    hrSelected?: EditorThemeClassName;
    image?: EditorThemeClassName;
    link?: EditorThemeClassName;
    list?: {
        ul?: EditorThemeClassName;
        ulDepth?: Array<EditorThemeClassName>;
        ol?: EditorThemeClassName;
        olDepth?: Array<EditorThemeClassName>;
        checklist?: EditorThemeClassName;
        listitem?: EditorThemeClassName;
        listitemChecked?: EditorThemeClassName;
        listitemUnchecked?: EditorThemeClassName;
        nested?: {
            list?: EditorThemeClassName;
            listitem?: EditorThemeClassName;
        };
    };
    ltr?: EditorThemeClassName;
    mark?: EditorThemeClassName;
    markOverlap?: EditorThemeClassName;
    paragraph?: EditorThemeClassName;
    quote?: EditorThemeClassName;
    root?: EditorThemeClassName;
    rtl?: EditorThemeClassName;
    tab?: EditorThemeClassName;
    table?: EditorThemeClassName;
    tableAddColumns?: EditorThemeClassName;
    tableAddRows?: EditorThemeClassName;
    tableCellActionButton?: EditorThemeClassName;
    tableCellActionButtonContainer?: EditorThemeClassName;
    tableCellSelected?: EditorThemeClassName;
    tableCell?: EditorThemeClassName;
    tableCellHeader?: EditorThemeClassName;
    tableCellResizer?: EditorThemeClassName;
    tableRow?: EditorThemeClassName;
    tableScrollableWrapper?: EditorThemeClassName;
    tableSelected?: EditorThemeClassName;
    tableSelection?: EditorThemeClassName;
    text?: TextNodeThemeClasses;
    embedBlock?: {
        base?: EditorThemeClassName;
        focus?: EditorThemeClassName;
    };
    indent?: EditorThemeClassName;
    [key: string]: any;
};
export type EditorConfig = {
    disableEvents?: boolean;
    namespace: string;
    theme: EditorThemeClasses;
};
export type LexicalNodeReplacement = {
    replace: Klass<LexicalNode>;
    with: <T extends {
        new (...args: any): any;
    }>(node: InstanceType<T>) => LexicalNode;
    withKlass?: Klass<LexicalNode>;
};
export type HTMLConfig = {
    export?: DOMExportOutputMap;
    import?: DOMConversionMap;
};
/**
 * A LexicalNode class or LexicalNodeReplacement configuration
 */
export type LexicalNodeConfig = Klass<LexicalNode> | LexicalNodeReplacement;
export type CreateEditorArgs = {
    disableEvents?: boolean;
    editorState?: EditorState;
    namespace?: string;
    nodes?: ReadonlyArray<LexicalNodeConfig>;
    onError?: ErrorHandler;
    parentEditor?: LexicalEditor;
    editable?: boolean;
    theme?: EditorThemeClasses;
    html?: HTMLConfig;
};
export type RegisteredNodes = Map<string, RegisteredNode>;
export type RegisteredNode = {
    klass: Klass<LexicalNode>;
    transforms: Set<Transform<LexicalNode>>;
    replace: null | ((node: LexicalNode) => LexicalNode);
    replaceWithKlass: null | Klass<LexicalNode>;
    exportDOM?: (editor: LexicalEditor, targetNode: LexicalNode) => DOMExportOutput;
    sharedNodeState: SharedNodeState;
};
export type Transform<T extends LexicalNode> = (node: T) => void;
export type ErrorHandler = (error: Error) => void;
export type MutationListeners = Map<MutationListener, Set<Klass<LexicalNode>>>;
export type MutatedNodes = Map<Klass<LexicalNode>, Map<NodeKey, NodeMutation>>;
export type NodeMutation = 'created' | 'updated' | 'destroyed';
export interface MutationListenerOptions {
    /**
     * Skip the initial call of the listener with pre-existing DOM nodes.
     *
     * The default was previously true for backwards compatibility with <= 0.16.1
     * but this default has been changed to false as of 0.21.0.
     */
    skipInitialization?: boolean;
}
/**
 * The payload passed to an UpdateListener
 */
export interface UpdateListenerPayload {
    /**
     * A Map of NodeKeys of ElementNodes to a boolean that is true
     * if the node was intentionally mutated ('unintentional' mutations
     * are triggered when an indirect descendant is marked dirty)
     */
    dirtyElements: Map<NodeKey, IntentionallyMarkedAsDirtyElement>;
    /**
     * A Set of NodeKeys of all nodes that were marked dirty that
     * do not inherit from ElementNode.
     */
    dirtyLeaves: Set<NodeKey>;
    /**
     * The new EditorState after all updates have been processed,
     * equivalent to `editor.getEditorState()`
     */
    editorState: EditorState;
    /**
     * The Map of LexicalNode constructors to a `Map<NodeKey, NodeMutation>`,
     * this is useful when you have a mutation listener type use cases that
     * should apply to all or most nodes. Will be null if no DOM was mutated,
     * such as when only the selection changed. Note that this will be empty
     * unless at least one MutationListener is explicitly registered
     * (any MutationListener is sufficient to compute the mutatedNodes Map
     * for all nodes).
     *
     * Added in v0.28.0
     */
    mutatedNodes: null | MutatedNodes;
    /**
     * For advanced use cases only.
     *
     * Tracks the keys of TextNode descendants that have been merged
     * with their siblings by normalization. Note that these keys may
     * not exist in either editorState or prevEditorState and generally
     * this is only used for conflict resolution edge cases in collab.
     */
    normalizedNodes: Set<NodeKey>;
    /**
     * The previous EditorState that is being discarded
     */
    prevEditorState: EditorState;
    /**
     * The set of tags added with update options or {@link $addUpdateTag},
     * node that this includes all tags that were processed in this
     * reconciliation which may have been added by separate updates.
     */
    tags: Set<string>;
}
/**
 * A listener that gets called after the editor is updated
 */
export type UpdateListener = (payload: UpdateListenerPayload) => void;
export type DecoratorListener<T = never> = (decorator: Record<NodeKey, T>) => void;
export type RootListener = (rootElement: null | HTMLElement, prevRootElement: null | HTMLElement) => void;
export type TextContentListener = (text: string) => void;
export type MutationListener = (nodes: Map<NodeKey, NodeMutation>, payload: {
    updateTags: Set<string>;
    dirtyLeaves: Set<string>;
    prevEditorState: EditorState;
}) => void;
export type CommandListener<P> = (payload: P, editor: LexicalEditor) => boolean;
export type EditableListener = (editable: boolean) => void;
export type CommandListenerPriority = 0 | 1 | 2 | 3 | 4;
export declare const COMMAND_PRIORITY_EDITOR = 0;
export declare const COMMAND_PRIORITY_LOW = 1;
export declare const COMMAND_PRIORITY_NORMAL = 2;
export declare const COMMAND_PRIORITY_HIGH = 3;
export declare const COMMAND_PRIORITY_CRITICAL = 4;
export type LexicalCommand<TPayload> = {
    type?: string;
};
/**
 * Type helper for extracting the payload type from a command.
 *
 * @example
 * ```ts
 * const MY_COMMAND = createCommand<SomeType>();
 *
 * // ...
 *
 * editor.registerCommand(MY_COMMAND, payload => {
 *   // Type of `payload` is inferred here. But lets say we want to extract a function to delegate to
 *   $handleMyCommand(editor, payload);
 *   return true;
 * });
 *
 * function $handleMyCommand(editor: LexicalEditor, payload: CommandPayloadType<typeof MY_COMMAND>) {
 *   // `payload` is of type `SomeType`, extracted from the command.
 * }
 * ```
 */
export type CommandPayloadType<TCommand extends LexicalCommand<unknown>> = TCommand extends LexicalCommand<infer TPayload> ? TPayload : never;
type Commands = Map<LexicalCommand<unknown>, Array<Set<CommandListener<unknown>>>>;
export interface Listeners {
    decorator: Set<DecoratorListener<any>>;
    mutation: MutationListeners;
    editable: Set<EditableListener>;
    root: Set<RootListener>;
    textcontent: Set<TextContentListener>;
    update: Set<UpdateListener>;
}
export type SetListeners = {
    [K in keyof Listeners as Listeners[K] extends Set<(...args: any[]) => void> ? K : never]: Listeners[K] extends Set<(...args: infer Args) => void> ? Args : never;
};
export type TransformerType = 'text' | 'decorator' | 'element' | 'root';
type IntentionallyMarkedAsDirtyElement = boolean;
type DOMConversionCache = Map<string, Array<(node: Node) => DOMConversion | null>>;
export type SerializedEditor = {
    editorState: SerializedEditorState;
};
export declare function resetEditor(editor: LexicalEditor, prevRootElement: null | HTMLElement, nextRootElement: null | HTMLElement, pendingEditorState: EditorState): void;
/** @internal */
export declare function getTransformSetFromKlass(klass: KlassConstructor<typeof LexicalNode>): Set<Transform<LexicalNode>>;
/**
 * Creates a new LexicalEditor attached to a single contentEditable (provided in the config). This is
 * the lowest-level initialization API for a LexicalEditor. If you're using React or another framework,
 * consider using the appropriate abstractions, such as LexicalComposer
 * @param editorConfig - the editor configuration.
 * @returns a LexicalEditor instance
 */
export declare function createEditor(editorConfig?: CreateEditorArgs): LexicalEditor;
export declare class LexicalEditor {
    /** @internal */
    ['constructor']: KlassConstructor<typeof LexicalEditor>;
    /** The version with build identifiers for this editor (since 0.17.1) */
    static version: string | undefined;
    /** @internal */
    _headless: boolean;
    /** @internal */
    _parentEditor: null | LexicalEditor;
    /** @internal */
    _rootElement: null | HTMLElement;
    /** @internal */
    _editorState: EditorState;
    /** @internal */
    _pendingEditorState: null | EditorState;
    /** @internal */
    _compositionKey: null | NodeKey;
    /** @internal */
    _deferred: Array<() => void>;
    /** @internal */
    _keyToDOMMap: Map<NodeKey, HTMLElement>;
    /** @internal */
    _updates: Array<[() => void, EditorUpdateOptions | undefined]>;
    /** @internal */
    _updating: boolean;
    /** @internal */
    _listeners: Listeners;
    /** @internal */
    _commands: Commands;
    /** @internal */
    _nodes: RegisteredNodes;
    /** @internal */
    _decorators: Record<NodeKey, unknown>;
    /** @internal */
    _pendingDecorators: null | Record<NodeKey, unknown>;
    /** @internal */
    _config: EditorConfig;
    /** @internal */
    _dirtyType: 0 | 1 | 2;
    /** @internal */
    _cloneNotNeeded: Set<NodeKey>;
    /** @internal */
    _dirtyLeaves: Set<NodeKey>;
    /** @internal */
    _dirtyElements: Map<NodeKey, IntentionallyMarkedAsDirtyElement>;
    /** @internal */
    _normalizedNodes: Set<NodeKey>;
    /** @internal */
    _updateTags: Set<UpdateTag>;
    /** @internal */
    _observer: null | MutationObserver;
    /** @internal */
    _key: string;
    /** @internal */
    _onError: ErrorHandler;
    /** @internal */
    _htmlConversions: DOMConversionCache;
    /** @internal */
    _window: null | Window;
    /** @internal */
    _editable: boolean;
    /** @internal */
    _blockCursorElement: null | HTMLDivElement;
    /** @internal */
    _createEditorArgs?: undefined | CreateEditorArgs;
    /** @internal */
    constructor(editorState: EditorState, parentEditor: null | LexicalEditor, nodes: RegisteredNodes, config: EditorConfig, onError: ErrorHandler, htmlConversions: DOMConversionCache, editable: boolean, createEditorArgs?: CreateEditorArgs);
    /**
     *
     * @returns true if the editor is currently in "composition" mode due to receiving input
     * through an IME, or 3P extension, for example. Returns false otherwise.
     */
    isComposing(): boolean;
    /**
     * Registers a listener for Editor update event. Will trigger the provided callback
     * each time the editor goes through an update (via {@link LexicalEditor.update}) until the
     * teardown function is called.
     *
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerUpdateListener(listener: UpdateListener): () => void;
    /**
     * Registers a listener for for when the editor changes between editable and non-editable states.
     * Will trigger the provided callback each time the editor transitions between these states until the
     * teardown function is called.
     *
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerEditableListener(listener: EditableListener): () => void;
    /**
     * Registers a listener for when the editor's decorator object changes. The decorator object contains
     * all DecoratorNode keys -> their decorated value. This is primarily used with external UI frameworks.
     *
     * Will trigger the provided callback each time the editor transitions between these states until the
     * teardown function is called.
     *
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerDecoratorListener<T>(listener: DecoratorListener<T>): () => void;
    /**
     * Registers a listener for when Lexical commits an update to the DOM and the text content of
     * the editor changes from the previous state of the editor. If the text content is the
     * same between updates, no notifications to the listeners will happen.
     *
     * Will trigger the provided callback each time the editor transitions between these states until the
     * teardown function is called.
     *
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerTextContentListener(listener: TextContentListener): () => void;
    /**
     * Registers a listener for when the editor's root DOM element (the content editable
     * Lexical attaches to) changes. This is primarily used to attach event listeners to the root
     *  element. The root listener function is executed directly upon registration and then on
     * any subsequent update.
     *
     * Will trigger the provided callback each time the editor transitions between these states until the
     * teardown function is called.
     *
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerRootListener(listener: RootListener): () => void;
    /**
     * Registers a listener that will trigger anytime the provided command
     * is dispatched with {@link LexicalEditor.dispatch}, subject to priority.
     * Listeners that run at a higher priority can "intercept" commands and
     * prevent them from propagating to other handlers by returning true.
     *
     * Listeners are always invoked in an {@link LexicalEditor.update} and can
     * call dollar functions.
     *
     * Listeners registered at the same priority level will run
     * deterministically in the order of registration.
     *
     * @param command - the command that will trigger the callback.
     * @param listener - the function that will execute when the command is dispatched.
     * @param priority - the relative priority of the listener. 0 | 1 | 2 | 3 | 4
     *   (or {@link COMMAND_PRIORITY_EDITOR} |
     *     {@link COMMAND_PRIORITY_LOW} |
     *     {@link COMMAND_PRIORITY_NORMAL} |
     *     {@link COMMAND_PRIORITY_HIGH} |
     *     {@link COMMAND_PRIORITY_CRITICAL})
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerCommand<P>(command: LexicalCommand<P>, listener: CommandListener<P>, priority: CommandListenerPriority): () => void;
    /**
     * Registers a listener that will run when a Lexical node of the provided class is
     * mutated. The listener will receive a list of nodes along with the type of mutation
     * that was performed on each: created, destroyed, or updated.
     *
     * One common use case for this is to attach DOM event listeners to the underlying DOM nodes as Lexical nodes are created.
     * {@link LexicalEditor.getElementByKey} can be used for this.
     *
     * If any existing nodes are in the DOM, and skipInitialization is not true, the listener
     * will be called immediately with an updateTag of 'registerMutationListener' where all
     * nodes have the 'created' NodeMutation. This can be controlled with the skipInitialization option
     * (whose default was previously true for backwards compatibility with &lt;=0.16.1 but has been changed to false as of 0.21.0).
     *
     * @param klass - The class of the node that you want to listen to mutations on.
     * @param listener - The logic you want to run when the node is mutated.
     * @param options - see {@link MutationListenerOptions}
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerMutationListener(klass: Klass<LexicalNode>, listener: MutationListener, options?: MutationListenerOptions): () => void;
    /** @internal */
    getRegisteredNode(klass: Klass<LexicalNode>): RegisteredNode;
    /** @internal */
    resolveRegisteredNodeAfterReplacements(registeredNode: RegisteredNode): RegisteredNode;
    /** @internal */
    private initializeMutationListener;
    /** @internal */
    private registerNodeTransformToKlass;
    /**
     * Registers a listener that will run when a Lexical node of the provided class is
     * marked dirty during an update. The listener will continue to run as long as the node
     * is marked dirty. There are no guarantees around the order of transform execution!
     *
     * Watch out for infinite loops. See [Node Transforms](https://lexical.dev/docs/concepts/transforms)
     * @param klass - The class of the node that you want to run transforms on.
     * @param listener - The logic you want to run when the node is updated.
     * @returns a teardown function that can be used to cleanup the listener.
     */
    registerNodeTransform<T extends LexicalNode>(klass: Klass<T>, listener: Transform<T>): () => void;
    /**
     * Used to assert that a certain node is registered, usually by plugins to ensure nodes that they
     * depend on have been registered.
     * @returns True if the editor has registered the provided node type, false otherwise.
     */
    hasNode<T extends Klass<LexicalNode>>(node: T): boolean;
    /**
     * Used to assert that certain nodes are registered, usually by plugins to ensure nodes that they
     * depend on have been registered.
     * @returns True if the editor has registered all of the provided node types, false otherwise.
     */
    hasNodes<T extends Klass<LexicalNode>>(nodes: Array<T>): boolean;
    /**
     * Dispatches a command of the specified type with the specified payload.
     * This triggers all command listeners (set by {@link LexicalEditor.registerCommand})
     * for this type, passing them the provided payload. The command listeners
     * will be triggered in an implicit {@link LexicalEditor.update}, unless
     * this was invoked from inside an update in which case that update context
     * will be re-used (as if this was a dollar function itself).
     * @param type - the type of command listeners to trigger.
     * @param payload - the data to pass as an argument to the command listeners.
     */
    dispatchCommand<TCommand extends LexicalCommand<unknown>>(type: TCommand, payload: CommandPayloadType<TCommand>): boolean;
    /**
     * Gets a map of all decorators in the editor.
     * @returns A mapping of call decorator keys to their decorated content
     */
    getDecorators<T>(): Record<NodeKey, T>;
    /**
     *
     * @returns the current root element of the editor. If you want to register
     * an event listener, do it via {@link LexicalEditor.registerRootListener}, since
     * this reference may not be stable.
     */
    getRootElement(): null | HTMLElement;
    /**
     * Gets the key of the editor
     * @returns The editor key
     */
    getKey(): string;
    /**
     * Imperatively set the root contenteditable element that Lexical listens
     * for events on.
     */
    setRootElement(nextRootElement: null | HTMLElement): void;
    /**
     * Gets the underlying HTMLElement associated with the LexicalNode for the given key.
     * @returns the HTMLElement rendered by the LexicalNode associated with the key.
     * @param key - the key of the LexicalNode.
     */
    getElementByKey(key: NodeKey): HTMLElement | null;
    /**
     * Gets the active editor state.
     * @returns The editor state
     */
    getEditorState(): EditorState;
    /**
     * Imperatively set the EditorState. Triggers reconciliation like an update.
     * @param editorState - the state to set the editor
     * @param options - options for the update.
     */
    setEditorState(editorState: EditorState, options?: EditorSetOptions): void;
    /**
     * Parses a SerializedEditorState (usually produced by {@link EditorState.toJSON}) and returns
     * and EditorState object that can be, for example, passed to {@link LexicalEditor.setEditorState}. Typically,
     * deserialization from JSON stored in a database uses this method.
     * @param maybeStringifiedEditorState
     * @param updateFn
     * @returns
     */
    parseEditorState(maybeStringifiedEditorState: string | SerializedEditorState, updateFn?: () => void): EditorState;
    /**
     * Executes a read of the editor's state, with the
     * editor context available (useful for exporting and read-only DOM
     * operations). Much like update, but prevents any mutation of the
     * editor's state. Any pending updates will be flushed immediately before
     * the read.
     * @param callbackFn - A function that has access to read-only editor state.
     */
    read<T>(callbackFn: () => T): T;
    /**
     * Executes an update to the editor state. The updateFn callback is the ONLY place
     * where Lexical editor state can be safely mutated.
     * @param updateFn - A function that has access to writable editor state.
     * @param options - A bag of options to control the behavior of the update.
     */
    update(updateFn: () => void, options?: EditorUpdateOptions): void;
    /**
     * Focuses the editor by marking the existing selection as dirty, or by
     * creating a new selection at `defaultSelection` if one does not already
     * exist. If you want to force a specific selection, you should call
     * `root.selectStart()` or `root.selectEnd()` in an update.
     *
     * @param callbackFn - A function to run after the editor is focused.
     * @param options - A bag of options
     */
    focus(callbackFn?: () => void, options?: EditorFocusOptions): void;
    /**
     * Removes focus from the editor.
     */
    blur(): void;
    /**
     * Returns true if the editor is editable, false otherwise.
     * @returns True if the editor is editable, false otherwise.
     */
    isEditable(): boolean;
    /**
     * Sets the editable property of the editor. When false, the
     * editor will not listen for user events on the underling contenteditable.
     * @param editable - the value to set the editable mode to.
     */
    setEditable(editable: boolean): void;
    /**
     * Returns a JSON-serializable javascript object NOT a JSON string.
     * You still must call JSON.stringify (or something else) to turn the
     * state into a string you can transfer over the wire and store in a database.
     *
     * See {@link LexicalNode.exportJSON}
     *
     * @returns A JSON-serializable javascript object
     */
    toJSON(): SerializedEditor;
}
export {};
