flow-mindmap 0.4.0 → 0.4.2

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,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 {};
@@ -0,0 +1,43 @@
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[];
@@ -0,0 +1,18 @@
1
+ import MindMap from './components/MindMap.vue';
2
+ import Outline from './components/Outline.vue';
3
+ import Drawer from './components/Drawer.vue';
4
+ import DataPanel from './components/DataPanel.vue';
5
+ import MarkdownPanel from './components/MarkdownPanel.vue';
6
+ import SettingsPanel from './components/SettingsPanel.vue';
7
+ import NotePanel from './components/NotePanel.vue';
8
+ import MindMapApp from './App.vue';
9
+ import type { App } from 'vue';
10
+ import type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose, MindMapSettings, NodeStyle, LineStyle, LayoutMode, BranchPalette, BranchPaletteId, RichContent } from './types';
11
+ import { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown, markdownToRichMindMap, richBlockToMarkdown } from './tree';
12
+ export type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose, MindMapSettings, NodeStyle, LineStyle, LayoutMode, BranchPalette, BranchPaletteId, RichContent };
13
+ export { MindMap, Outline, Drawer, DataPanel, MarkdownPanel, SettingsPanel, NotePanel, MindMapApp };
14
+ export { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown, markdownToRichMindMap, richBlockToMarkdown };
15
+ declare const plugin: {
16
+ install(app: App): void;
17
+ };
18
+ export default plugin;