@umbraci/jsmind 0.10.14 → 0.10.15

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.
Files changed (69) hide show
  1. package/LICENSE +24 -24
  2. package/README.md +116 -116
  3. package/dist/jsmind.copy-paste.js +9 -0
  4. package/dist/jsmind.copy-paste.js.map +1 -0
  5. package/dist/jsmind.draggable-node.js +1 -1
  6. package/dist/jsmind.draggable-node.js.map +1 -1
  7. package/dist/jsmind.history.js +1 -1
  8. package/dist/jsmind.history.js.map +1 -1
  9. package/dist/jsmind.js +1 -1
  10. package/dist/jsmind.js.map +1 -1
  11. package/dist/jsmind.multi-select.js +1 -1
  12. package/dist/jsmind.multi-select.js.map +1 -1
  13. package/dist/jsmind.multiline-text.js +1 -1
  14. package/dist/jsmind.multiline-text.js.map +1 -1
  15. package/dist/jsmind.screenshot.js +1 -1
  16. package/dist/jsmind.screenshot.js.map +1 -1
  17. package/es/jsmind.copy-paste.js +9 -0
  18. package/es/jsmind.copy-paste.js.map +1 -0
  19. package/es/jsmind.draggable-node.js +1 -1
  20. package/es/jsmind.draggable-node.js.map +1 -1
  21. package/es/jsmind.history.js +1 -1
  22. package/es/jsmind.history.js.map +1 -1
  23. package/es/jsmind.js +1 -1
  24. package/es/jsmind.js.map +1 -1
  25. package/es/jsmind.multi-select.js +1 -1
  26. package/es/jsmind.multi-select.js.map +1 -1
  27. package/es/jsmind.multiline-text.js +1 -1
  28. package/es/jsmind.multiline-text.js.map +1 -1
  29. package/es/jsmind.screenshot.js +1 -1
  30. package/es/jsmind.screenshot.js.map +1 -1
  31. package/lib/jsmind.copy-paste.js +9 -0
  32. package/lib/jsmind.copy-paste.js.map +1 -0
  33. package/lib/jsmind.draggable-node.js +1 -1
  34. package/lib/jsmind.draggable-node.js.map +1 -1
  35. package/lib/jsmind.history.js +1 -1
  36. package/lib/jsmind.history.js.map +1 -1
  37. package/lib/jsmind.js +1 -1
  38. package/lib/jsmind.js.map +1 -1
  39. package/lib/jsmind.multi-select.js +1 -1
  40. package/lib/jsmind.multi-select.js.map +1 -1
  41. package/lib/jsmind.multiline-text.js +1 -1
  42. package/lib/jsmind.multiline-text.js.map +1 -1
  43. package/lib/jsmind.screenshot.js +1 -1
  44. package/lib/jsmind.screenshot.js.map +1 -1
  45. package/package.json +115 -115
  46. package/style/jsmind.css +408 -408
  47. package/types/generated/index.d.ts +8 -0
  48. package/types/generated/jsmind.common.d.ts +68 -0
  49. package/types/generated/jsmind.d.ts +632 -0
  50. package/types/generated/jsmind.data_provider.d.ts +56 -0
  51. package/types/generated/jsmind.dom.d.ts +59 -0
  52. package/types/generated/jsmind.enhanced-plugin.d.ts +103 -0
  53. package/types/generated/jsmind.format.d.ts +113 -0
  54. package/types/generated/jsmind.graph.d.ts +180 -0
  55. package/types/generated/jsmind.layout_provider.d.ts +182 -0
  56. package/types/generated/jsmind.mind.d.ts +129 -0
  57. package/types/generated/jsmind.node.d.ts +69 -0
  58. package/types/generated/jsmind.option.d.ts +78 -0
  59. package/types/generated/jsmind.plugin.d.ts +21 -0
  60. package/types/generated/jsmind.shortcut_provider.d.ts +52 -0
  61. package/types/generated/jsmind.util.d.ts +26 -0
  62. package/types/generated/jsmind.view_provider.d.ts +374 -0
  63. package/types/generated/plugins/history/history-diff.d.ts +310 -0
  64. package/types/generated/plugins/history/jsmind.history.d.ts +87 -0
  65. package/types/generated/plugins/jsmind.draggable-node.d.ts +262 -0
  66. package/types/generated/plugins/jsmind.multiline-text-v2.d.ts +58 -0
  67. package/types/generated/plugins/jsmind.multiline-text.d.ts +43 -0
  68. package/types/generated/plugins/jsmind.screenshot.d.ts +83 -0
  69. package/types/tsconfig.declaration.json +19 -19
@@ -0,0 +1,374 @@
1
+ export class ViewProvider {
2
+ /**
3
+ * View layer: DOM nodes, editor, graph and zoom.
4
+ * @param {import('./jsmind.js').default} jm - jsMind instance
5
+ * @param {{
6
+ * engine: 'canvas'|'svg',
7
+ * enable_device_pixel_ratio: boolean,
8
+ * hmargin: number,
9
+ * vmargin: number,
10
+ * line_width: number,
11
+ * line_color: string,
12
+ * line_style: 'curved'|'straight',
13
+ * custom_line_render?: Function,
14
+ * draggable: boolean,
15
+ * hide_scrollbars_when_draggable: boolean,
16
+ * node_overflow: 'hidden'|'wrap',
17
+ * zoom: {min:number, max:number, step:number, mask_key:number},
18
+ * custom_node_render?: Function,
19
+ * expander_style: 'char'|'number'
20
+ * }} options - View configuration options
21
+ */
22
+ constructor(jm: import("./jsmind.js").default, options: {
23
+ engine: "canvas" | "svg";
24
+ enable_device_pixel_ratio: boolean;
25
+ hmargin: number;
26
+ vmargin: number;
27
+ line_width: number;
28
+ line_color: string;
29
+ line_style: "curved" | "straight";
30
+ custom_line_render?: Function;
31
+ draggable: boolean;
32
+ hide_scrollbars_when_draggable: boolean;
33
+ node_overflow: "hidden" | "wrap";
34
+ zoom: {
35
+ min: number;
36
+ max: number;
37
+ step: number;
38
+ mask_key: number;
39
+ };
40
+ custom_node_render?: Function;
41
+ expander_style: "char" | "number";
42
+ });
43
+ opts: {
44
+ engine: "canvas" | "svg";
45
+ enable_device_pixel_ratio: boolean;
46
+ hmargin: number;
47
+ vmargin: number;
48
+ line_width: number;
49
+ line_color: string;
50
+ line_style: "curved" | "straight";
51
+ custom_line_render?: Function;
52
+ draggable: boolean;
53
+ hide_scrollbars_when_draggable: boolean;
54
+ node_overflow: "hidden" | "wrap";
55
+ zoom: {
56
+ min: number;
57
+ max: number;
58
+ step: number;
59
+ mask_key: number;
60
+ };
61
+ custom_node_render?: Function;
62
+ expander_style: "char" | "number";
63
+ };
64
+ jm: import("./jsmind.js").default;
65
+ layout: import("./jsmind.layout_provider.js").LayoutProvider;
66
+ container: HTMLElement;
67
+ e_panel: HTMLElement;
68
+ e_nodes: HTMLElement;
69
+ size: {
70
+ w: number;
71
+ h: number;
72
+ };
73
+ selected_node: import("./jsmind.node.js").Node;
74
+ /** @type {Map<string, import('./jsmind.node.js').Node>} */
75
+ multi_selected_nodes: Map<string, import("./jsmind.node.js").Node>;
76
+ editing_node: import("./jsmind.node.js").Node;
77
+ graph: {
78
+ view: ViewProvider;
79
+ opts: {
80
+ engine: "canvas" | "svg";
81
+ enable_device_pixel_ratio: boolean;
82
+ hmargin: number;
83
+ vmargin: number;
84
+ line_width: number;
85
+ line_color: string;
86
+ line_style: "curved" | "straight";
87
+ custom_line_render?: Function;
88
+ draggable: boolean;
89
+ hide_scrollbars_when_draggable: boolean;
90
+ node_overflow: "hidden" | "wrap";
91
+ zoom: {
92
+ min: number;
93
+ max: number;
94
+ step: number;
95
+ mask_key: number;
96
+ };
97
+ custom_node_render?: Function;
98
+ expander_style: "char" | "number";
99
+ };
100
+ e_svg: SVGElement;
101
+ size: {
102
+ w: number;
103
+ h: number;
104
+ };
105
+ lines: SVGPathElement[];
106
+ line_drawing: {
107
+ straight: (path: SVGPathElement, x1: number, y1: number, x2: number, y2: number) => void;
108
+ curved: (path: SVGPathElement, x1: number, y1: number, x2: number, y2: number) => void;
109
+ };
110
+ init_line_render(): void;
111
+ drawing: (path: SVGPathElement, x1: number, y1: number, x2: number, y2: number) => void;
112
+ element(): SVGSVGElement;
113
+ set_size(w: number, h: number): void;
114
+ clear(): void;
115
+ draw_line(pout: {
116
+ x: number;
117
+ y: number;
118
+ }, pin: {
119
+ x: number;
120
+ y: number;
121
+ }, offset: {
122
+ x: number;
123
+ y: number;
124
+ }, color?: string | undefined): void;
125
+ copy_to(dest_canvas_ctx: CanvasRenderingContext2D, callback?: (() => void) | undefined): void;
126
+ _bezier_to(path: SVGPathElement, x1: number, y1: number, x2: number, y2: number): void;
127
+ _line_to(path: SVGPathElement, x1: number, y1: number, x2: number, y2: number): void;
128
+ } | {
129
+ opts: {
130
+ engine: "canvas" | "svg";
131
+ enable_device_pixel_ratio: boolean;
132
+ hmargin: number;
133
+ vmargin: number;
134
+ line_width: number;
135
+ line_color: string;
136
+ line_style: "curved" | "straight";
137
+ custom_line_render?: Function;
138
+ draggable: boolean;
139
+ hide_scrollbars_when_draggable: boolean;
140
+ node_overflow: "hidden" | "wrap";
141
+ zoom: {
142
+ min: number;
143
+ max: number;
144
+ step: number;
145
+ mask_key: number;
146
+ };
147
+ custom_node_render?: Function;
148
+ expander_style: "char" | "number";
149
+ };
150
+ e_canvas: HTMLElement;
151
+ canvas_ctx: CanvasRenderingContext2D;
152
+ size: {
153
+ w: number;
154
+ h: number;
155
+ };
156
+ line_drawing: {
157
+ straight: (ctx: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number) => void;
158
+ curved: (ctx: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number) => void;
159
+ };
160
+ dpr: number;
161
+ init_line_render(): void;
162
+ drawing: (ctx: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number) => void;
163
+ element(): HTMLCanvasElement;
164
+ set_size(w: number, h: number): void;
165
+ clear(): void;
166
+ draw_line(pout: {
167
+ x: number;
168
+ y: number;
169
+ }, pin: {
170
+ x: number;
171
+ y: number;
172
+ }, offset: {
173
+ x: number;
174
+ y: number;
175
+ }, color?: string | undefined): void;
176
+ copy_to(dest_canvas_ctx: CanvasRenderingContext2D, callback?: (() => void) | undefined): void;
177
+ _bezier_to(ctx: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number): void;
178
+ _line_to(ctx: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number): void;
179
+ };
180
+ render_node: (ele: HTMLElement, node: import("./jsmind.node.js").Node) => void;
181
+ zoom_current: number;
182
+ device_pixel_ratio: number;
183
+ _initialized: boolean;
184
+ /** Initialize DOM structure, graph and editor. */
185
+ init(): void;
186
+ e_editor: HTMLElement;
187
+ /**
188
+ * Add a delegated event handler.
189
+ * @param {import('./jsmind.js').default} obj
190
+ * @param {string} event_name
191
+ * @param {(e:Event)=>void} event_handle
192
+ * @param {boolean=} capture_by_panel
193
+ */
194
+ add_event(obj: import("./jsmind.js").default, event_name: string, event_handle: (e: Event) => void, capture_by_panel?: boolean | undefined): void;
195
+ /**
196
+ * @param {HTMLElement|null} element
197
+ * @returns {string|null}
198
+ */
199
+ get_binded_nodeid(element: HTMLElement | null): string | null;
200
+ /**
201
+ * @param {HTMLElement|null} element
202
+ * @returns {boolean}
203
+ */
204
+ is_node(element: HTMLElement | null): boolean;
205
+ /**
206
+ * @param {HTMLElement} element
207
+ * @returns {boolean}
208
+ */
209
+ is_expander(element: HTMLElement): boolean;
210
+ reset(): void;
211
+ reset_theme(): void;
212
+ /** Reset custom styles for all nodes. */
213
+ reset_custom_style(): void;
214
+ /** Load and initialize the view. */
215
+ load(): void;
216
+ /** Calculate and set the expanded canvas size. */
217
+ expand_size(): void;
218
+ /**
219
+ * Initialize size data for a node.
220
+ * @param {import('./jsmind.node.js').Node} node - Target node
221
+ */
222
+ init_nodes_size(node: import("./jsmind.node.js").Node): void;
223
+ /** Initialize DOM elements for all nodes. */
224
+ init_nodes(): void;
225
+ /**
226
+ * Add a new node to the view.
227
+ * @param {import('./jsmind.node.js').Node} node - Node to add
228
+ */
229
+ add_node(node: import("./jsmind.node.js").Node): void;
230
+ /**
231
+ * Run function in compatibility mode if container is not visible.
232
+ * @param {Function} func - Function to execute
233
+ */
234
+ run_in_c11y_mode_if_needed(func: Function): void;
235
+ /**
236
+ * Create a DOM element for a node and append to parent container.
237
+ * @param {import('./jsmind.node.js').Node} node
238
+ * @param {HTMLElement} parent_node
239
+ */
240
+ create_node_element(node: import("./jsmind.node.js").Node, parent_node: HTMLElement): void;
241
+ /**
242
+ * Remove a node from the view.
243
+ * @param {import('./jsmind.node.js').Node} node - Node to remove
244
+ */
245
+ remove_node(node: import("./jsmind.node.js").Node): void;
246
+ /**
247
+ * Update a node's display.
248
+ * @param {import('./jsmind.node.js').Node} node - Node to update
249
+ */
250
+ update_node(node: import("./jsmind.node.js").Node): void;
251
+ /**
252
+ * Select a node visually.
253
+ * @param {import('./jsmind.node.js').Node|null} node - Node to select
254
+ */
255
+ select_node(node: import("./jsmind.node.js").Node | null): void;
256
+ /** Clear node selection. */
257
+ select_clear(): void;
258
+ /**
259
+ * Append nodes to the current selection without clearing existing ones.
260
+ * @param {import('./jsmind.node.js').Node[]} nodes
261
+ * @param {import('./jsmind.node.js').Node=} focus_node
262
+ */
263
+ append_selected_nodes(nodes: import("./jsmind.node.js").Node[], focus_node?: import("./jsmind.node.js").Node | undefined): void;
264
+ /**
265
+ * Remove the provided nodes from selection state.
266
+ * @param {import('./jsmind.node.js').Node[]} nodes
267
+ */
268
+ remove_selected_nodes(nodes: import("./jsmind.node.js").Node[]): void;
269
+ /** Clear all selections at once. */
270
+ clear_all_selected_nodes(): void;
271
+ /**
272
+ * Get currently editing node.
273
+ * @returns {import('./jsmind.node.js').Node|null} Currently editing node
274
+ */
275
+ get_editing_node(): import("./jsmind.node.js").Node | null;
276
+ /**
277
+ * Check if any node is being edited.
278
+ * @returns {boolean} True if editing
279
+ */
280
+ is_editing(): boolean;
281
+ /**
282
+ * Begin editing a node.
283
+ * @param {import('./jsmind.node.js').Node} node - Node to edit
284
+ */
285
+ edit_node_begin(node: import("./jsmind.node.js").Node): void;
286
+ /** End editing current node. */
287
+ edit_node_end(): void;
288
+ /** @returns {{x:number,y:number}} */
289
+ get_view_offset(): {
290
+ x: number;
291
+ y: number;
292
+ };
293
+ /** Resize the view to fit container. */
294
+ resize(): void;
295
+ /**
296
+ * Internal show implementation.
297
+ * @private
298
+ */
299
+ private _show;
300
+ /**
301
+ * Zoom in the view.
302
+ * @param {MouseEvent=} e - Mouse event for zoom center
303
+ * @returns {boolean} True if zoom succeeded
304
+ */
305
+ zoom_in(e?: MouseEvent | undefined): boolean;
306
+ /**
307
+ * Zoom out the view.
308
+ * @param {MouseEvent=} e - Mouse event for zoom center
309
+ * @returns {boolean} True if zoom succeeded
310
+ */
311
+ zoom_out(e?: MouseEvent | undefined): boolean;
312
+ /**
313
+ * Set zoom level and keep scroll around zoom center.
314
+ * @param {number} zoom
315
+ * @param {MouseEvent=} e
316
+ */
317
+ set_zoom(zoom: number, e?: MouseEvent | undefined): boolean;
318
+ /** @param {boolean=} keep_center */
319
+ show(keep_center?: boolean | undefined): void;
320
+ relayout(): void;
321
+ /** @param {import('./jsmind.node.js').Node} node */
322
+ save_location(node: import("./jsmind.node.js").Node): void;
323
+ /** @param {import('./jsmind.node.js').Node} node */
324
+ restore_location(node: import("./jsmind.node.js").Node): void;
325
+ clear_nodes(): void;
326
+ /** Render node elements and expanders to screen. */
327
+ show_nodes(): void;
328
+ /** @param {import('./jsmind.node.js').Node} node @param {{x:number,y:number}} view_offset */
329
+ _show_expander(node: import("./jsmind.node.js").Node, view_offset: {
330
+ x: number;
331
+ y: number;
332
+ }): void;
333
+ /** @param {import('./jsmind.node.js').Node} node */
334
+ _get_expander_text(node: import("./jsmind.node.js").Node): number | "..." | "-" | "+";
335
+ /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */
336
+ _default_node_render(ele: HTMLElement, node: import("./jsmind.node.js").Node): void;
337
+ /** @param {HTMLElement} ele @param {import('./jsmind.node.js').Node} node */
338
+ _custom_node_render(ele: HTMLElement, node: import("./jsmind.node.js").Node): void;
339
+ /** @param {import('./jsmind.node.js').Node} node */
340
+ reset_node_custom_style(node: import("./jsmind.node.js").Node): void;
341
+ /** @param {HTMLElement} node_element @param {Record<string,string|number>} node_data */
342
+ _reset_node_custom_style(node_element: HTMLElement, node_data: Record<string, string | number>): void;
343
+ /** @param {import('./jsmind.node.js').Node} node */
344
+ restore_selected_node_custom_style(node: import("./jsmind.node.js").Node): void;
345
+ /** @param {import('./jsmind.node.js').Node} node */
346
+ clear_selected_node_custom_style(node: import("./jsmind.node.js").Node): void;
347
+ /**
348
+ * Mark the DOM/state for a selected node.
349
+ * @param {import('./jsmind.node.js').Node} node
350
+ * @private
351
+ */
352
+ private _mark_node_selected;
353
+ /**
354
+ * Remove DOM/state selection for a node.
355
+ * @param {import('./jsmind.node.js').Node} node
356
+ * @private
357
+ */
358
+ private _unmark_node_selected;
359
+ clear_lines(): void;
360
+ show_lines(): void;
361
+ /**
362
+ * Enable/disable dragging the whole canvas with mouse.
363
+ * @param {boolean} enabled
364
+ */
365
+ setup_canvas_draggable(enabled: boolean): void;
366
+ /** @param {import('./jsmind.node.js').Node} node */
367
+ center_node(node: import("./jsmind.node.js").Node): boolean;
368
+ /** @param {MouseEvent=} e */
369
+ zoomIn(e?: MouseEvent | undefined): boolean;
370
+ /** @param {MouseEvent=} e */
371
+ zoomOut(e?: MouseEvent | undefined): boolean;
372
+ /** @param {number} zoom @param {MouseEvent=} e */
373
+ setZoom(zoom: number, e?: MouseEvent | undefined): boolean;
374
+ }
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Flatten a tree into a Map of nodes keyed by id.
3
+ *
4
+ * Note: When using custom fieldNames, make sure to pass the correct field names in opts.fields.
5
+ * For example, if you configured fieldNames: { topic: 'name' }, you should pass fields: ['name', 'data', 'id'].
6
+ *
7
+ * @param {NodeTreeFormat|NodeTreeData} tree - The tree to flatten
8
+ * @param {FlattenOptions} [opts] - Flatten options
9
+ * @returns {Map<string, FlatNode>} Map of node id -> flattened node object
10
+ *
11
+ * @example
12
+ * // With default fieldNames
13
+ * const tree = { data: { id: 'root', topic: 'Root', children: [...] } };
14
+ * const flatMap = flatten(tree);
15
+ * const rootNode = flatMap.get('root'); // { id: 'root', topic: 'Root', data: {...}, parentid: null, index: 0 }
16
+ *
17
+ * @example
18
+ * // With custom fieldNames: { topic: 'name' }
19
+ * const tree = { data: { id: 'root', name: 'Root', children: [...] } };
20
+ * const flatMap = flatten(tree, { fields: ['name', 'data', 'id'] });
21
+ * const rootNode = flatMap.get('root'); // { id: 'root', name: 'Root', data: {...}, parentid: null, index: 0 }
22
+ */
23
+ export function flatten(tree: NodeTreeFormat | NodeTreeData, opts?: FlattenOptions): Map<string, FlatNode>;
24
+ /**
25
+ * Compute diff between two snapshots.
26
+ *
27
+ * Note: When using custom fieldNames, make sure to pass the correct field names in opts.fields.
28
+ * For example, if you configured fieldNames: { topic: 'name' }, you should pass fields: ['name', 'data', 'id'].
29
+ * When using jm.history.diff(), this is automatically handled for you.
30
+ *
31
+ * @param {NodeTreeFormat|NodeTreeData} a - First snapshot (before)
32
+ * @param {NodeTreeFormat|NodeTreeData} b - Second snapshot (after)
33
+ * @param {DiffOptions} [opts] - Diff options
34
+ * @returns {DiffResult} Diff result with created, updated, deleted nodes, and optionally categorized updates
35
+ *
36
+ * @example
37
+ * // Basic usage with default fieldNames
38
+ * const result = diff(snapshot1, snapshot2);
39
+ * console.log(result.created); // Newly created nodes
40
+ * console.log(result.updated); // Updated nodes with changes
41
+ * console.log(result.deleted); // Deleted nodes
42
+ *
43
+ * @example
44
+ * // With categorization
45
+ * const result = diff(snapshot1, snapshot2, { categorize: true });
46
+ * console.log(result.moved); // Nodes that were only moved
47
+ * console.log(result.modified); // Nodes that were only modified
48
+ * console.log(result.movedAndModified); // Nodes that were both moved and modified
49
+ *
50
+ * @example
51
+ * // With custom fieldNames: { topic: 'name' }
52
+ * const result = diff(snapshot1, snapshot2, { fields: ['name', 'data', 'id'] });
53
+ * // Now the diff will correctly detect changes in the 'name' field
54
+ *
55
+ * @example
56
+ * // Using jm.history.diff() (recommended - automatically handles fieldNames)
57
+ * const before = jm.get_data('node_tree');
58
+ * // ... make changes ...
59
+ * const after = jm.get_data('node_tree');
60
+ * const result = jm.history.diff(before, after);
61
+ * // fieldNames are automatically applied, no need to specify fields manually
62
+ *
63
+ * @example
64
+ * // Ignore index changes caused by preceding node deletions
65
+ * const result = jm.history.diff(before, after, { ignoreDeletionShift: true });
66
+ * // Now nodes that only change index due to deletion of previous siblings won't be marked as moved
67
+ */
68
+ export function diff(a: NodeTreeFormat | NodeTreeData, b: NodeTreeFormat | NodeTreeData, opts?: DiffOptions): DiffResult;
69
+ export type NodeTreeFormat = {
70
+ meta?: any;
71
+ format?: "node_tree";
72
+ data: NodeTreeData;
73
+ };
74
+ export type NodeTreeData = {
75
+ id?: string;
76
+ topic?: string;
77
+ expanded?: boolean;
78
+ direction?: "left" | "right";
79
+ data?: Record<string, any>;
80
+ children?: NodeTreeData[];
81
+ [key: string]: any;
82
+ };
83
+ export type FlatNode = {
84
+ /**
85
+ * - Node ID
86
+ */
87
+ id: string;
88
+ /**
89
+ * - Node topic/title
90
+ */
91
+ topic?: string;
92
+ /**
93
+ * - Node data
94
+ */
95
+ data?: Record<string, any>;
96
+ /**
97
+ * - Parent node ID (structure field)
98
+ */
99
+ parentid?: string | null;
100
+ /**
101
+ * - Node order in parent's children (structure field)
102
+ */
103
+ index?: number;
104
+ };
105
+ export type ChangeDetail = {
106
+ /**
107
+ * - The field name that changed
108
+ */
109
+ key: string;
110
+ /**
111
+ * - Value before change
112
+ */
113
+ before: any;
114
+ /**
115
+ * - Value after change
116
+ */
117
+ after: any;
118
+ };
119
+ export type UpdatedNode = {
120
+ /**
121
+ * - Node ID
122
+ */
123
+ id: string;
124
+ /**
125
+ * - Node state before change
126
+ */
127
+ before: FlatNode;
128
+ /**
129
+ * - Node state after change
130
+ */
131
+ after: FlatNode;
132
+ /**
133
+ * - Array of field changes
134
+ */
135
+ changes: ChangeDetail[];
136
+ };
137
+ export type MoveInfo = {
138
+ /**
139
+ * - Whether parent changed
140
+ */
141
+ parentChanged: boolean;
142
+ /**
143
+ * - Whether order changed
144
+ */
145
+ orderChanged: boolean;
146
+ /**
147
+ * - Original parent ID
148
+ */
149
+ fromParent: string | null;
150
+ /**
151
+ * - New parent ID
152
+ */
153
+ toParent: string | null;
154
+ /**
155
+ * - Original order
156
+ */
157
+ fromOrder: number;
158
+ /**
159
+ * - New order
160
+ */
161
+ toOrder: number;
162
+ };
163
+ export type MovedNode = {
164
+ /**
165
+ * - Node ID
166
+ */
167
+ id: string;
168
+ /**
169
+ * - Node state before move
170
+ */
171
+ before: FlatNode;
172
+ /**
173
+ * - Node state after move
174
+ */
175
+ after: FlatNode;
176
+ /**
177
+ * - Movement details
178
+ */
179
+ moveInfo: MoveInfo;
180
+ };
181
+ export type ModifiedNode = {
182
+ /**
183
+ * - Node ID
184
+ */
185
+ id: string;
186
+ /**
187
+ * - Node state before modification
188
+ */
189
+ before: FlatNode;
190
+ /**
191
+ * - Node state after modification
192
+ */
193
+ after: FlatNode;
194
+ /**
195
+ * - Array of field changes (excluding structure fields)
196
+ */
197
+ changes: ChangeDetail[];
198
+ };
199
+ export type MovedAndModifiedNode = {
200
+ /**
201
+ * - Node ID
202
+ */
203
+ id: string;
204
+ /**
205
+ * - Node state before change
206
+ */
207
+ before: FlatNode;
208
+ /**
209
+ * - Node state after change
210
+ */
211
+ after: FlatNode;
212
+ /**
213
+ * - Array of field changes (excluding structure fields)
214
+ */
215
+ changes: ChangeDetail[];
216
+ /**
217
+ * - Movement details
218
+ */
219
+ moveInfo: MoveInfo;
220
+ };
221
+ export type DiffResult = {
222
+ /**
223
+ * - Newly created nodes
224
+ */
225
+ created: FlatNode[];
226
+ /**
227
+ * - Updated nodes (all changes)
228
+ */
229
+ updated: UpdatedNode[];
230
+ /**
231
+ * - Deleted nodes
232
+ */
233
+ deleted: FlatNode[];
234
+ /**
235
+ * - Whether results were truncated due to maxSize
236
+ */
237
+ truncated: boolean;
238
+ /**
239
+ * - Nodes that were only moved (when categorize=true)
240
+ */
241
+ moved?: MovedNode[];
242
+ /**
243
+ * - Nodes that were only modified (when categorize=true)
244
+ */
245
+ modified?: ModifiedNode[];
246
+ /**
247
+ * - Nodes that were both moved and modified (when categorize=true)
248
+ */
249
+ movedAndModified?: MovedAndModifiedNode[];
250
+ };
251
+ export type FlattenOptions = {
252
+ /**
253
+ * - Array of field names to include. Defaults to ['topic', 'data', 'id'].
254
+ * When using custom fieldNames (e.g., { id: 'key', topic: 'name' }), this should be
255
+ * ['name', 'data', 'key'] to match the actual field names in the data.
256
+ */
257
+ fields?: string[];
258
+ /**
259
+ * - The field name to use as the node ID. Defaults to 'id'.
260
+ * When using custom fieldNames (e.g., { id: 'key' }), this should be 'key'.
261
+ */
262
+ idKey?: string;
263
+ /**
264
+ * - The field name to use for children array. Defaults to 'children'.
265
+ * When using custom fieldNames (e.g., { children: 'items' }), this should be 'items'.
266
+ */
267
+ childrenKey?: string;
268
+ /**
269
+ * - Whether to include parentid and index. Defaults to true
270
+ */
271
+ includeStructure?: boolean;
272
+ };
273
+ export type DiffOptions = {
274
+ /**
275
+ * - Array of field names to compare. Defaults to ['topic', 'data', 'id'].
276
+ * When using custom fieldNames (e.g., { id: 'key', topic: 'name' }), this should be
277
+ * ['name', 'data', 'key'] to match the actual field names in the data.
278
+ * Note: When using jm.history.diff(), this is automatically handled based
279
+ * on the configured fieldNames, so you don't need to specify it manually.
280
+ */
281
+ fields?: string[];
282
+ /**
283
+ * - The field name to use as the node ID. Defaults to 'id'.
284
+ * When using custom fieldNames (e.g., { id: 'key' }), this should be 'key'.
285
+ * Note: When using jm.history.diff(), this is automatically handled.
286
+ */
287
+ idKey?: string;
288
+ /**
289
+ * - The field name to use for children array. Defaults to 'children'.
290
+ * When using custom fieldNames (e.g., { children: 'items' }), this should be 'items'.
291
+ * Note: When using jm.history.diff(), this is automatically handled.
292
+ */
293
+ childrenKey?: string;
294
+ /**
295
+ * - Whether to include parentid and index in comparison. Defaults to true
296
+ */
297
+ includeStructure?: boolean;
298
+ /**
299
+ * - Maximum number of diff results. Defaults to 5000
300
+ */
301
+ maxSize?: number;
302
+ /**
303
+ * - Whether to categorize updates into moved/modified/movedAndModified. Defaults to false
304
+ */
305
+ categorize?: boolean;
306
+ /**
307
+ * - Whether to ignore index changes caused by preceding node deletions. When true, nodes that only change index due to deletion of previous siblings won't be marked as moved. Defaults to false
308
+ */
309
+ ignoreDeletionShift?: boolean;
310
+ };