flow-mindmap 0.1.1-beta.1 → 0.2.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.
package/README.md CHANGED
@@ -62,6 +62,48 @@ const data: MindMapNode = {
62
62
  </template>
63
63
  ```
64
64
 
65
+ ### 从 Markdown 渲染
66
+
67
+ ```vue
68
+ <script setup lang="ts">
69
+ import { ref } from 'vue'
70
+ import { MindMap } from 'flow-mindmap'
71
+ import 'flow-mindmap/style.css'
72
+
73
+ const md = ref(`# 项目计划
74
+
75
+ ## 第一阶段
76
+
77
+ 调研 / 设计
78
+
79
+ ## 第二阶段
80
+
81
+ 实现
82
+
83
+ ## 第三阶段
84
+
85
+ 上线`)
86
+
87
+ // 监听变化把 markdown 同步回外部存储(可选)
88
+ function onMdChange(next: string) {
89
+ // 写入 localStorage / autosave / 远端等
90
+ console.log('md changed, length =', next.length)
91
+ }
92
+ </script>
93
+
94
+ <template>
95
+ <MindMap
96
+ :markdown="md"
97
+ :theme="{ fontSize: 16, rainbowBranch: true }"
98
+ :line-colors="['#5eead4', '#fbbf24', '#f472b6', '#a78bfa']"
99
+ @markdown-change="onMdChange"
100
+ style="width: 100vw; height: 100vh"
101
+ />
102
+ </template>
103
+ ```
104
+
105
+ `markdown` prop 接受标准 markdown:`# / ## / ###` 作为节点层级;紧跟 heading 的 `[label](url)` 作为节点的 link;` ```note ... ``` ` 围栏作为节点的 note;`![alt](url)` 作为图片。改节点文字会自动 emit `markdownChange`,你可以把它写回输入框或远端。
106
+
65
107
  ## Props
66
108
 
67
109
  | Prop | Type | Default | 说明 |
@@ -70,6 +112,8 @@ const data: MindMapNode = {
70
112
  | `readonly` | `boolean` | `false` | 只读模式:禁用增删改、拖拽、编辑输入框。 |
71
113
  | `previewMode` | `boolean` | `false` | 预览模式:隐藏画布自带工具栏,只保留节点和折叠/调整手柄。适合做截图、嵌入展示。 |
72
114
  | `theme` | [`MindMapTheme`](#数据类型) | — | 主题色/字号/连线粗细等外观配置,见下表。 |
115
+ | `markdown` | `string` | — | 可选:传入 markdown 文本,内部解析为 `data`。**与 `data` 二选一**,传了 `markdown` 后 `data` 被忽略。双向同步:数据变化时通过 `markdownChange` 事件回传序列化结果。 |
116
+ | `lineColors` | `string[]` | — | 可选:顶层分支**连线**颜色列表(hex / rgb / 命名色)。优先级高于 `branchPaletteId` / `customPalettes`;留空走 palette 流程。 |
73
117
 
74
118
  ### `MindMapTheme` 字段
75
119
 
@@ -81,7 +125,7 @@ const data: MindMapNode = {
81
125
  | `branchText` | `string` | — | 普通节点文字色 |
82
126
  | `lineColor` | `string` | — | 连线颜色 |
83
127
  | `bgColor` | `string` | — | 画布背景色 |
84
- | `fontSize` | `number` | | 基础字号(px) |
128
+ | `fontSize` | `number` | `14` | 基础字号(px)。**节点的实际尺寸(高度/最小宽度/内边距/文本宽度)会按 `fontSize / 14` 等比缩放**——`fontSize=28` 时所有节点都会变成两倍大;`fontSize=10` 时一半。 |
85
129
  | `lineWidthStart` | `number` | `2.2` | 父端连线粗细(px) |
86
130
  | `lineWidthEnd` | `number` | `0.8` | 子端连线粗细(px) |
87
131
  | `rainbowBranch` | `boolean` | `false` | 顶层分支按色板循环配色 |
@@ -93,6 +137,7 @@ const data: MindMapNode = {
93
137
  | `change` | `MindMapNode` | 数据变更(增删改、导入、拖动)后触发,载荷是**新的整棵根节点**。 |
94
138
  | `select` | `MindMapNode \| null` | 用户点击节点时触发;`null` 表示点空白处取消选中。 |
95
139
  | `edit-note` | `nodeId: string` | 用户点击节点笔记图标 / 右键"添加/编辑笔记"时触发,由父组件决定如何展示笔记编辑界面。 |
140
+ | `markdownChange` | `markdown: string` | 当使用了 `markdown` prop 且内部数据变化时触发,载荷是重新序列化后的 markdown 文本。`markdown` prop 写入触发时**不会**回环 emit。 |
96
141
 
97
142
  ## Expose 方法(通过 `ref` 访问)
98
143
 
@@ -148,6 +193,8 @@ mm.value.addChild('a') // 给 id=a 的节点加一个子节点
148
193
  | ---- | ---- |
149
194
  | `exportData()` | 返回当前数据的 JSON 字符串。 |
150
195
  | `importData(json)` | 从 JSON 字符串恢复数据,成功返回 `true`。 |
196
+ | `getMarkdown()` | 返回当前数据序列化后的 markdown 字符串。 |
197
+ | `setMarkdown(md, emitMarkdownChange?)` | 用 markdown 解析结果替换数据。`emitMarkdownChange` 默认 `true`,传 `false` 可避免回环(比如用 `markdown` prop 接收外部值后写回时)。 |
151
198
 
152
199
  ### 设置项
153
200
 
@@ -268,6 +315,8 @@ import {
268
315
  removeNode, // (root, id) => 移除子树
269
316
  addChild, // (parent, text) => 新子节点
270
317
  addSibling, // (node, text) => 新同级节点
318
+ markdownToMindMap, // (md, rootText?) => MindMapNode — 与 MindMap 内部解析逻辑一致
319
+ mindMapToMarkdown, // (node, depth?) => string — 与 MindMap 内部序列化逻辑一致
271
320
  } from 'flow-mindmap'
272
321
  ```
273
322
 
@@ -44,16 +44,31 @@ export interface LayoutNode {
44
44
  note?: {
45
45
  text: string;
46
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;
47
53
  children: LayoutNode[];
48
54
  parent: LayoutNode | null;
49
55
  }
50
- import type { MindMapNode, MindMapImage } from '../types';
56
+ import type { MindMapNode, MindMapImage, RichContent } from '../types';
51
57
  /** Return the rendered font size for a node at the given depth, scaled
52
58
  * by the host's `theme.fontSize` (default 14). The base table is
53
59
  * tuned at 14px; values scale linearly so a 30px theme produces
54
60
  * roughly 2.14× larger nodes. */
55
61
  declare function fontAt(depth: number, baseFontSize?: number): number;
56
62
  declare function heightAt(depth: number, baseFontSize?: number): number;
63
+ /** Max text-label width in px. MUST match `max-width` on `.zm-text`
64
+ * in MindMap.vue. The layout reserves this much room for the label
65
+ * regardless of how long the actual text is — the DOM then truncates
66
+ * with `text-overflow: ellipsis`. Without this cap, a long string
67
+ * pushes the rendered node box past the layout's reserved width and
68
+ * the line anchor (computed from layout width) ends up inside the
69
+ * box. The 200px default is the same value `flow-mindmap` shipped
70
+ * with before; keeping it keeps edge anchors stable. */
71
+ export declare const TEXT_MAX_W = 200;
57
72
  export type LayoutMode = 'mindmap' | 'tree' | 'org';
58
73
  export interface LayoutOptions {
59
74
  mode?: LayoutMode;
package/dist/entry.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import MindMap from './components/MindMap.vue';
2
2
  import type { App } from 'vue';
3
- import type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose, MindMapSettings, NodeStyle, LineStyle, LayoutMode, BranchPalette, BranchPaletteId } from './types';
4
- import { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown } from './tree';
5
- export type { MindMapNode, MindMapOptions, MindMapTheme, MindMapExpose, MindMapSettings, NodeStyle, LineStyle, LayoutMode, BranchPalette, BranchPaletteId };
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
6
  export { MindMap };
7
- export { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown };
7
+ export { uid, clone, findNode, findParent, removeNode, addChild, addSibling, markdownToMindMap, mindMapToMarkdown, markdownToRichMindMap, richBlockToMarkdown };
8
8
  declare const plugin: {
9
9
  install(app: App): void;
10
10
  };