flow-mindmap 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ import type { MindMapNode } from '../types';
2
+ type __VLS_Props = {
3
+ data: MindMapNode;
4
+ };
5
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
+ import: (data: MindMapNode) => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ onImport?: ((data: MindMapNode) => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ export default _default;
@@ -0,0 +1,33 @@
1
+ type __VLS_Props = {
2
+ /** 'left' slides in from the left edge, 'right' from the right. */
3
+ side?: 'left' | 'right';
4
+ /** Pixels wide. */
5
+ width?: number;
6
+ /** Show or hide the panel. Animation handles the transition. */
7
+ open?: boolean;
8
+ /** Optional title shown in the header. */
9
+ title?: string;
10
+ };
11
+ declare var __VLS_5: {}, __VLS_7: {};
12
+ type __VLS_Slots = {} & {
13
+ header?: (props: typeof __VLS_5) => any;
14
+ } & {
15
+ default?: (props: typeof __VLS_7) => any;
16
+ };
17
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
18
+ "update:open": (value: boolean) => any;
19
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
20
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
21
+ }>, {
22
+ title: string;
23
+ width: number;
24
+ side: "left" | "right";
25
+ open: boolean;
26
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
28
+ export default _default;
29
+ type __VLS_WithSlots<T, S> = T & {
30
+ new (): {
31
+ $slots: S;
32
+ };
33
+ };
@@ -0,0 +1,7 @@
1
+ type __VLS_Props = {
2
+ name: string;
3
+ size?: number | string;
4
+ stroke?: number | string;
5
+ };
6
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ export default _default;
@@ -0,0 +1,12 @@
1
+ import type { MindMapNode } from '../types';
2
+ type __VLS_Props = {
3
+ /** Current data tree. Used to populate the editor on first mount
4
+ * (as markdown) and as the source of the "export .md" action. */
5
+ data: MindMapNode;
6
+ };
7
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
+ import: (data: MindMapNode) => any;
9
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
10
+ onImport?: ((data: MindMapNode) => any) | undefined;
11
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
+ export default _default;
@@ -0,0 +1,87 @@
1
+ import type { MindMapNode, MindMapTheme, MindMapSettings, NodeStyle, MindMapImage } from '../types';
2
+ type __VLS_Props = {
3
+ data: MindMapNode;
4
+ theme?: MindMapTheme;
5
+ /**
6
+ * When true, hides the MindMap's own toolbar and disables every
7
+ * edit operation (add/remove/edit/drag/paste/rich-edit/note
8
+ * edit/context menu). Expand/collapse stays available so the
9
+ * user can still navigate a large tree. The app-level top
10
+ * toolbar / drawers are controlled by the parent (App.vue).
11
+ */
12
+ previewMode?: boolean;
13
+ /**
14
+ * Optional raw markdown source. When set, the component parses
15
+ * it into the data tree and ignores `data` (use one or the
16
+ * other). Editing nodes on the canvas emits `markdownChange`
17
+ * with the re-serialized form, so the host can keep its
18
+ * markdown source in sync without polling. Pass an empty
19
+ * string to clear.
20
+ */
21
+ markdown?: string;
22
+ /**
23
+ * Optional per-edge color list. When set, top-level branches
24
+ * draw their edges (and their descendant edges under
25
+ * `rainbowBranch`) using these colors in order, wrapping
26
+ * around. Overrides the palette picked by `branchPaletteId`
27
+ * / `customPalettes`. Pass an empty array to fall back to
28
+ * the palette pipeline.
29
+ */
30
+ lineColors?: string[];
31
+ };
32
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {
33
+ addChild: (parentId: string) => void;
34
+ addSibling: (nodeId: string) => void;
35
+ removeNode: (nodeId: string) => void;
36
+ duplicateNode: (nodeId: string) => void;
37
+ setNodeText: (nodeId: string, text: string) => void;
38
+ moveNode: (srcId: string, targetId: string, position: "before" | "after" | "child") => boolean;
39
+ getData: () => MindMapNode;
40
+ setData: (data: MindMapNode) => void;
41
+ resetView: () => void;
42
+ exportData: () => string;
43
+ importData: (json: string) => boolean;
44
+ getMarkdown: () => string;
45
+ setMarkdown: (md: string, emitMarkdownChange?: boolean) => void;
46
+ setBalanced: (value: boolean) => void;
47
+ isBalanced: () => boolean;
48
+ balance: () => void;
49
+ applyNodeStyle: (nodeId: string, style: NodeStyle) => void;
50
+ getNodeStyle: (nodeId: string) => NodeStyle;
51
+ applyNodeLink: (nodeId: string, url: string) => void;
52
+ removeNodeLink: (nodeId: string) => void;
53
+ applyNodeNote: (nodeId: string, text: string) => void;
54
+ removeNodeNote: (nodeId: string) => void;
55
+ applyNodeImageByUrl: (nodeId: string, url: string) => void;
56
+ applyNodeImage: (nodeId: string, image: MindMapImage) => void;
57
+ removeNodeImage: (nodeId: string) => void;
58
+ applyNodeRichContent: (nodeId: string, content: {
59
+ kind: "code" | "table";
60
+ raw: string;
61
+ lang?: string;
62
+ } | null) => void;
63
+ undo: () => void;
64
+ redo: () => void;
65
+ canUndo: () => boolean;
66
+ canRedo: () => boolean;
67
+ applySettings: (s: Partial<MindMapSettings>) => void;
68
+ getSettings: () => MindMapSettings;
69
+ setBranchPalette: (id: import("../types").BranchPaletteId) => void;
70
+ getBranchPalette: () => import("../types").BranchPaletteId;
71
+ getBranchPalettes: () => import("../types").BranchPalette[];
72
+ lineWidthForDepth: (depth: number) => number;
73
+ endWidthForDepth: (depth: number) => number;
74
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
75
+ select: (node: MindMapNode | null) => any;
76
+ change: (data: MindMapNode) => any;
77
+ "edit-note": (nodeId: string) => any;
78
+ markdownChange: (markdown: string) => any;
79
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
80
+ onSelect?: ((node: MindMapNode | null) => any) | undefined;
81
+ onChange?: ((data: MindMapNode) => any) | undefined;
82
+ "onEdit-note"?: ((nodeId: string) => any) | undefined;
83
+ onMarkdownChange?: ((markdown: string) => any) | undefined;
84
+ }>, {
85
+ previewMode: boolean;
86
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
87
+ export default _default;
@@ -0,0 +1,63 @@
1
+ type __VLS_Props = {
2
+ /** Cursor X in viewport coords (clientX). */
3
+ x: number;
4
+ /** Cursor Y in viewport coords (clientY). */
5
+ y: number;
6
+ /** Container the menu should not escape — used to clamp the
7
+ * position so the menu stays on-screen. */
8
+ container: HTMLElement | null;
9
+ /** Whether the node already has an image. When true, the
10
+ * "添加图片" action is renamed "替换图片" and a "移除图片"
11
+ * action is appended. */
12
+ hasImage?: boolean;
13
+ /** Whether the node already has a link. Drives the label /
14
+ * presence of the "添加链接" / "编辑链接" / "移除链接"
15
+ * actions. */
16
+ hasLink?: boolean;
17
+ /** Whether the node already has a note. Same role as
18
+ * hasLink for the note action. */
19
+ hasNote?: boolean;
20
+ /** Whether the node already has a code block in its
21
+ * richContent. Drives the code-block action's label and
22
+ * whether a "移除代码块" sub-action shows. */
23
+ hasCode?: boolean;
24
+ /** Whether the node already has a table in its richContent.
25
+ * Same role as hasCode for the table action. */
26
+ hasTable?: boolean;
27
+ };
28
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
29
+ close: () => any;
30
+ pickImage: () => any;
31
+ setLink: () => any;
32
+ removeLink: () => any;
33
+ editNote: () => any;
34
+ removeNote: () => any;
35
+ removeImage: () => any;
36
+ addCode: () => any;
37
+ editCode: () => any;
38
+ removeCode: () => any;
39
+ addTable: () => any;
40
+ editTable: () => any;
41
+ removeTable: () => any;
42
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
43
+ onClose?: (() => any) | undefined;
44
+ onPickImage?: (() => any) | undefined;
45
+ onSetLink?: (() => any) | undefined;
46
+ onRemoveLink?: (() => any) | undefined;
47
+ onEditNote?: (() => any) | undefined;
48
+ onRemoveNote?: (() => any) | undefined;
49
+ onRemoveImage?: (() => any) | undefined;
50
+ onAddCode?: (() => any) | undefined;
51
+ onEditCode?: (() => any) | undefined;
52
+ onRemoveCode?: (() => any) | undefined;
53
+ onAddTable?: (() => any) | undefined;
54
+ onEditTable?: (() => any) | undefined;
55
+ onRemoveTable?: (() => any) | undefined;
56
+ }>, {
57
+ hasImage: boolean;
58
+ hasLink: boolean;
59
+ hasNote: boolean;
60
+ hasCode: boolean;
61
+ hasTable: boolean;
62
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
63
+ export default _default;
@@ -0,0 +1,34 @@
1
+ import type { MindMapNode } from '../types';
2
+ type __VLS_Props = {
3
+ /** The currently selected node. `null` means nothing is
4
+ * selected; the panel renders an empty-state in that case. */
5
+ selectedNode: MindMapNode | null;
6
+ /** Disable all edit controls (read-only mode). */
7
+ readonly?: boolean;
8
+ /** Bumped by the parent (App.vue) on each select change. The
9
+ * panel uses this as a "focus the textarea" signal so the
10
+ * user can start typing immediately after picking a node. */
11
+ focusTick?: number;
12
+ };
13
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
14
+ "set-link": (url: string) => any;
15
+ apply: (text: string) => any;
16
+ remove: () => any;
17
+ "set-image": (src: string) => any;
18
+ "set-rich": (payload: {
19
+ kind: "code" | "table";
20
+ raw: string;
21
+ lang?: string;
22
+ } | null) => any;
23
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
24
+ "onSet-link"?: ((url: string) => any) | undefined;
25
+ onApply?: ((text: string) => any) | undefined;
26
+ onRemove?: (() => any) | undefined;
27
+ "onSet-image"?: ((src: string) => any) | undefined;
28
+ "onSet-rich"?: ((payload: {
29
+ kind: "code" | "table";
30
+ raw: string;
31
+ lang?: string;
32
+ } | null) => any) | undefined;
33
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
+ export default _default;
@@ -0,0 +1,45 @@
1
+ import type { MindMapNode } from '../types';
2
+ type __VLS_Props = {
3
+ /** Root of the mind map. */
4
+ data: MindMapNode;
5
+ /** Highlight the node with this id (the one selected on the main canvas). */
6
+ selectedId?: string | null;
7
+ /** When true, hide a node's children in the outline. */
8
+ collapsedIds?: Set<string>;
9
+ /** Read-only — disables editing / add / drag. Default false. */
10
+ readonly?: boolean;
11
+ };
12
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
13
+ select: (node: MindMapNode) => any;
14
+ edit: (payload: {
15
+ id: string;
16
+ text: string;
17
+ }) => any;
18
+ toggleCollapse: (id: string) => any;
19
+ addChild: (id: string) => any;
20
+ addSibling: (id: string) => any;
21
+ move: (payload: {
22
+ srcId: string;
23
+ targetId: string;
24
+ position: "before" | "after" | "child";
25
+ }) => any;
26
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
27
+ onSelect?: ((node: MindMapNode) => any) | undefined;
28
+ onEdit?: ((payload: {
29
+ id: string;
30
+ text: string;
31
+ }) => any) | undefined;
32
+ onToggleCollapse?: ((id: string) => any) | undefined;
33
+ onAddChild?: ((id: string) => any) | undefined;
34
+ onAddSibling?: ((id: string) => any) | undefined;
35
+ onMove?: ((payload: {
36
+ srcId: string;
37
+ targetId: string;
38
+ position: "before" | "after" | "child";
39
+ }) => any) | undefined;
40
+ }>, {
41
+ selectedId: string | null;
42
+ readonly: boolean;
43
+ collapsedIds: Set<string>;
44
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
45
+ export default _default;
@@ -0,0 +1,30 @@
1
+ import type { MindMapSettings } from '../types';
2
+ type __VLS_Props = {
3
+ settings: MindMapSettings;
4
+ /** true when a node is selected — the per-node panel is shown too. */
5
+ hasSelection: boolean;
6
+ selectedNodeText?: string;
7
+ };
8
+ /** Style overrides for a single node. Stored externally (App.vue
9
+ * holds the map) so the per-node state is preserved across
10
+ * selection changes. */
11
+ export interface NodeStyle {
12
+ /** Background colour. undefined = fall back to theme/branch. */
13
+ bg?: string;
14
+ /** Text colour. */
15
+ textColor?: string;
16
+ /** Border colour. */
17
+ borderColor?: string;
18
+ /** Font weight: 400 / 600. undefined = inherit. */
19
+ fontWeight?: 400 | 600;
20
+ }
21
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
22
+ reset: () => any;
23
+ "update:settings": (s: Partial<MindMapSettings>) => any;
24
+ "update:nodeStyle": (s: Partial<NodeStyle>) => any;
25
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
26
+ onReset?: (() => any) | undefined;
27
+ "onUpdate:settings"?: ((s: Partial<MindMapSettings>) => any) | undefined;
28
+ "onUpdate:nodeStyle"?: ((s: Partial<NodeStyle>) => any) | undefined;
29
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
+ export default _default;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Tiny autosize helper for textareas. Usage:
3
+ *
4
+ * const taRef = ref<HTMLTextAreaElement | null>(null)
5
+ * useAutosize(taRef, { minRows: 4, maxRows: 12 })
6
+ *
7
+ * The composable listens to the textarea's `input` event, sets
8
+ * its height to its scrollHeight (clamped to the row range), and
9
+ * also re-runs when the bound value changes from outside so a
10
+ * parent that resets `.value` (e.g. on node switch) still sizes
11
+ * correctly.
12
+ */
13
+ import { type Ref } from 'vue';
14
+ export interface AutosizeOptions {
15
+ /** Minimum visible rows when the textarea is empty. Default 3. */
16
+ minRows?: number;
17
+ /** Maximum visible rows before the textarea starts scrolling.
18
+ * Default 12. Set to 0 for "no cap". */
19
+ maxRows?: number;
20
+ }
21
+ export declare function useAutosize(refEl: Ref<HTMLTextAreaElement | null>, options?: AutosizeOptions): void;
@@ -0,0 +1,19 @@
1
+ import type { MindMapNode } from '../types';
2
+ /**
3
+ * Linear undo/redo history for the mind map.
4
+ *
5
+ * Each entry stores the data tree (full JSON snapshot).
6
+ * Snapshots are deep-cloned JSON strings (one string per state). The
7
+ * timeline is bounded so a long session doesn't grow without limit.
8
+ */
9
+ export interface HistoryState {
10
+ data: MindMapNode;
11
+ }
12
+ export declare function useHistory(maxSize?: number): {
13
+ canUndo: () => boolean;
14
+ canRedo: () => boolean;
15
+ record: (snapshot: HistoryState) => void;
16
+ undo: () => HistoryState | null;
17
+ redo: () => HistoryState | null;
18
+ reset: () => void;
19
+ };
@@ -0,0 +1,32 @@
1
+ export interface KeyboardOptions {
2
+ isEditing: () => boolean;
3
+ isReadonly: () => boolean;
4
+ getSelectedId: () => string | null;
5
+ getRootId: () => string;
6
+ /**
7
+ * Called when Tab/Enter fires and no node is selected — defaults the
8
+ * action to the root node so the user can build a tree from scratch
9
+ * without first clicking something.
10
+ */
11
+ defaultTargetId?: () => string;
12
+ onAddChild: (id: string) => void;
13
+ onAddSibling: (id: string) => void;
14
+ onAddSiblingBefore: (id: string) => void;
15
+ onRemove: (id: string) => void;
16
+ onStartEdit: (id: string) => void;
17
+ onClearSelection: () => void;
18
+ onDuplicate: (id: string) => void;
19
+ onUndo: () => void;
20
+ onRedo: () => void;
21
+ /**
22
+ * Move selection to a neighbour. Returns the new selected id (or null
23
+ * if no neighbour exists in that direction).
24
+ * dx = -1 → select first child
25
+ * dx = +1 → select parent
26
+ * dy = -1 → select previous sibling
27
+ * dy = +1 → select next sibling
28
+ */
29
+ onNavigate: (dx: number, dy: number) => void;
30
+ onSelectRoot: () => void;
31
+ }
32
+ export declare function useKeyboard(opts: KeyboardOptions): void;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Render a markdown string to sanitized HTML. Returns `''` for
3
+ * empty input so the caller can use the result in a `v-html` v-if
4
+ * without a separate guard.
5
+ */
6
+ export declare function renderMarkdown(src: string): string;
@@ -0,0 +1,35 @@
1
+ import { type Ref } from 'vue';
2
+ export interface PanZoomOptions {
3
+ minScale?: number;
4
+ maxScale?: number;
5
+ step?: number;
6
+ getContainer: () => HTMLElement | null;
7
+ }
8
+ export interface MarqueeRect {
9
+ x: number;
10
+ y: number;
11
+ width: number;
12
+ height: number;
13
+ }
14
+ export declare function usePanZoom(opts: PanZoomOptions): {
15
+ scale: Ref<number, number>;
16
+ offsetX: Ref<number, number>;
17
+ offsetY: Ref<number, number>;
18
+ isPanning: Ref<boolean, boolean>;
19
+ onWheel: (e: WheelEvent) => void;
20
+ zoomIn: () => void;
21
+ zoomOut: () => void;
22
+ startPan: (e: PointerEvent | MouseEvent) => void;
23
+ startMarquee: (worldX: number, worldY: number) => void;
24
+ updateMarquee: (worldX: number, worldY: number) => void;
25
+ isMarquee: Ref<boolean, boolean>;
26
+ marquee: {
27
+ x: number;
28
+ y: number;
29
+ width: number;
30
+ height: number;
31
+ };
32
+ marqueeVersion: Ref<number, number>;
33
+ setOnMarqueeEnd: (cb: (() => void) | null) => void;
34
+ resetView: (layoutWidth: number, layoutHeight: number, rootY: number, padding?: number) => void;
35
+ };
@@ -0,0 +1,29 @@
1
+ /** Strip the opening and closing ``` fences from a code block,
2
+ * returning just the body. Handles both ``` and ~~~ markers. */
3
+ export declare function stripCodeFence(raw: string): string;
4
+ /** Detect the info-string from the opening fence. Returns an
5
+ * empty string when the block has no fence or the language
6
+ * isn't one of our registered ones (so callers can fall back
7
+ * to a plain `<pre>`). */
8
+ export declare function codeLang(raw: string): string;
9
+ /** Run highlight.js on a code body and return sanitized HTML.
10
+ * Falls back to an escaped plain-text version when the language
11
+ * isn't registered — never throws. `body` should already be
12
+ * fence-stripped (see `stripCodeFence`). */
13
+ export declare function highlightCode(body: string, lang: string): string;
14
+ /** Split a pipe-delimited table into rows of cells, dropping the
15
+ * alignment separator row. Each inner array is the cells of one
16
+ * row. The first row is conventionally the header. */
17
+ export declare function tableRows(raw: string): string[][];
18
+ /** Re-join a 2-D cell array into pipe-delimited markdown. Used
19
+ * when the user edits a table in CSV/textarea form and we need
20
+ * to push it back into `richContent.raw`. */
21
+ export declare function rowsToTable(rows: string[][]): string;
22
+ /** Sort a 2-D cell array in place around a chosen column. The
23
+ * first row is the header and stays pinned at the top.
24
+ * Direction is `'asc'` | `'desc'`. When every value in the
25
+ * column parses as a finite number the sort is numeric,
26
+ * otherwise lexical (locale-aware). Stable across equal keys.
27
+ * Doesn't mutate the input. */
28
+ export type SortDir = 'asc' | 'desc';
29
+ export declare function sortTable(rows: string[][], col: number, dir: SortDir): string[][];
@@ -0,0 +1,144 @@
1
+ export interface LayoutNode {
2
+ id: string;
3
+ text: string;
4
+ depth: number;
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ /** Font size to render this node's text at, in px. */
10
+ fontSize: number;
11
+ isRoot: boolean;
12
+ collapsed?: boolean;
13
+ side: 1 | -1;
14
+ /**
15
+ * Direction this node's children fan out in: 'right' (default for
16
+ * mindmap right side / tree), 'left' (mindmap left side), or 'down'
17
+ * (org mode).
18
+ */
19
+ _dir: 'right' | 'left' | 'down';
20
+ /** Direction this node's children fan out in, as a signed scalar
21
+ * (1 = right, -1 = left). Mirrors `_dir` for callers that need
22
+ * a number. Kept in sync by applyDoLayout and forceRight — when
23
+ * the height-based balancer moves a child to the opposite side,
24
+ * the whole subtree gets its `side` / `_dir` / `_dirRight`
25
+ * re-stamped so descendants fan the right way. */
26
+ _dirRight: 1 | -1;
27
+ /** Layout-only: vertical extent of this node's subtree (post-order
28
+ * walk result, read by layoutHorizontal). Not for public use. */
29
+ _subtreeH: number;
30
+ /** Layout-only: horizontal extent of this node's subtree (read by
31
+ * layoutVertical / org mode). Not for public use. */
32
+ _subtreeW: number;
33
+ /** Optional embedded image (mirrored from MindMapNode.image).
34
+ * The renderer uses src/width/height; naturalW/H lock the
35
+ * resize aspect ratio. */
36
+ image?: MindMapImage;
37
+ /** Mirrored from MindMapNode.link. Read by the renderer to
38
+ * show a link icon next to the text. */
39
+ link?: {
40
+ url: string;
41
+ };
42
+ /** Mirrored from MindMapNode.note. Read by the renderer to
43
+ * show a note icon next to the text. */
44
+ note?: {
45
+ text: string;
46
+ };
47
+ /** Mirrored from MindMapNode.richContent. Read by the renderer
48
+ * to show a small framed body under the node title (code / list /
49
+ * table / paragraph). Undefined means the node is plain text
50
+ * only — the default behaviour, unchanged from before this
51
+ * field was introduced. */
52
+ richContent?: RichContent;
53
+ /** Inset (px) the SVG edge anchor should retreat from the
54
+ * geometric box edge on the in-side, to land at the visible
55
+ * content edge instead. Set to `.zm-node` padding +
56
+ * `.zm-rich` padding + 2 for code/table nodes (their visible
57
+ * content sits well inside the box); 0 for plain nodes (the
58
+ * geometric edge IS the visible edge). Used by lineAnchor
59
+ * in MindMap.vue — non-zero for nodes whose first child of
60
+ * the line would otherwise appear to pierce the rich body. */
61
+ _richInsetX?: number;
62
+ children: LayoutNode[];
63
+ parent: LayoutNode | null;
64
+ }
65
+ import type { MindMapNode, MindMapImage, RichContent } from '../types';
66
+ /** Return the rendered font size for a node at the given depth, scaled
67
+ * by the host's `theme.fontSize` (default 14). The base table is
68
+ * tuned at 14px; values scale linearly so a 30px theme produces
69
+ * roughly 2.14× larger nodes. */
70
+ declare function fontAt(depth: number, baseFontSize?: number): number;
71
+ declare function heightAt(depth: number, baseFontSize?: number): number;
72
+ /** Max text-label width in px. MUST match `max-width` on `.zm-text`
73
+ * in MindMap.vue. The layout reserves this much room for the label
74
+ * regardless of how long the actual text is — the DOM then truncates
75
+ * with `text-overflow: ellipsis`. Without this cap, a long string
76
+ * pushes the rendered node box past the layout's reserved width and
77
+ * the line anchor (computed from layout width) ends up inside the
78
+ * box. The 200px default is the same value `flow-mindmap` shipped
79
+ * with before; keeping it keeps edge anchors stable. */
80
+ export declare const TEXT_MAX_W = 200;
81
+ export type LayoutMode = 'mindmap' | 'tree' | 'org';
82
+ export interface LayoutOptions {
83
+ mode?: LayoutMode;
84
+ /** @deprecated kept for API compat; ignored in 1.html-style layout. */
85
+ balanced?: boolean;
86
+ /** Base font size (px) used to scale node metrics (font/height/
87
+ * min-width). The internal tier table is tuned for 14px; values
88
+ * scale linearly. Default 14. */
89
+ baseFontSize?: number;
90
+ /**
91
+ * When true, layout() leaves each LayoutNode's existing x/y in
92
+ * place — it still does the doLayout split / redirect / stack
93
+ * walk, but skips writing to child.x / child.y. Used after a
94
+ * drag: we commit the offset into the data tree, clear the
95
+ * per-node offset map, then re-run layout with this flag so
96
+ * the dragged node (and its subtree) stay where the user put
97
+ * them. The root is still forced to (0, 0) — to put the
98
+ * dragged node at a new position, the surrounding tree moves
99
+ * relative to it. New nodes added later get the algorithmic
100
+ * position since their LayoutNode has x = 0, y = 0.
101
+ */
102
+ preservePositions?: boolean;
103
+ /**
104
+ * Per-node measured size of the rendered rich body (the
105
+ * `<div class="zm-rich">` element above the title), in px. The
106
+ * caller (MindMap.vue) populates this after each render with
107
+ * `el.offsetWidth` / `el.offsetHeight`; layout reads it for
108
+ * nodes that carry code / table rich content. When a node has
109
+ * a measured size we use it directly so the box grows /
110
+ * shrinks to fit the content. When the caller hasn't
111
+ * measured a node yet we fall back to the fixed floor / cap.
112
+ * IDs not present in the map are simply ignored — useful for
113
+ * the very first render before measurement has happened.
114
+ */
115
+ richHeights?: Record<string, number>;
116
+ richWidths?: Record<string, number>;
117
+ }
118
+ export declare function layout(root: MindMapNode, options?: LayoutOptions): {
119
+ root: LayoutNode;
120
+ width: number;
121
+ height: number;
122
+ vbX: number;
123
+ vbY: number;
124
+ vbW: number;
125
+ vbH: number;
126
+ };
127
+ export declare const LAYOUT: {
128
+ /** Legacy single-size values for callers that still expect them. */
129
+ NODE_W: number;
130
+ NODE_H: number;
131
+ NODE_FONTS: number[];
132
+ NODE_HEIGHTS: number[];
133
+ NODE_MIN_W: number[];
134
+ NODE_PAD_H: number[];
135
+ NODE_FONT_WEIGHTS: number[];
136
+ H_GAP: number;
137
+ V_GAP: number;
138
+ SIDE_PADDING: number;
139
+ heightAt: typeof heightAt;
140
+ fontAt: typeof fontAt;
141
+ /** Clear the text-measurement cache (call after font load). */
142
+ clearMeasureCache: () => void;
143
+ };
144
+ export {};