@umbraci/jsmind 0.9.12 → 0.9.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umbraci/jsmind",
3
- "version": "0.9.12",
3
+ "version": "0.9.13",
4
4
  "description": "jsMind is a pure javascript library for mindmap, it base on html5 canvas. jsMind was released under BSD license, you can embed it in any project, if only you observe the license.",
5
5
  "main": "lib/jsmind.js",
6
6
  "module": "es/jsmind.js",
@@ -223,15 +223,16 @@ declare class jsMind {
223
223
  * Add multiple nodes to the mind map with optimized performance.
224
224
  * Supports standard jsMind formats: node_tree, node_array, and freemind with nested children structure.
225
225
  * @param {string | import('./jsmind.node.js').Node} parent_node - Parent node for all new nodes
226
- * @param {Array<{id: string, topic: string, data?: Record<string, any>, direction?: ('left'|'center'|'right'|'-1'|'0'|'1'|number), children?: Array}>} nodes_data - Array of node data objects with same format as add_node
226
+ * @param {Array<{id?: string, topic?: string, data?: Record<string, any>, direction?: ('left'|'center'|'right'|'-1'|'0'|'1'|number), children?: Array, [key: string]: any}>} nodes_data - Array of node data objects with same format as add_node
227
227
  * @returns {Array<import('./jsmind.node.js').Node|null>} Array of created nodes (flattened from all levels)
228
228
  */
229
229
  add_nodes(parent_node: string | import("./jsmind.node.js").Node, nodes_data: Array<{
230
- id: string;
231
- topic: string;
230
+ id?: string;
231
+ topic?: string;
232
232
  data?: Record<string, any>;
233
233
  direction?: ("left" | "center" | "right" | "-1" | "0" | "1" | number);
234
234
  children?: any[];
235
+ [key: string]: any;
235
236
  }>): Array<import("./jsmind.node.js").Node | null>;
236
237
  /**
237
238
  * Recursively add nodes using existing format processors.
@@ -60,14 +60,20 @@ export type MindMapMeta = {
60
60
  };
61
61
  /**
62
62
  * Node tree data item
63
+ *
64
+ * Note: When using custom fieldNames configuration, the actual property names
65
+ * in your data may differ from these type definitions. For example, if you
66
+ * configure `fieldNames: { topic: 'name' }`, your data should use 'name'
67
+ * instead of 'topic'. The types shown here represent the default field names.
63
68
  */
64
69
  export type NodeTreeData = {
65
- id: string;
66
- topic: string;
70
+ id?: string;
71
+ topic?: string;
67
72
  data?: Record<string, any>;
68
73
  direction?: (number | string);
69
74
  expanded?: boolean;
70
75
  children?: NodeTreeData[];
76
+ [key: string]: any;
71
77
  };
72
78
  /**
73
79
  * Node tree formatted payload
@@ -79,15 +85,22 @@ export type NodeTreeFormat = {
79
85
  };
80
86
  /**
81
87
  * Node array data item
88
+ *
89
+ * Note: When using custom fieldNames configuration, the actual property names
90
+ * in your data may differ from these type definitions. For example, if you
91
+ * configure `fieldNames: { topic: 'name', parentid: 'parent' }`, your data
92
+ * should use 'name' and 'parent' instead of 'topic' and 'parentid'. The types
93
+ * shown here represent the default field names.
82
94
  */
83
95
  export type NodeArrayItem = {
84
- id: string;
85
- topic: string;
96
+ id?: string;
97
+ topic?: string;
86
98
  parentid?: string;
87
99
  data?: Record<string, any>;
88
100
  direction?: (number | string);
89
101
  expanded?: boolean;
90
102
  isroot?: boolean;
103
+ [key: string]: any;
91
104
  };
92
105
  /**
93
106
  * Node array formatted payload
@@ -60,5 +60,14 @@ export type JsMindRuntimeOptions = {
60
60
  mapping?: Record<string, number | number[]>;
61
61
  id_generator?: () => string;
62
62
  };
63
+ fieldNames?: {
64
+ id?: string;
65
+ topic?: string;
66
+ children?: string;
67
+ parentid?: string;
68
+ isroot?: string;
69
+ direction?: string;
70
+ expanded?: string;
71
+ };
63
72
  plugin?: Record<string, object>;
64
73
  };
@@ -1,55 +1,246 @@
1
1
  /**
2
- * Flatten a NodeTreeFormat/NodeTreeData by id
3
- * @param {NodeTreeFormat|NodeTreeData} tree
4
- * @param {{ fields?: string[], includeStructure?: boolean }=} opts
5
- * @returns {Record<string, any>}
2
+ * Flatten a tree into a Map of nodes keyed by id.
3
+ * @param {NodeTreeFormat|NodeTreeData} tree - The tree to flatten
4
+ * @param {FlattenOptions} [opts] - Flatten options
5
+ * @returns {Map<string, FlatNode>} Map of node id -> flattened node object
6
+ * @example
7
+ * const tree = { data: { id: 'root', topic: 'Root', children: [...] } };
8
+ * const flatMap = flatten(tree);
9
+ * const rootNode = flatMap.get('root'); // { id: 'root', topic: 'Root', data: {...}, _parentid: null, _order: 0 }
6
10
  */
7
- export function flatten(tree: NodeTreeFormat | NodeTreeData, opts?: {
8
- fields?: string[];
9
- includeStructure?: boolean;
10
- } | undefined): Record<string, any>;
11
+ export function flatten(tree: NodeTreeFormat | NodeTreeData, opts?: FlattenOptions): Map<string, FlatNode>;
11
12
  /**
12
13
  * Compute diff between two snapshots
13
- * @param {NodeTreeFormat|NodeTreeData} a
14
- * @param {NodeTreeFormat|NodeTreeData} b
15
- * @param {{ fields?: string[], includeStructure?: boolean, maxSize?: number }=} opts
16
- * - fields: 可选。指定要参与 diff 的节点属性列表;默认比较所有属性(除 children)。与 includeStructure 组合使用时可同时比较 _parentid/_order。
17
- * @returns {{
18
- * created: any[],
19
- * updated: { id:string, before:any, after:any, changes: { key:string, before:any, after:any }[] }[],
20
- * deleted: any[],
21
- * truncated: boolean
22
- * }}
14
+ * @param {NodeTreeFormat|NodeTreeData} a - First snapshot (before)
15
+ * @param {NodeTreeFormat|NodeTreeData} b - Second snapshot (after)
16
+ * @param {DiffOptions} [opts] - Diff options
17
+ * @returns {DiffResult} Diff result with created, updated, deleted nodes, and optionally categorized updates
18
+ * @example
19
+ * // Basic usage
20
+ * const result = diff(snapshot1, snapshot2);
21
+ * console.log(result.created); // Newly created nodes
22
+ * console.log(result.updated); // Updated nodes with changes
23
+ * console.log(result.deleted); // Deleted nodes
24
+ *
25
+ * @example
26
+ * // With categorization
27
+ * const result = diff(snapshot1, snapshot2, { categorize: true });
28
+ * console.log(result.moved); // Nodes that were only moved
29
+ * console.log(result.modified); // Nodes that were only modified
30
+ * console.log(result.movedAndModified); // Nodes that were both moved and modified
31
+ *
32
+ * @example
33
+ * // Custom fields
34
+ * const result = diff(snapshot1, snapshot2, { fields: ['id', 'topic'] });
23
35
  */
24
- export function diff(a: NodeTreeFormat | NodeTreeData, b: NodeTreeFormat | NodeTreeData, opts?: {
25
- fields?: string[];
26
- includeStructure?: boolean;
27
- maxSize?: number;
28
- } | undefined): {
29
- created: any[];
30
- updated: {
31
- id: string;
32
- before: any;
33
- after: any;
34
- changes: {
35
- key: string;
36
- before: any;
37
- after: any;
38
- }[];
39
- }[];
40
- deleted: any[];
41
- truncated: boolean;
42
- };
36
+ export function diff(a: NodeTreeFormat | NodeTreeData, b: NodeTreeFormat | NodeTreeData, opts?: DiffOptions): DiffResult;
43
37
  export type NodeTreeFormat = {
44
38
  meta?: any;
45
39
  format?: "node_tree";
46
40
  data: NodeTreeData;
47
41
  };
48
42
  export type NodeTreeData = {
49
- id: string;
43
+ id?: string;
50
44
  topic?: string;
51
45
  expanded?: boolean;
52
46
  direction?: "left" | "right";
53
47
  data?: Record<string, any>;
54
48
  children?: NodeTreeData[];
49
+ [key: string]: any;
50
+ };
51
+ export type FlatNode = {
52
+ /**
53
+ * - Node ID
54
+ */
55
+ id: string;
56
+ /**
57
+ * - Node topic/title
58
+ */
59
+ topic?: string;
60
+ /**
61
+ * - Node data
62
+ */
63
+ data?: Record<string, any>;
64
+ /**
65
+ * - Parent node ID (structure field)
66
+ */
67
+ _parentid?: string | null;
68
+ /**
69
+ * - Node order in parent's children (structure field)
70
+ */
71
+ _order?: number;
72
+ };
73
+ export type ChangeDetail = {
74
+ /**
75
+ * - The field name that changed
76
+ */
77
+ key: string;
78
+ /**
79
+ * - Value before change
80
+ */
81
+ before: any;
82
+ /**
83
+ * - Value after change
84
+ */
85
+ after: any;
86
+ };
87
+ export type UpdatedNode = {
88
+ /**
89
+ * - Node ID
90
+ */
91
+ id: string;
92
+ /**
93
+ * - Node state before change
94
+ */
95
+ before: FlatNode;
96
+ /**
97
+ * - Node state after change
98
+ */
99
+ after: FlatNode;
100
+ /**
101
+ * - Array of field changes
102
+ */
103
+ changes: ChangeDetail[];
104
+ };
105
+ export type MoveInfo = {
106
+ /**
107
+ * - Whether parent changed
108
+ */
109
+ parentChanged: boolean;
110
+ /**
111
+ * - Whether order changed
112
+ */
113
+ orderChanged: boolean;
114
+ /**
115
+ * - Original parent ID
116
+ */
117
+ fromParent: string | null;
118
+ /**
119
+ * - New parent ID
120
+ */
121
+ toParent: string | null;
122
+ /**
123
+ * - Original order
124
+ */
125
+ fromOrder: number;
126
+ /**
127
+ * - New order
128
+ */
129
+ toOrder: number;
130
+ };
131
+ export type MovedNode = {
132
+ /**
133
+ * - Node ID
134
+ */
135
+ id: string;
136
+ /**
137
+ * - Node state before move
138
+ */
139
+ before: FlatNode;
140
+ /**
141
+ * - Node state after move
142
+ */
143
+ after: FlatNode;
144
+ /**
145
+ * - Movement details
146
+ */
147
+ moveInfo: MoveInfo;
148
+ };
149
+ export type ModifiedNode = {
150
+ /**
151
+ * - Node ID
152
+ */
153
+ id: string;
154
+ /**
155
+ * - Node state before modification
156
+ */
157
+ before: FlatNode;
158
+ /**
159
+ * - Node state after modification
160
+ */
161
+ after: FlatNode;
162
+ /**
163
+ * - Array of field changes (excluding structure fields)
164
+ */
165
+ changes: ChangeDetail[];
166
+ };
167
+ export type MovedAndModifiedNode = {
168
+ /**
169
+ * - Node ID
170
+ */
171
+ id: string;
172
+ /**
173
+ * - Node state before change
174
+ */
175
+ before: FlatNode;
176
+ /**
177
+ * - Node state after change
178
+ */
179
+ after: FlatNode;
180
+ /**
181
+ * - Array of field changes (excluding structure fields)
182
+ */
183
+ changes: ChangeDetail[];
184
+ /**
185
+ * - Movement details
186
+ */
187
+ moveInfo: MoveInfo;
188
+ };
189
+ export type DiffResult = {
190
+ /**
191
+ * - Newly created nodes
192
+ */
193
+ created: FlatNode[];
194
+ /**
195
+ * - Updated nodes (all changes)
196
+ */
197
+ updated: UpdatedNode[];
198
+ /**
199
+ * - Deleted nodes
200
+ */
201
+ deleted: FlatNode[];
202
+ /**
203
+ * - Whether results were truncated due to maxSize
204
+ */
205
+ truncated: boolean;
206
+ /**
207
+ * - Nodes that were only moved (when categorize=true)
208
+ */
209
+ moved?: MovedNode[];
210
+ /**
211
+ * - Nodes that were only modified (when categorize=true)
212
+ */
213
+ modified?: ModifiedNode[];
214
+ /**
215
+ * - Nodes that were both moved and modified (when categorize=true)
216
+ */
217
+ movedAndModified?: MovedAndModifiedNode[];
218
+ };
219
+ export type FlattenOptions = {
220
+ /**
221
+ * - Array of field names to include. Defaults to ['topic', 'data', 'id']
222
+ */
223
+ fields?: string[];
224
+ /**
225
+ * - Whether to include _parentid and _order. Defaults to true
226
+ */
227
+ includeStructure?: boolean;
228
+ };
229
+ export type DiffOptions = {
230
+ /**
231
+ * - Array of field names to compare. Defaults to ['topic', 'data', 'id']
232
+ */
233
+ fields?: string[];
234
+ /**
235
+ * - Whether to include _parentid and _order in comparison. Defaults to true
236
+ */
237
+ includeStructure?: boolean;
238
+ /**
239
+ * - Maximum number of diff results. Defaults to 5000
240
+ */
241
+ maxSize?: number;
242
+ /**
243
+ * - Whether to categorize updates into moved/modified/movedAndModified. Defaults to false
244
+ */
245
+ categorize?: boolean;
55
246
  };
@@ -55,6 +55,7 @@ declare class HistoryCore {
55
55
  _pending: boolean;
56
56
  _pendingMeta: any;
57
57
  _lastSig: any;
58
+ _lastRootId: any;
58
59
  add(reason: string, meta: any): void;
59
60
  pause(): void;
60
61
  resume(flush?: boolean): void;