import * as React from 'react';
import { Subject } from 'rxjs';
import { BaseEditor, Node, NodeMatch, Path, RangeMode, Selection } from 'slate';
import { HistoryEditor } from 'slate-history';
import { ReactEditor } from 'slate-react';
import { T } from 'vitest/dist/chunks/environment.LoooBwUu.js';
import { FootnoteDefinitionNode } from '../el';
import type { MarkdownEditorPlugin } from '../plugin';
import { CommentDataType, MarkdownEditorProps } from '../types';
import { KeyboardTask, Methods } from './utils';
import type { MarkdownToHtmlOptions } from './utils/markdownToHtml';
/**
 * 编辑器上下文接口
 *
 * 提供编辑器组件间共享的状态和方法
 */
export interface EditorStoreContextType {
    /** 编辑器核心状态存储 */
    store: EditorStore;
    /** 是否启用打字机模式 */
    typewriter: boolean;
    /** 根容器引用 */
    rootContainer?: React.MutableRefObject<HTMLDivElement | undefined>;
    /** 设置显示评论列表 */
    setShowComment: (list: CommentDataType[]) => void;
    /** 是否为只读模式 */
    readonly: boolean;
    /** 键盘任务流 */
    keyTask$: Subject<{
        key: Methods<KeyboardTask>;
        args?: any[];
    }>;
    /** 插入自动完成文本流 */
    insertCompletionText$: Subject<string>;
    /** 打开插入链接流 */
    openInsertLink$: Subject<Selection>;
    /** 是否刷新浮动工具栏 */
    refreshFloatBar?: boolean;
    /** DOM矩形信息 */
    domRect: DOMRect | null;
    /** 设置DOM矩形 */
    setDomRect: (rect: DOMRect | null) => void;
    /** 设置刷新浮动工具栏状态 */
    setRefreshFloatBar?: (refresh: boolean) => void;
    /** 是否打开插入自动完成 */
    openInsertCompletion?: boolean;
    /** 设置打开插入自动完成状态 */
    setOpenInsertCompletion?: (open: boolean) => void;
    /** 编辑器属性配置 */
    editorProps: MarkdownEditorProps;
    /** Markdown编辑器引用 */
    markdownEditorRef: React.MutableRefObject<BaseEditor & ReactEditor & HistoryEditor>;
    /** Markdown容器引用 */
    markdownContainerRef: React.MutableRefObject<HTMLDivElement | null>;
}
export declare const EditorStoreContext: React.Context<EditorStoreContextType | null>;
/**
 * 获取编辑器存储上下文的Hook
 *
 * 提供安全的上下文访问，包含默认值处理
 *
 * @returns 编辑器存储上下文对象
 *
 * @example
 * ```tsx
 * const { store, readonly, typewriter } = useEditorStore();
 * ```
 */
export declare const useEditorStore: () => EditorStoreContextType;
/**
 * 编辑器核心状态管理类
 *
 * 负责管理编辑器的所有状态、操作和事件处理
 * 包括文档结构、选择状态、高亮、拖拽、历史记录等
 *
 * @class
 */
export declare class EditorStore {
    /** 高亮缓存映射表 */
    highlightCache: Map<object, import("slate").BaseRange[]>;
    /** 允许进入的元素类型集合 */
    private ableToEnter;
    /** 当前拖拽的元素 */
    draggedElement: null | HTMLElement;
    footnoteDefinitionMap: Map<string, FootnoteDefinitionNode>;
    inputComposition: boolean;
    plugins?: MarkdownEditorPlugin[];
    domRect: DOMRect | null;
    _editor: React.MutableRefObject<BaseEditor & ReactEditor & HistoryEditor>;
    /** 当前 setMDContent 操作的 AbortController */
    private _currentAbortController;
    private markdownToHtmlOptions?;
    /**
     * 获取当前编辑器实例。
     *
     * @returns 当前的 Slate 编辑器实例。
     */
    get editor(): BaseEditor & ReactEditor & HistoryEditor;
    constructor(_editor: React.MutableRefObject<BaseEditor & ReactEditor & HistoryEditor>, plugins?: MarkdownEditorPlugin[], markdownToHtmlOptions?: MarkdownToHtmlOptions);
    /**
     * 聚焦到编辑器
     */
    focus(): void;
    /**
     * 查找最新的节点索引。
     *
     * @param node - 当前节点。
     * @param index - 当前索引路径。
     * @returns 最新节点的索引路径。
     */
    private findLatest;
    /**
     * 检查给定节点是否是最新节点。用于展示 闪动光标
     *
     * @param node - 要检查的节点。
     * @returns 如果节点是最新节点，则返回 true；否则返回 false。
     */
    isLatestNode(node: Node): boolean;
    /**
     * 插入一个链接到编辑器中。
     *
     * @param filePath - 要插入的文件路径。如果路径以 'http' 开头，则链接文本为路径本身，否则为文件名。
     *
     * 该方法首先解析文件路径，并创建一个包含文本和 URL 的节点对象。
     * 然后，它检查当前编辑器的选区是否存在且未折叠。如果选区不存在或已折叠，则方法返回。
     *
     * 接下来，它查找当前选区所在的最低层级的元素节点。如果节点类型是 'table-cell' 或 'paragraph'，
     * 则在当前选区插入链接节点并选中它。
     *
     * 如果当前选区所在的元素节点类型不是 'table-cell' 或 'paragraph'，则查找包含当前选区的父级元素节点，
     * 并在其后插入一个包含链接节点的新段落。
     */
    insertLink(filePath: string): void;
    /**
     * 插入节点到编辑器中。
     *
     * @param nodes - 要插入的节点，可以是单个节点或节点数组。
     * @param options - 可选参数，用于指定插入节点的选项。
     */
    insertNodes(nodes: Node | Node[], options?: any): void;
    /**
     * Converts an HTML element to a Slate path and node.
     *
     * @param el - The HTML element to convert.
     * @returns A tuple containing the path and the corresponding Slate node.
     * @private
     */
    private toPath;
    /**
     * Clears all content from the editor, replacing it with an empty paragraph.
     */
    clearContent(): void;
    /**
     * 从 markdown 文本设置编辑器内容
     *
     * @param md - 要设置为编辑器内容的 Markdown 字符串
     *             如果为 undefined，方法将直接返回不做任何更改
     *             如果 markdown 与当前内容相同，则不做任何更改
     * @param plugins - 可选的自定义 markdown 解析插件
     * @param options - 可选的配置参数
     *   - chunkSize: 分块大小阈值，默认 5000 字符。超过此大小会启用分批处理
     *   - separator: 分隔符，默认为双换行符 '\n\n'，用于拆分长文本
     *   - useRAF: 是否使用 requestAnimationFrame 优化，默认 true，避免长文本处理时卡顿
     *   - batchSize: 每帧处理的节点数量，默认 50，仅在 useRAF=true 时生效
     *   - onProgress: 进度回调函数，接收当前进度 (0-1) 作为参数
     * @returns 如果使用 RAF，返回 Promise；否则同步执行
     */
    setMDContent(md?: string, plugins?: MarkdownEditorPlugin[], options?: {
        chunkSize?: number;
        separator?: string | RegExp;
        useRAF?: boolean;
        batchSize?: number;
        onProgress?: (progress: number) => void;
    }): void | Promise<void>;
    /**
     * 检查是否应该跳过设置内容
     */
    private _shouldSkipSetContent;
    /**
     * 设置短内容（直接处理）
     */
    private _setShortContent;
    /**
     * 同步设置长内容
     */
    private _setLongContentSync;
    /**
     * 解析分块为节点列表
     */
    private _parseChunksToNodes;
    /**
     * 取消当前正在进行的 setMDContent 操作
     */
    cancelSetMDContent(): void;
    /**
     * 使用 requestAnimationFrame 分批解析和设置内容
     * 边解析边插入，实时显示内容
     *
     * @param chunks - markdown 分块数组
     * @param plugins - 解析插件
     * @param batchSize - 每帧处理的数量
     * @param onProgress - 进度回调函数
     * @returns Promise，在所有内容处理完成后 resolve
     * @private
     */
    private _parseAndSetContentWithRAF;
    /**
     * 按指定分隔符拆分 markdown 内容
     * 保持内容结构的完整性
     *
     * @param md - 要拆分的 markdown 字符串
     * @param separator - 分隔符，可以是字符串或正则表达式
     * @returns 拆分后的字符串数组
     * @private
     */
    private _splitMarkdown;
    private _collectSeparatorMatches;
    private _isLineStart;
    private _matchFence;
    private _findLineEnd;
    /**
     * 移除节点
     * @param options
     */
    removeNodes: (options?: {
        at?: Location;
        match?: NodeMatch<T>;
        mode?: RangeMode;
        hanging?: boolean;
        voids?: boolean;
    }) => void;
    /**
     * 获取当前编辑器内容作为节点列表
     *
     * @returns 当前编辑器内容的节点列表
     */
    getContent(): any[];
    /**
     * 获取当前编辑器内容作为 markdown 字符串
     *
     * @param plugins - 可选的自定义 markdown 转换插件
     * @returns 转换为 markdown 的当前编辑器内容
     */
    getMDContent(plugins?: MarkdownEditorPlugin[]): string;
    /**
     * 获取当前编辑器内容作为 HTML 字符串
     *
     * @returns 转换为 HTML 的当前编辑器内容
     */
    getHtmlContent(options?: MarkdownToHtmlOptions): string;
    /**
     * 获取节点的 finished 属性
     *
     * @param node - 节点对象
     * @returns finished 属性值
     * @private
     */
    private _getNodeFinished;
    /**
     * 比较两个节点的 hash 和 finished 是否相同
     *
     * @param newNode - 新节点
     * @param oldNode - 旧节点
     * @returns 如果 hash 和 finished 都相同返回 true，否则返回 false
     * @private
     */
    private _isNodeEqual;
    /**
     * 替换指定位置的节点
     *
     * @param path - 节点路径
     * @param newNode - 新节点
     * @private
     */
    private _replaceNodeAt;
    /**
     * 使用节点列表设置编辑器内容
     *
     * @param nodeList - 要设置为编辑器内容的节点列表
     */
    setContent(nodeList: Node[]): void;
    /**
     * 使用差异检测和操作队列优化更新节点列表。
     *
     * @param nodeList - 新的节点列表
     *
     * 优化步骤：
     * 1. 过滤无效节点
     * 2. 计算 hash 并检查是否需要更新
     * 3. 生成差异操作
     * 4. 执行优化后的操作
     * 5. 处理可能的错误情况
     *
     * 过滤规则：
     * - 移除空的段落节点
     * - 移除空的列表节点
     * - 移除空的列表项节点
     * - 移除无效的代码块节点
     * - 移除无源的图片节点
     *
     * 错误处理：
     * - 如果优化更新失败，会回退到直接替换整个节点列表
     * - 错误信息会被记录到控制台
     */
    updateNodeList(nodeList: Node[]): void;
    /**
     * 检查节点是否有效
     */
    private _isValidNode;
    /**
     * 生成两个节点列表之间的差异操作队列。
     *
     * @param newNodes - 新的节点列表
     * @param oldNodes - 旧的节点列表
     * @returns 包含所有需要执行的操作的队列
     *
     * 该方法通过以下步骤生成差异：
     * 1. 处理节点数量不同的情况
     * 2. 对共有节点进行深度比较
     * 3. 生成最小化的操作序列
     * 4. 根据优先级排序操作
     */
    private generateDiffOperations;
    /**
     * 内部方法：生成差异操作，不进行排序。
     * 递归调用时使用此方法，避免重复排序。
     */
    private generateDiffOperationsInternal;
    /**
     * 递归比较两个节点及其子节点的差异。
     *
     * @param newNode - 新节点
     * @param oldNode - 旧节点
     * @param path - 当前节点的路径
     * @param operations - 操作队列，用于存储发现的差异操作
     *
     * 比较过程包括：
     * 1. 检查节点 hash 是否相同（相同则跳过比较）
     * 2. 检查节点类型是否相同
     * 3. 特殊处理表格节点
     * 4. 比较文本节点内容
     * 5. 比较节点属性
     * 6. 递归比较子节点
     * @private
     */
    private compareNodes;
    /**
     * 特殊处理表格节点的比较。
     *
     * @param newTable - 新的表格节点
     * @param oldTable - 旧的表格节点
     * @param path - 表格节点的路径
     * @param operations - 操作队列
     *
     * 处理步骤：
     * 1. 检查表格结构是否相同
     * 2. 比较表格属性
     * 3. 逐行比较和更新
     * 4. 处理行数变化
     * 5. 必要时进行整表替换
     * @private
     */
    private compareTableNodes;
    /**
     * 检查表格结构是否相同
     */
    private _isSameTableStructure;
    /**
     * 更新结构相同的表格
     */
    private _updateSameStructureTable;
    /**
     * 更新结构不同的表格
     */
    private _updateDifferentStructureTable;
    /**
     * 检查表格属性是否变化
     */
    private _tablePropsChanged;
    /**
     * 更新表格行
     */
    private _updateTableRow;
    /**
     * 处理单元格数量变化
     */
    private _handleCellCountChanges;
    /**
     * 更新有行数变化的表格
     */
    private _updateTableWithRowChanges;
    /**
     * 处理行数变化
     */
    private _handleRowCountChanges;
    /**
     * 比较和更新表格单元格。
     *
     * @param newCell - 新的单元格节点
     * @param oldCell - 旧的单元格节点
     * @param path - 单元格的路径
     * @param operations - 操作队列
     *
     * 处理步骤：
     * 1. 检查单元格属性变化
     * 2. 处理简单文本单元格
     * 3. 处理复杂单元格内容
     * 4. 生成适当的更新操作
     * @private
     */
    private compareCells;
    /**
     * 比较单元格属性
     */
    private compareCellProperties;
    /**
     * 比较单元格子节点
     */
    private compareCellChildren;
    /**
     * 判断是否是简单文本单元格
     */
    private isSimpleTextCell;
    /**
     * 比较简单文本单元格
     */
    private compareSimpleTextCell;
    /**
     * 比较文本节点属性
     */
    private compareTextNodeProperties;
    /**
     * 比较复杂单元格子节点
     */
    private compareComplexCellChildren;
    /**
     * 判断结构是否不同
     */
    private isStructurallyDifferent;
    /**
     * 替换复杂单元格子节点
     */
    private replaceComplexCellChildren;
    /**
     * 逐个比较子节点
     */
    private compareChildrenSequentially;
    /**
     * 执行操作队列中的所有操作。
     *
     * @param operations - 要执行的操作队列
     *
     * 执行过程：
     * 1. 使用批处理模式执行所有操作
     * 2. 按照操作类型分别处理
     * 3. 处理可能的错误情况
     * 4. 保证操作的原子性
     */
    private executeOperations;
    /**
     * 处理拖拽开始事件。
     *
     * @param e - React 拖拽事件对象
     * @param container - 容器 div 元素
     *
     * 此方法会在拖拽开始时调用，主要功能包括：
     * 1. 阻止事件传播
     * 2. 设置拖拽图像
     * 3. 初始化拖拽相关的元素和位置数据
     * 4. 添加拖拽过程中和拖拽结束时的事件监听器
     * 5. 计算可拖拽目标的位置
     * 6. 处理拖拽过程中的视觉反馈
     * 7. 在拖拽结束时更新编辑器内容
     */
    dragStart(e: any, container: HTMLDivElement): void;
    /**
     * 设置拖拽图像
     */
    private _setupDragImage;
    /**
     * 获取允许进入的元素类型集合
     */
    private _getAbleToEnterSet;
    /**
     * 收集移动点
     */
    private _collectMovePoints;
    /**
     * 判断是否应该包含元素
     */
    private _shouldIncludeElement;
    /**
     * 创建拖拽悬停处理器
     */
    private _createDragOverHandler;
    /**
     * 查找最近的移动点
     */
    private _findClosestPoint;
    /**
     * 更新拖拽标记
     */
    private _updateDragMark;
    /**
     * 处理拖拽结束
     */
    private _handleDragEnd;
    /**
     * 移动节点
     */
    private _moveNode;
    /**
     * 移动列表项到非列表项位置
     * @returns 需要删除的路径，如果不需要删除则返回 null
     */
    private _moveListItemToNonListItem;
    /**
     * 清理空的父节点
     */
    private _cleanupEmptyParent;
    /**
     * 替换编辑器中的文本内容
     *
     * @param searchText - 要查找和替换的原始文本
     * @param replaceText - 替换后的新文本
     * @param options - 可选参数
     * @param options.caseSensitive - 是否区分大小写，默认为 false
     * @param options.wholeWord - 是否只匹配完整单词，默认为 false
     * @param options.replaceAll - 是否替换所有匹配项，默认为 true
     *
     * @returns 替换操作的数量
     *
     * @example
     * ```ts
     * // 替换所有 "old" 为 "new"
     * const count = store.replaceText("old", "new");
     *
     * // 只替换第一个匹配项，区分大小写
     * const count = store.replaceText("Old", "New", {
     *   caseSensitive: true,
     *   replaceAll: false
     * });
     * ```
     */
    replaceText(searchText: string, replaceText: string, options?: {
        caseSensitive?: boolean;
        wholeWord?: boolean;
        replaceAll?: boolean;
    }): number;
    /**
     * 在所有文本节点中替换所有匹配项
     */
    private _replaceAllInNodes;
    /**
     * 在所有文本节点中替换第一个匹配项
     */
    private _replaceFirstInNodes;
    /**
     * 在单个文本中执行替换
     */
    private _replaceInText;
    /**
     * 构建正则表达式标志
     */
    private _buildRegexFlags;
    /**
     * 在选中的区域内替换文本
     *
     * @param searchText - 要查找和替换的原始文本
     * @param replaceText - 替换后的新文本
     * @param options - 可选参数
     * @param options.caseSensitive - 是否区分大小写，默认为 false
     * @param options.wholeWord - 是否只匹配完整单词，默认为 false
     * @param options.replaceAll - 是否替换所有匹配项，默认为 true
     *
     * @returns 替换操作的数量，如果没有选中区域则返回 0
     *
     * @example
     * ```ts
     * // 在选中区域内替换文本
     * const count = store.replaceTextInSelection("old", "new");
     * ```
     */
    replaceTextInSelection(searchText: string, replaceText: string, options?: {
        caseSensitive?: boolean;
        wholeWord?: boolean;
        replaceAll?: boolean;
    }): number;
    /**
     * 在选中区域的文本节点中执行替换
     */
    private _replaceInSelectionNodes;
    /**
     * 替换所有匹配的文本（replaceText 的简化版本）
     *
     * @param searchText - 要查找和替换的原始文本
     * @param replaceText - 替换后的新文本
     * @param caseSensitive - 是否区分大小写，默认为 false
     *
     * @returns 替换操作的数量
     *
     * @example
     * ```ts
     * // 替换所有 "old" 为 "new"
     * const count = store.replaceAll("old", "new");
     *
     * // 区分大小写替换
     * const count = store.replaceAll("Old", "New", true);
     * ```
     */
    replaceAll(searchText: string, replaceText: string, caseSensitive?: boolean): number;
    /**
     * 转义正则表达式特殊字符
     *
     * @param string - 需要转义的字符串
     * @returns 转义后的字符串
     * @private
     */
    private escapeRegExp;
    /**
     * 在编辑器中根据路径描述和文本内容查找并选择匹配位置
     *
     * @param pathDescription - 路径描述，用于限制搜索范围。可以是：
     *                         - 节点类型（如 "paragraph", "table", "list"）
     *                         - 包含特定文本的节点区域
     *                         - 空字符串表示在整个编辑器中搜索
     * @param searchText - 要查找的文本内容
     * @param options - 查找选项
     * @returns 匹配结果数组
     *
     * @example
     * ```ts
     * // 查找所有包含 "focus" 的位置
     * const results = store.findByPathAndText("", "focus");
     */
    findByPathAndText(pathDescription: Path, searchText: string, options?: {
        caseSensitive?: boolean;
        wholeWord?: boolean;
        maxResults?: number;
    }): {
        path: Path;
        range: import("slate").BaseRange;
        node: any;
        matchedText: string;
        offset: {
            start: number;
            end: number;
        };
        lineContent: string;
        nodeType?: string | undefined;
        searchVariant?: string | undefined;
        isLink?: boolean | undefined;
        linkUrl?: string | undefined;
    }[];
    /**
     * 更新编辑器的状态数据
     *
     * @param value - 状态更新器，可以是函数或对象
     *
     * 该方法提供两种更新状态的方式：
     * 1. 函数式更新：传入一个函数，可以直接修改状态
     * 2. 对象式更新：传入一个对象，直接覆盖对应的状态值
     *
     * @example
     * ```ts
     * // 函数式更新 - 可以访问当前状态
     * setState((state) => {
     *   state.focus = true;
     *   state.manual = false;
     * });
     *
     * // 对象式更新 - 直接设置新值
     * setState({
     *   focus: true,
     *   manual: false
     * });
     * ```
     */
    setState(value: (state: EditorStore) => void): void;
}
