flow-mindmap 0.3.8 → 0.4.0

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.
@@ -1,144 +0,0 @@
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 {};
@@ -1,43 +0,0 @@
1
- export interface BranchPalette {
2
- id: string;
3
- name: string;
4
- /** Hex colors cycled across top-level branches, in display order. */
5
- colors: string[];
6
- }
7
- export declare const BUILTIN_PALETTES: readonly BranchPalette[];
8
- /**
9
- * Resolve a palette by id from a combined list of built-ins and
10
- * user-defined custom palettes. Falls back to the default palette
11
- * if `id` is missing or points at a deleted custom palette. Pure
12
- * — no DOM, no reactive deps — so it can be called from a computed
13
- * or a watch.
14
- */
15
- export declare function resolvePalette(id: string, customPalettes?: readonly BranchPalette[]): BranchPalette;
16
- /**
17
- * Parse a free-form text blob into a cleaned color array. Accepts:
18
- *
19
- * 1. **Hex codes** — `#rgb` / `#rgba` / `#rrggbb` / `#rrggbbaa`,
20
- * with or without the leading `#`. The alpha channel on
21
- * 4- or 8-digit hex is silently dropped.
22
- * 2. **`rgb()` / `rgba()` functions** — `rgb(255, 99, 71)`,
23
- * `rgba(255,99,71,0.5)`. Whitespace and percentage values
24
- * are both accepted (matches CSS rules). Alpha dropped.
25
- * 3. **CSS named colors** — the 30 most common (`red`, `tomato`,
26
- * `coral`, `teal`, …). A small curated set keeps the parser
27
- * from silently accepting typos that look color-ish
28
- * (`tan`, `peru` are in; `chartreuse1` is not).
29
- * 4. **JSON / JS array** — `['#f87171', 'red']`,
30
- * `["#f87171","rgb(0,0,255)"]`, even a single-line
31
- * `["red","blue"]`. Bracket and quote chars are tolerated
32
- * so a copy-pasted `[…]` round-trips cleanly.
33
- * 5. **Any-delimiter blob** — the parser scans the raw text for
34
- * color-shaped substrings rather than splitting on commas,
35
- * so a user can paste `rgb(255, 0, 0), #0f0, blue` and every
36
- * piece lands.
37
- *
38
- * Malformed tokens are dropped silently (consistent with the
39
- * rest of the canvas's "paste messy text" UX). Returns at most
40
- * `maxColors` entries; output is lowercased `#rrggbb` for stable
41
- * dedup and direct comparison with `BUILTIN_PALETTES`.
42
- */
43
- export declare function parsePaletteInput(text: string, maxColors?: number): string[];
package/dist/entry.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import MindMap from './components/MindMap.vue';
2
- import type { App } from 'vue';
3
- import type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose, MindMapSettings, NodeStyle, LineStyle, LayoutMode, BranchPalette, BranchPaletteId, RichContent } from './types';
4
- import { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown, markdownToRichMindMap, richBlockToMarkdown } from './tree';
5
- export type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose, MindMapSettings, NodeStyle, LineStyle, LayoutMode, BranchPalette, BranchPaletteId, RichContent };
6
- export { MindMap };
7
- export { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown, markdownToRichMindMap, richBlockToMarkdown };
8
- declare const plugin: {
9
- install(app: App): void;
10
- };
11
- export default plugin;
package/dist/tree.d.ts DELETED
@@ -1,96 +0,0 @@
1
- import type { MindMapNode } from './types';
2
- export declare function uid(): string;
3
- export declare function clone<T>(o: T): T;
4
- export declare function findNode(root: MindMapNode, id: string): MindMapNode | null;
5
- export declare function findParent(root: MindMapNode, id: string, parent?: MindMapNode | null): MindMapNode | null;
6
- export declare function removeNode(root: MindMapNode, id: string): boolean;
7
- /** Replace the text of a node by id. Returns true on success, false
8
- * if the node was not found. No-op on an empty / same string. */
9
- export declare function setNodeText(root: MindMapNode, id: string, text: string): boolean;
10
- /** Position relative to a target node when moving a sibling. */
11
- export type MovePosition = 'before' | 'after' | 'child';
12
- /** Move a node to a new location in the tree.
13
- * - 'before' / 'after': insert as a sibling of the target at that slot
14
- * (target's parent's children array).
15
- * - 'child': insert as the last child of the target.
16
- * No-op (returns false) if src === root, or if the move would
17
- * create a cycle (i.e. the target lives inside the src subtree, or
18
- * src is already in the target's desired position). */
19
- export declare function moveNode(root: MindMapNode, srcId: string, targetId: string, position: MovePosition): boolean;
20
- export declare function addChild(root: MindMapNode, parentId: string, text?: string): MindMapNode | null;
21
- export declare function addSibling(root: MindMapNode, nodeId: string, text?: string): MindMapNode | null;
22
- /**
23
- * Insert a new sibling node BEFORE the given node (Shift+Enter in xmind).
24
- * Returns the new node, or null if the target is the root.
25
- */
26
- export declare function addSiblingBefore(root: MindMapNode, nodeId: string, text?: string): MindMapNode | null;
27
- /**
28
- * Deep-clone a node (with all its descendants) and insert the copy as a
29
- * sibling immediately after the original. New ids are generated so the
30
- * result is a real duplicate. Returns the new node, or null if the
31
- * target is the root.
32
- */
33
- export declare function duplicateNode(root: MindMapNode, nodeId: string): MindMapNode | null;
34
- export declare function countDescendants(n: MindMapNode): number;
35
- export declare const DEFAULT_NEW_NODE_TEXT = "\u65B0\u8282\u70B9";
36
- /**
37
- * Parse a Markdown string into a MindMapNode tree. Each heading
38
- * becomes a node; its level sets the depth.
39
- * - `# Title` → root text (overrides `rootText`)
40
- * - `## Sub` → child of the previous #/##/... heading
41
- * - bullet / paragraph text between headings → first child
42
- * of the preceding heading (so a `# Topic\n- detail` tree
43
- * gives one root node with one child).
44
- *
45
- * Inline fields parsed from a heading's body (in order, attached
46
- * to the heading that precedes them):
47
- * - `![alt](url)` → image
48
- * - `[label](url)` → link (label becomes the node's text)
49
- * - ` ```note ... ``` ` → note (the fence body becomes note.text)
50
- *
51
- * Empty input, or input with no `#` heading, returns a single
52
- * root with the fallback text.
53
- */
54
- export declare function markdownToMindMap(md: string, rootText?: string): MindMapNode;
55
- /**
56
- * Round-trip-safe Markdown export of a MindMapNode tree. Each
57
- * heading is emitted as `#…`, then any inline fields (link /
58
- * image / note) in a fixed order so the same source produces
59
- * byte-stable output across re-exports.
60
- *
61
- * The `note` field round-trips through a ` ```note ` fence so a
62
- * user opening the export in any markdown editor sees a clearly
63
- * labeled block. The link is emitted as a standard `[label](url)`
64
- * with the node's text as the label — this keeps the export
65
- * human-readable and lets `markdownToMindMap` re-attach the
66
- * link to the right heading.
67
- */
68
- export declare function mindMapToMarkdown(n: MindMapNode, depth?: number): string;
69
- /**
70
- * Parse a whole markdown document into a MindMapNode tree where
71
- * every block (heading, paragraph, list, code fence, table)
72
- * becomes a node. Body blocks carry their original markdown
73
- * payload in `node.richContent` so the renderer can show code,
74
- * tables, lists, etc. inside the node box. Headings form the
75
- * hierarchy; everything else is attached to the most recent
76
- * heading as a child (or to the synthetic root if no heading
77
- * has been seen yet).
78
- *
79
- * Unlike `markdownToMindMap`, this does NOT collapse body into
80
- * a single child of the heading, and the depth is unbounded —
81
- * a paragraph under `## Foo` becomes a child of `Foo`, and a
82
- * paragraph that follows a list under the same heading becomes
83
- * a sibling of that list, etc. This is the mode the user
84
- * asked for: "every paragraph becomes a child, no depth limit".
85
- *
86
- * A document with no `#` heading still produces a valid tree —
87
- * every block lands under the synthetic root.
88
- */
89
- export declare function markdownToRichMindMap(md: string, rootText?: string): MindMapNode;
90
- /**
91
- * Serialize a single node's rich body (if any) back to the
92
- * original markdown it came from. Used by `mindMapToMarkdown`
93
- * to round-trip a tree built by `markdownToRichMindMap`.
94
- * Returns '' when the node has no rich body.
95
- */
96
- export declare function richBlockToMarkdown(n: MindMapNode): string;
package/dist/types.d.ts DELETED
@@ -1,270 +0,0 @@
1
- export interface MindMapNode {
2
- id: string;
3
- text: string;
4
- children: MindMapNode[];
5
- collapsed?: boolean;
6
- /**
7
- * Reserved for the layout algorithm — do not set or read from
8
- * your own code. After a drag, MindMap writes the dragged
9
- * node's offset into the data tree so a subsequent layout with
10
- * `preservePositions: true` can keep the node where the user
11
- * put it. Cleared on the next data-mutating action (add,
12
- * remove, edit, import) so unrelated re-layouts don't keep
13
- * stale overrides around.
14
- */
15
- _x?: number;
16
- _y?: number;
17
- /**
18
- * Optional embedded image shown above the node text. The
19
- * image is stored as either a remote URL (preferred) or a
20
- * data: URL (fallback for local-file uploads); width/height
21
- * reflect the rendered size, which the user can resize via
22
- * a drag handle. naturalW/naturalH preserve the source
23
- * aspect ratio so a resize keeps the original proportions.
24
- */
25
- image?: MindMapImage;
26
- /**
27
- * Optional external link. When set, the node renders a
28
- * small link icon next to its text; clicking the icon
29
- * navigates to `url` in a new tab. No validation is
30
- * performed at write time — the rendering layer is
31
- * responsible for rejecting dangerous schemes (javascript:,
32
- * data:, …) before following the link.
33
- */
34
- link?: {
35
- url: string;
36
- };
37
- /**
38
- * Optional free-form note. When set, the node renders a
39
- * small note icon next to its text; clicking the icon
40
- * expands an inline textarea below the node for editing,
41
- * hovering the icon shows a tooltip preview. An empty
42
- * `text` field is treated as "no note" by the UI.
43
- */
44
- note?: {
45
- text: string;
46
- };
47
- /**
48
- * Optional rich body. When set, the node renders the raw
49
- * markdown payload in a small framed block under the title
50
- * (code fences get monospace styling, lists get bullet
51
- * markers, tables get a mini grid, paragraphs get plain
52
- * text). Produced by `markdownToRichMindMap` so a whole
53
- * markdown document can be previewed as a mindmap without
54
- * losing its body content. The first line of `raw` is
55
- * still available as `text` so the node always has a
56
- * meaningful label.
57
- */
58
- richContent?: RichContent;
59
- }
60
- /**
61
- * A node body that came from a markdown block. `raw` is the
62
- * original markdown source for the block (preserved verbatim so
63
- * `mindMapToMarkdown` can re-emit it byte-for-byte). `kind`
64
- * tells the renderer which layout to use.
65
- */
66
- export interface RichContent {
67
- kind: 'code' | 'list' | 'table' | 'paragraph';
68
- /** Original markdown source. Always non-empty. */
69
- raw: string;
70
- /**
71
- * Optional language tag for code blocks (the info string after
72
- * the opening fence). `undefined` for non-code kinds.
73
- */
74
- lang?: string;
75
- }
76
- export interface MindMapImage {
77
- /** Remote URL or data URL. Always a string — never undefined. */
78
- src: string;
79
- /** Source image intrinsic size, in px. Used to lock aspect
80
- * ratio during a user-driven resize. */
81
- naturalW: number;
82
- naturalH: number;
83
- /** Current rendered size, in px. Drag handle writes to these
84
- * fields. Clamped to a sane range by the layout (≥24, ≤400). */
85
- width: number;
86
- height: number;
87
- }
88
- export interface MindMapOptions {
89
- data: MindMapNode;
90
- theme?: MindMapTheme;
91
- }
92
- export interface MindMapTheme {
93
- rootBg?: string;
94
- rootText?: string;
95
- branchBg?: string;
96
- branchText?: string;
97
- lineColor?: string;
98
- bgColor?: string;
99
- fontSize?: number;
100
- /** Stroke width of SVG connecting paths at the *parent-end* of the
101
- * edge, in px. Default 2.2. */
102
- lineWidthStart?: number;
103
- /** Stroke width at the *child-end* of the edge, in px. Default 0.8. */
104
- lineWidthEnd?: number;
105
- /**
106
- * When true, each top-level branch gets its own color (root stays
107
- * neutral, every child[0] of root takes a different hue, and that
108
- * hue propagates down the subtree). Default false.
109
- */
110
- rainbowBranch?: boolean;
111
- }
112
- export type LineStyle = 'curve' | 'straight';
113
- export type LayoutMode = 'mindmap' | 'tree' | 'org';
114
- /** Identifier for a branch palette — the id of a built-in (e.g.
115
- * 'default', 'classic', 'vivid', 'dev', 'mint') or a user-defined
116
- * custom palette. Strings rather than a string union so users
117
- * can add their own ids without recompiling the type. */
118
- export type BranchPaletteId = string;
119
- /**
120
- * A named 8-color palette cycled across top-level branches when
121
- * `rainbowBranch` is on. Exposed in the public API so the library
122
- * consumer can register their own scheme (e.g. a corporate brand
123
- * palette) via `setBranchPalette` / `customPalettes`.
124
- */
125
- export interface BranchPalette {
126
- id: BranchPaletteId;
127
- name: string;
128
- /** Hex colors cycled across top-level branches, in display order.
129
- * When a palette has fewer than the number of branches, colors
130
- * wrap around with modulo. */
131
- colors: string[];
132
- }
133
- export interface MindMapSettings {
134
- /** When the user adds a new node or finishes a drag, automatically
135
- * snap the layout back to balanced mode. Default false. */
136
- autoBalanceOnChange: boolean;
137
- /** Stroke width of SVG edges at the parent end. */
138
- lineWidthStart: number;
139
- /** Stroke width of SVG edges at the child end. */
140
- lineWidthEnd: number;
141
- /** Color-cycle the top-level branches. */
142
- rainbowBranch: boolean;
143
- /** Which named palette to use when rainbowBranch is on. Built-in
144
- * ids: 'default' | 'classic' | 'vivid' | 'dev' | 'mint'. Any
145
- * custom palette id in `customPalettes` is also valid. Default
146
- * 'default'. */
147
- branchPaletteId: BranchPaletteId;
148
- /** User-defined palettes. The settings panel lets the user add,
149
- * edit (via a textarea of hex codes), and delete entries. The
150
- * canvas treats these as first-class palettes alongside the
151
- * built-ins. Persisted by the host app. */
152
- customPalettes: BranchPalette[];
153
- /** Edge shape between parent and child. 'curve' = fish-gill bezier
154
- * (xmind default), 'straight' = direct line segment. */
155
- lineStyle: LineStyle;
156
- /** Layout mode (1.html parity). 'mindmap' = center + left/right
157
- * fans; 'tree' = single column expanding to the right; 'org' =
158
- * downward hierarchy. Default 'mindmap'. */
159
- layoutMode: LayoutMode;
160
- /** When true (default), each edge tapers independently — its
161
- * parent-end width comes from the parent node's tier and its
162
- * child-end width comes from `lineWidthEnd`. Visually you get
163
- * discrete ribbons where the parent side of a level-2 edge can
164
- * be thicker than the child side of a level-1 edge.
165
- * When false, the whole tree forms a single tapered band:
166
- * every edge's parent end = the previous edge's child end, so
167
- * widths interpolate continuously from root to leaves. */
168
- taperedEdge: boolean;
169
- /** When true, every node shows a small badge with its zero-based
170
- * position in its parent's children array ("1.", "2.", "3.").
171
- * Default false — useful when verifying the data-tree order
172
- * against the visual layout. */
173
- showOrderBadge: boolean;
174
- }
175
- export interface NodeStyle {
176
- bg?: string;
177
- textColor?: string;
178
- borderColor?: string;
179
- fontWeight?: 400 | 600;
180
- }
181
- export interface MindMapExpose {
182
- addChild: (parentId: string) => void;
183
- addSibling: (nodeId: string) => void;
184
- removeNode: (nodeId: string) => void;
185
- duplicateNode: (nodeId: string) => void;
186
- /** Set a node's text (no-op if unchanged). Used by the outline
187
- * panel's inline edit; the canvas has its own dblclick → input
188
- * flow. */
189
- setNodeText: (nodeId: string, text: string) => void;
190
- /** Move a node to a new location. `position` is relative to
191
- * `targetId`: 'before' / 'after' insert as siblings, 'child'
192
- * makes it the last child of target. Used by the outline panel's
193
- * drag-and-drop. Returns true on success, false (no-op) if the
194
- * move would create a cycle or hit another invalid case. */
195
- moveNode: (srcId: string, targetId: string, position: 'before' | 'after' | 'child') => boolean;
196
- getData: () => MindMapNode;
197
- setData: (data: MindMapNode) => void;
198
- resetView: () => void;
199
- exportData: () => string;
200
- importData: (json: string) => boolean;
201
- /** Serialize the current data tree as markdown. */
202
- getMarkdown: () => string;
203
- /** Replace the data tree with the result of parsing `md`. The
204
- * `emitMarkdownChange` flag (default true) controls whether the
205
- * change is also echoed via `markdownChange` — set false to
206
- * avoid feedback loops when the host just wrote back the
207
- * value the component emitted. */
208
- setMarkdown: (md: string, emitMarkdownChange?: boolean) => void;
209
- setBalanced: (value: boolean) => void;
210
- isBalanced: () => boolean;
211
- balance: () => void;
212
- /** Apply or update the per-node style override (empty object clears it). */
213
- applyNodeStyle: (nodeId: string, style: NodeStyle) => void;
214
- /** Read the current per-node style override. */
215
- getNodeStyle: (nodeId: string) => NodeStyle;
216
- /** Set a node's external link. Pass an empty string to clear. */
217
- applyNodeLink: (nodeId: string, url: string) => void;
218
- /** Remove a node's link (no-op if absent). */
219
- removeNodeLink: (nodeId: string) => void;
220
- /** Set a node's note text. Pass an empty string to clear. */
221
- applyNodeNote: (nodeId: string, text: string) => void;
222
- /** Remove a node's note (no-op if absent). */
223
- removeNodeNote: (nodeId: string) => void;
224
- /** Set a node's image from a URL or data: URI. Fetches the
225
- * asset to read its natural dimensions; clamps to IMG_MAX_W
226
- * with a preserved aspect ratio. Empty string removes the
227
- * image. */
228
- applyNodeImageByUrl: (nodeId: string, url: string) => void;
229
- /** Set a node's image from a fully-resolved MindMapImage.
230
- * Used by the file-picker flow (readImageFile) and the drag
231
- * resize handle. Prefer `applyNodeImageByUrl` from the
232
- * panel — it fetches the natural dimensions for you. */
233
- applyNodeImage: (nodeId: string, image: MindMapImage) => void;
234
- /** Remove a node's image (no-op if absent). */
235
- removeNodeImage: (nodeId: string) => void;
236
- /** Set a node's rich body (code block or table). Pass `null`
237
- * to remove the body. The renderer reads `kind` to decide
238
- * which preview layout to use. */
239
- applyNodeRichContent: (nodeId: string, content: {
240
- kind: 'code' | 'table';
241
- raw: string;
242
- lang?: string;
243
- } | null) => void;
244
- undo: () => void;
245
- redo: () => void;
246
- canUndo: () => boolean;
247
- canRedo: () => boolean;
248
- /** Apply a partial settings object — keys you omit are left as-is. */
249
- applySettings: (s: Partial<MindMapSettings>) => void;
250
- /** Read the current effective settings. */
251
- getSettings: () => MindMapSettings;
252
- /** Set the active branch palette by id. The id may be a built-in
253
- * ('default' / 'classic' / 'vivid' / 'dev' / 'mint') or a custom
254
- * palette id from `customPalettes`. No-op if the id is unknown. */
255
- setBranchPalette: (id: BranchPaletteId) => void;
256
- /** Read the active palette id. */
257
- getBranchPalette: () => BranchPaletteId;
258
- /** Read every palette the canvas knows about — built-ins first,
259
- * then the user's custom palettes. Useful for the host app to
260
- * render a picker. */
261
- getBranchPalettes: () => BranchPalette[];
262
- /** Stroke width used for the parent end of an edge that starts at
263
- * a node of the given depth. Lets the canvas taper sharply
264
- * (root → 1st → 2nd → 3rd+) instead of using a single global
265
- * width. */
266
- lineWidthForDepth: (depth: number) => number;
267
- /** Stroke width used for the child end of an edge that ends at
268
- * a node of the given depth. */
269
- endWidthForDepth: (depth: number) => number;
270
- }