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