import type { MindMapNode, MindMapRelation } from './types'; export declare function uid(): string; export declare function clone(o: T): T; export declare function findNode(root: MindMapNode, id: string): MindMapNode | null; export declare function findParent(root: MindMapNode, id: string, parent?: MindMapNode | null): MindMapNode | null; export declare function removeNode(root: MindMapNode, id: string): boolean; /** Replace the text of a node by id. Returns true on success, false * if the node was not found. No-op on an empty / same string. */ export declare function setNodeText(root: MindMapNode, id: string, text: string): boolean; /** Position relative to a target node when moving a sibling. */ export type MovePosition = 'before' | 'after' | 'child'; /** Move a node to a new location in the tree. * - 'before' / 'after': insert as a sibling of the target at that slot * (target's parent's children array). * - 'child': insert as the last child of the target. * No-op (returns false) if src === root, or if the move would * create a cycle (i.e. the target lives inside the src subtree, or * src is already in the target's desired position). */ export declare function moveNode(root: MindMapNode, srcId: string, targetId: string, position: MovePosition): boolean; export declare function addChild(root: MindMapNode, parentId: string, text?: string): MindMapNode | null; export declare function addSibling(root: MindMapNode, nodeId: string, text?: string): MindMapNode | null; /** * Insert a new sibling node BEFORE the given node (Shift+Enter in xmind). * Returns the new node, or null if the target is the root. */ export declare function addSiblingBefore(root: MindMapNode, nodeId: string, text?: string): MindMapNode | null; /** * Deep-clone a node (with all its descendants) and insert the copy as a * sibling immediately after the original. New ids are generated so the * result is a real duplicate. Returns the new node, or null if the * target is the root. */ export declare function duplicateNode(root: MindMapNode, nodeId: string): MindMapNode | null; export declare function reassignIds(n: MindMapNode): void; /** Deep-clone a subtree rooted at `nodeId`, reassigning all ids so * the copy can be re-inserted into the tree without id collisions. * Returns null if the node isn't found or is the root. */ export declare function cloneSubtree(root: MindMapNode, nodeId: string): MindMapNode | null; /** True iff a node with `descendantId` lives anywhere under * `rootId` in the tree (rootId itself counts). Used by the * clipboard paste cycle guard. */ export declare function hasDescendant(root: MindMapNode, rootId: string, descendantId: string): boolean; export declare function countDescendants(n: MindMapNode): number; export declare const DEFAULT_NEW_NODE_TEXT = "\u65B0\u8282\u70B9"; export declare function findRelation(root: MindMapNode, id: string): MindMapRelation | null; /** Create a relationship between two nodes. Returns the new * relation, or null when the pair is invalid: same node on both * ends, an unknown node id, or an identical (fromId, toId) * connection already exists. */ export declare function addRelation(root: MindMapNode, fromId: string, toId: string): MindMapRelation | null; export declare function removeRelation(root: MindMapNode, id: string): boolean; /** Patch a relation in place (label / anchors / control points). * `fromId` / `toId` / `id` are ignored — re-attach goes through * `reattachRelation`. Returns true on success. */ export declare function updateRelation(root: MindMapNode, id: string, patch: Partial>): boolean; /** Move one end of a relation to a different node. `end` selects * which side ('from' | 'to'). No-op (returns false) when the new * node is unknown, equals the other endpoint, or the resulting * (fromId, toId) pair already exists. Clears the moved end's * anchor offset so the line re-anchors at the new node's edge. */ export declare function reattachRelation(root: MindMapNode, id: string, end: 'from' | 'to', newNodeId: string): boolean; /** Drop every relation that references `nodeId` on either end. * Called by the canvas when a node (or its subtree) is removed. * Returns the number of relations removed. */ export declare function removeRelationsForNode(root: MindMapNode, nodeId: string): number; /** * Parse a Markdown string into a MindMapNode tree. Each heading * becomes a node; its level sets the depth. * - `# Title` → root text (overrides `rootText`) * - `## Sub` → child of the previous #/##/... heading * - bullet / paragraph text between headings → first child * of the preceding heading (so a `# Topic\n- detail` tree * gives one root node with one child). * * Inline fields parsed from a heading's body (in order, attached * to the heading that precedes them): * - `![alt](url)` → image * - `[label](url)` → link (label becomes the node's text) * - ` ```note ... ``` ` → note (the fence body becomes note.text) * * Empty input, or input with no `#` heading, returns a single * root with the fallback text. */ export declare function markdownToMindMap(md: string, rootText?: string): MindMapNode; /** * Round-trip-safe Markdown export of a MindMapNode tree. Each * heading is emitted as `#…`, then any inline fields (link / * image / note) in a fixed order so the same source produces * byte-stable output across re-exports. * * The `note` field round-trips through a ` ```note ` fence so a * user opening the export in any markdown editor sees a clearly * labeled block. The link is emitted as a standard `[label](url)` * with the node's text as the label — this keeps the export * human-readable and lets `markdownToMindMap` re-attach the * link to the right heading. */ export declare function mindMapToMarkdown(n: MindMapNode, depth?: number): string; /** * Parse a whole markdown document into a MindMapNode tree where * every block (heading, paragraph, list, code fence, table) * becomes a node. Body blocks carry their original markdown * payload in `node.richContent` so the renderer can show code, * tables, lists, etc. inside the node box. Headings form the * hierarchy; everything else is attached to the most recent * heading as a child (or to the synthetic root if no heading * has been seen yet). * * Unlike `markdownToMindMap`, this does NOT collapse body into * a single child of the heading, and the depth is unbounded — * a paragraph under `## Foo` becomes a child of `Foo`, and a * paragraph that follows a list under the same heading becomes * a sibling of that list, etc. This is the mode the user * asked for: "every paragraph becomes a child, no depth limit". * * A document with no `#` heading still produces a valid tree — * every block lands under the synthetic root. */ export declare function markdownToRichMindMap(md: string, rootText?: string): MindMapNode; /** * Serialize a single node's rich body (if any) back to the * original markdown it came from. Used by `mindMapToMarkdown` * to round-trip a tree built by `markdownToRichMindMap`. * Returns '' when the node has no rich body. */ export declare function richBlockToMarkdown(n: MindMapNode): string;