mind-elixir 4.5.1 → 5.0.0-beta.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.
package/readme.md CHANGED
@@ -1,430 +1,430 @@
1
- <p align="center">
2
- <a href="https://docs.mind-elixir.com" target="_blank" rel="noopener noreferrer">
3
- <img width="150" src="https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png" alt="mindelixir logo2">
4
- </a>
5
- <h1 align="center">Mind Elixir</h1>
6
- </p>
7
-
8
- <p align="center">
9
- <a href="https://www.npmjs.com/package/mind-elixir">
10
- <img src="https://img.shields.io/npm/v/mind-elixir" alt="version">
11
- </a>
12
- <a href="https://github.com/ssshooter/mind-elixir-core/blob/master/LICENSE">
13
- <img src="https://img.shields.io/npm/l/mind-elixir" alt="license">
14
- </a>
15
- <a href="https://app.codacy.com/gh/ssshooter/mind-elixir-core?utm_source=github.com&utm_medium=referral&utm_content=ssshooter/mind-elixir-core&utm_campaign=Badge_Grade_Settings">
16
- <img src="https://api.codacy.com/project/badge/Grade/09fadec5bf094886b30cea6aabf3a88b" alt="code quality">
17
- </a>
18
- <a href="https://bundlephobia.com/result?p=mind-elixir">
19
- <img src="https://badgen.net/bundlephobia/dependency-count/mind-elixir" alt="dependency-count">
20
- </a>
21
- <a href="https://packagephobia.com/result?p=mind-elixir">
22
- <img src="https://packagephobia.com/badge?p=mind-elixir" alt="package size">
23
- </a>
24
- </p>
25
-
26
- [English](/readme.md) |
27
- [中文](/readme/zh.md) |
28
- [Español](/readme/es.md) |
29
- [Français](/readme/fr.md) |
30
- [Português](/readme/pt.md) |
31
- [Русский](/readme/ru.md) |
32
- [日本語](/readme/ja.md) |
33
- [한국어](/readme/ko.md)
34
-
35
- Mind elixir is a open source JavaScript mind map core. You can use it with any frontend framework you like.
36
-
37
- Features:
38
-
39
- - Lightweight
40
- - High performance
41
- - Framework agnostic
42
- - Pluginable
43
- - Build-in drag and drop / node edit plugin
44
- - Export as SVG / PNG / Html
45
- - Summarize nodes
46
- - Bulk operations supported
47
- - Undo / Redo
48
- - Efficient shortcuts
49
- - Easily Styling your node with CSS variables
50
-
51
- <details>
52
- <summary>Table of Contents</summary>
53
-
54
- - [Try now](#try-now)
55
- - [Playground](#playground)
56
- - [Documentation](#documentation)
57
- - [Usage](#usage)
58
- - [Install](#install)
59
- - [NPM](#npm)
60
- - [Script tag](#script-tag)
61
- - [Init](#init)
62
- - [Data Structure](#data-structure)
63
- - [Event Handling](#event-handling)
64
- - [Data Export And Import](#data-export-and-import)
65
- - [Operation Guards](#operation-guards)
66
- - [Export as a Image](#export-as-a-image)
67
- - [Solution 1](#solution-1)
68
- - [Solution 2](#solution-2)
69
- - [Theme](#theme)
70
- - [Shortcuts](#shortcuts)
71
- - [Ecosystem](#ecosystem)
72
- - [Development](#development)
73
- - [Thanks](#thanks)
74
- - [Contributors](#contributors)
75
-
76
- </details>
77
-
78
- ## Try now
79
-
80
- ![mindelixir](https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/screenshot2.png)
81
-
82
- https://mind-elixir.com/
83
-
84
- ### Playground
85
-
86
- - Vanilla JS - https://codepen.io/ssshooter/pen/OJrJowN
87
- - React - https://codesandbox.io/s/mind-elixir-3-x-react-18-x-vy9fcq
88
- - Vue3 - https://codesandbox.io/s/mind-elixir-3-x-vue3-lth484
89
- - Vue2 - https://codesandbox.io/s/mind-elixir-3-x-vue-2-x-5kdfjp
90
-
91
- ## Documentation
92
-
93
- https://docs.mind-elixir.com/
94
-
95
- ## Usage
96
-
97
- ### Install
98
-
99
- #### NPM
100
-
101
- ```bash
102
- npm i mind-elixir -S
103
- ```
104
-
105
- ```javascript
106
- import MindElixir from 'mind-elixir'
107
- ```
108
-
109
- #### Script tag
110
-
111
- ```html
112
- <script type="module" src="https://cdn.jsdelivr.net/npm/mind-elixir/dist/MindElixir.js"></script>
113
- ```
114
-
115
- ### Init
116
-
117
- ```html
118
- <div id="map"></div>
119
- <style>
120
- #map {
121
- height: 500px;
122
- width: 100%;
123
- }
124
- </style>
125
- ```
126
-
127
- **Breaking Change** since 1.0.0, `data` should be passed to `init()`, not `options`.
128
-
129
- ```javascript
130
- import MindElixir from 'mind-elixir'
131
- import example from 'mind-elixir/dist/example1'
132
-
133
- let options = {
134
- el: '#map', // or HTMLDivElement
135
- direction: MindElixir.LEFT,
136
- draggable: true, // default true
137
- contextMenu: true, // default true
138
- toolBar: true, // default true
139
- nodeMenu: true, // default true
140
- keypress: true, // default true
141
- locale: 'en', // [zh_CN,zh_TW,en,ja,pt,ru] waiting for PRs
142
- overflowHidden: false, // default false
143
- mainLinkStyle: 2, // [1,2] default 1
144
- mouseSelectionButton: 0, // 0 for left button, 2 for right button, default 0
145
- contextMenuOption: {
146
- focus: true,
147
- link: true,
148
- extend: [
149
- {
150
- name: 'Node edit',
151
- onclick: () => {
152
- alert('extend menu')
153
- },
154
- },
155
- ],
156
- },
157
- before: {
158
- insertSibling(el, obj) {
159
- return true
160
- },
161
- async addChild(el, obj) {
162
- await sleep()
163
- return true
164
- },
165
- },
166
- }
167
-
168
- let mind = new MindElixir(options)
169
-
170
- mind.install(plugin) // install your plugin
171
-
172
- // create new map data
173
- const data = MindElixir.new('new topic')
174
- // or `example`
175
- // or the data return from `.getData()`
176
- mind.init(data)
177
-
178
- // get a node
179
- MindElixir.E('node-id')
180
- ```
181
-
182
- ### Data Structure
183
-
184
- ```javascript
185
- // whole node data structure up to now
186
- const nodeData = {
187
- topic: 'node topic',
188
- id: 'bd1c24420cd2c2f5',
189
- style: { fontSize: '32', color: '#3298db', background: '#ecf0f1' },
190
- expanded: true,
191
- parent: null,
192
- tags: ['Tag'],
193
- icons: ['😀'],
194
- hyperLink: 'https://github.com/ssshooter/mind-elixir-core',
195
- image: {
196
- url: 'https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png', // required
197
- // you need to query the height and width of the image and calculate the appropriate value to display the image
198
- height: 90, // required
199
- width: 90, // required
200
- },
201
- children: [
202
- {
203
- topic: 'child',
204
- id: 'xxxx',
205
- // ...
206
- },
207
- ],
208
- }
209
- ```
210
-
211
- ### Event Handling
212
-
213
- ```javascript
214
- mind.bus.addListener('operation', operation => {
215
- console.log(operation)
216
- // return {
217
- // name: action name,
218
- // obj: target object
219
- // }
220
-
221
- // name: [insertSibling|addChild|removeNode|beginEdit|finishEdit]
222
- // obj: target
223
-
224
- // name: moveNode
225
- // obj: {from:target1,to:target2}
226
- })
227
-
228
- mind.bus.addListener('selectNode', node => {
229
- console.log(node)
230
- })
231
-
232
- mind.bus.addListener('expandNode', node => {
233
- console.log('expandNode: ', node)
234
- })
235
- ```
236
-
237
- ### Data Export And Import
238
-
239
- ```javascript
240
- // data export
241
- const data = mind.getData() // javascript object, see src/example.js
242
- mind.getDataString() // stringify object
243
- mind.getDataMd() // markdown
244
-
245
- // data import
246
- // initiate
247
- let mind = new MindElixir(options)
248
- mind.init(data)
249
- // data update
250
- mind.refresh(data)
251
- ```
252
-
253
- ### Operation Guards
254
-
255
- ```javascript
256
- let mind = new MindElixir({
257
- // ...
258
- before: {
259
- insertSibling(el, obj) {
260
- console.log(el, obj)
261
- if (this.currentNode.nodeObj.parent.root) {
262
- return false
263
- }
264
- return true
265
- },
266
- async addChild(el, obj) {
267
- await sleep()
268
- if (this.currentNode.nodeObj.parent.root) {
269
- return false
270
- }
271
- return true
272
- },
273
- },
274
- })
275
- ```
276
-
277
- ## Export as a Image
278
-
279
- ### Solution 1
280
-
281
- ```typescript
282
- const mind = {
283
- /** mind elixir instance */
284
- }
285
- const downloadPng = async () => {
286
- const blob = await mind.exportPng() // Get a Blob!
287
- if (!blob) return
288
- const url = URL.createObjectURL(blob)
289
- const a = document.createElement('a')
290
- a.href = url
291
- a.download = 'filename.png'
292
- a.click()
293
- URL.revokeObjectURL(url)
294
- }
295
- ```
296
-
297
- ### Solution 2
298
-
299
- Install `@ssshooter/modern-screenshot`, then:
300
-
301
- ```typescript
302
- import { domToPng } from '@ssshooter/modern-screenshot'
303
-
304
- const download = async () => {
305
- const dataUrl = await domToPng(mind.nodes, {
306
- onCloneNode: node => {
307
- const n = node as HTMLDivElement
308
- n.style.position = ''
309
- n.style.top = ''
310
- n.style.left = ''
311
- n.style.bottom = ''
312
- n.style.right = ''
313
- },
314
- padding: 300,
315
- quality: 1,
316
- })
317
- const link = document.createElement('a')
318
- link.download = 'screenshot.png'
319
- link.href = dataUrl
320
- link.click()
321
- }
322
- ```
323
-
324
- ## Theme
325
-
326
- ```javascript
327
- const options = {
328
- // ...
329
- theme: {
330
- name: 'Dark',
331
- // main lines color palette
332
- palette: ['#848FA0', '#748BE9', '#D2F9FE', '#4145A5', '#789AFA', '#706CF4', '#EF987F', '#775DD5', '#FCEECF', '#DA7FBC'],
333
- // overwrite css variables
334
- cssVar: {
335
- '--main-color': '#ffffff',
336
- '--main-bgcolor': '#4c4f69',
337
- '--color': '#cccccc',
338
- '--bgcolor': '#252526',
339
- '--panel-color': '255, 255, 255',
340
- '--panel-bgcolor': '45, 55, 72',
341
- },
342
- // all variables see /src/index.less
343
- },
344
- // ...
345
- }
346
-
347
- // ...
348
-
349
- mind.changeTheme({
350
- name: 'Latte',
351
- palette: ['#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd'],
352
- cssVar: {
353
- '--main-color': '#444446',
354
- '--main-bgcolor': '#ffffff',
355
- '--color': '#777777',
356
- '--bgcolor': '#f6f6f6',
357
- },
358
- })
359
- ```
360
-
361
- Be aware that Mind Elixir will not observe the change of `prefers-color-scheme`. Please change the theme **manually** when the scheme changes.
362
-
363
- ## Shortcuts
364
-
365
- | Shortcut | Function |
366
- | ------------------ | -------------------------------- |
367
- | Enter | Insert Sibling Node |
368
- | Tab | Insert Child Node |
369
- | F1 | Center the Map |
370
- | F2 | Begin Editing the Current Node |
371
- | ↑ | Select the Previous Sibling Node |
372
- | ↓ | Select the Next Sibling Node |
373
- | ← / → | Select Parent or First Child |
374
- | PageUp / Alt + ↑ | Move Up Node |
375
- | PageDown / Alt + ↓ | Move Down Node |
376
- | Ctrl + ↑ | Change Layout Pattern to Side |
377
- | Ctrl + ← | Change Layout Pattern to Left |
378
- | Ctrl + → | Change Layout Pattern to Right |
379
- | Ctrl + C | Copy the Current Node |
380
- | Ctrl + V | Paste the Copied Node |
381
- | Ctrl + "+" | Zoom In Mind Map |
382
- | Ctrl + "-" | Zoom Out Mind Map |
383
- | Ctrl + 0 | Reset Zoom Level |
384
-
385
- ## Ecosystem
386
-
387
- - [@mind-elixir/node-menu](https://github.com/ssshooter/node-menu)
388
- - [@mind-elixir/node-menu-neo](https://github.com/ssshooter/node-menu-neo)
389
- - [@mind-elixir/export-xmind](https://github.com/ssshooter/export-xmind)
390
- - [@mind-elixir/export-html](https://github.com/ssshooter/export-html)
391
- - [mind-elixir-react](https://github.com/ssshooter/mind-elixir-react)
392
-
393
- PRs are welcome!
394
-
395
- ## Development
396
-
397
- ```
398
- pnpm i
399
- pnpm dev
400
- ```
401
-
402
- Test generated files with `dev.dist.ts`:
403
-
404
- ```
405
- pnpm build
406
- pnpm link ./
407
- ```
408
-
409
- Update docs:
410
-
411
- ```
412
- # Install api-extractor
413
- pnpm install -g @microsoft/api-extractor
414
- # Maintain /src/docs.ts
415
- # Generate docs
416
- pnpm doc
417
- pnpm doc:md
418
- ```
419
-
420
- ## Thanks
421
-
422
- - [@viselect/vanilla](https://github.com/simonwep/selection/tree/master/packages/vanilla)
423
-
424
- ## Contributors
425
-
426
- Thanks for your contributions to Mind Elixir! Your support and dedication make this project better.
427
-
428
- <a href="https://github.com/SSShooter/mind-elixir-core/graphs/contributors">
429
- <img src="https://contrib.rocks/image?repo=SSShooter/mind-elixir-core&columns=6" />
430
- </a>
1
+ <p align="center">
2
+ <a href="https://docs.mind-elixir.com" target="_blank" rel="noopener noreferrer">
3
+ <img width="150" src="https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png" alt="mindelixir logo2">
4
+ </a>
5
+ <h1 align="center">Mind Elixir</h1>
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://www.npmjs.com/package/mind-elixir">
10
+ <img src="https://img.shields.io/npm/v/mind-elixir" alt="version">
11
+ </a>
12
+ <a href="https://github.com/ssshooter/mind-elixir-core/blob/master/LICENSE">
13
+ <img src="https://img.shields.io/npm/l/mind-elixir" alt="license">
14
+ </a>
15
+ <a href="https://app.codacy.com/gh/ssshooter/mind-elixir-core?utm_source=github.com&utm_medium=referral&utm_content=ssshooter/mind-elixir-core&utm_campaign=Badge_Grade_Settings">
16
+ <img src="https://api.codacy.com/project/badge/Grade/09fadec5bf094886b30cea6aabf3a88b" alt="code quality">
17
+ </a>
18
+ <a href="https://bundlephobia.com/result?p=mind-elixir">
19
+ <img src="https://badgen.net/bundlephobia/dependency-count/mind-elixir" alt="dependency-count">
20
+ </a>
21
+ <a href="https://packagephobia.com/result?p=mind-elixir">
22
+ <img src="https://packagephobia.com/badge?p=mind-elixir" alt="package size">
23
+ </a>
24
+ </p>
25
+
26
+ [English](/readme.md) |
27
+ [中文](/readme/zh.md) |
28
+ [Español](/readme/es.md) |
29
+ [Français](/readme/fr.md) |
30
+ [Português](/readme/pt.md) |
31
+ [Русский](/readme/ru.md) |
32
+ [日本語](/readme/ja.md) |
33
+ [한국어](/readme/ko.md)
34
+
35
+ Mind elixir is a open source JavaScript mind map core. You can use it with any frontend framework you like.
36
+
37
+ Features:
38
+
39
+ - Lightweight
40
+ - High performance
41
+ - Framework agnostic
42
+ - Pluginable
43
+ - Build-in drag and drop / node edit plugin
44
+ - Export as SVG / PNG / Html
45
+ - Summarize nodes
46
+ - Bulk operations supported
47
+ - Undo / Redo
48
+ - Efficient shortcuts
49
+ - Easily Styling your node with CSS variables
50
+
51
+ <details>
52
+ <summary>Table of Contents</summary>
53
+
54
+ - [Try now](#try-now)
55
+ - [Playground](#playground)
56
+ - [Documentation](#documentation)
57
+ - [Usage](#usage)
58
+ - [Install](#install)
59
+ - [NPM](#npm)
60
+ - [Script tag](#script-tag)
61
+ - [Init](#init)
62
+ - [Data Structure](#data-structure)
63
+ - [Event Handling](#event-handling)
64
+ - [Data Export And Import](#data-export-and-import)
65
+ - [Operation Guards](#operation-guards)
66
+ - [Export as a Image](#export-as-a-image)
67
+ - [Solution 1](#solution-1)
68
+ - [Solution 2](#solution-2)
69
+ - [Theme](#theme)
70
+ - [Shortcuts](#shortcuts)
71
+ - [Ecosystem](#ecosystem)
72
+ - [Development](#development)
73
+ - [Thanks](#thanks)
74
+ - [Contributors](#contributors)
75
+
76
+ </details>
77
+
78
+ ## Try now
79
+
80
+ ![mindelixir](https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/screenshot2.png)
81
+
82
+ https://mind-elixir.com/
83
+
84
+ ### Playground
85
+
86
+ - Vanilla JS - https://codepen.io/ssshooter/pen/OJrJowN
87
+ - React - https://codesandbox.io/s/mind-elixir-3-x-react-18-x-vy9fcq
88
+ - Vue3 - https://codesandbox.io/s/mind-elixir-3-x-vue3-lth484
89
+ - Vue2 - https://codesandbox.io/s/mind-elixir-3-x-vue-2-x-5kdfjp
90
+
91
+ ## Documentation
92
+
93
+ https://docs.mind-elixir.com/
94
+
95
+ ## Usage
96
+
97
+ ### Install
98
+
99
+ #### NPM
100
+
101
+ ```bash
102
+ npm i mind-elixir -S
103
+ ```
104
+
105
+ ```javascript
106
+ import MindElixir from 'mind-elixir'
107
+ ```
108
+
109
+ #### Script tag
110
+
111
+ ```html
112
+ <script type="module" src="https://cdn.jsdelivr.net/npm/mind-elixir/dist/MindElixir.js"></script>
113
+ ```
114
+
115
+ ### Init
116
+
117
+ ```html
118
+ <div id="map"></div>
119
+ <style>
120
+ #map {
121
+ height: 500px;
122
+ width: 100%;
123
+ }
124
+ </style>
125
+ ```
126
+
127
+ **Breaking Change** since 1.0.0, `data` should be passed to `init()`, not `options`.
128
+
129
+ ```javascript
130
+ import MindElixir from 'mind-elixir'
131
+ import example from 'mind-elixir/dist/example1'
132
+
133
+ let options = {
134
+ el: '#map', // or HTMLDivElement
135
+ direction: MindElixir.LEFT,
136
+ draggable: true, // default true
137
+ contextMenu: true, // default true
138
+ toolBar: true, // default true
139
+ nodeMenu: true, // default true
140
+ keypress: true, // default true
141
+ locale: 'en', // [zh_CN,zh_TW,en,ja,pt,ru] waiting for PRs
142
+ overflowHidden: false, // default false
143
+ mainLinkStyle: 2, // [1,2] default 1
144
+ mouseSelectionButton: 0, // 0 for left button, 2 for right button, default 0
145
+ contextMenuOption: {
146
+ focus: true,
147
+ link: true,
148
+ extend: [
149
+ {
150
+ name: 'Node edit',
151
+ onclick: () => {
152
+ alert('extend menu')
153
+ },
154
+ },
155
+ ],
156
+ },
157
+ before: {
158
+ insertSibling(el, obj) {
159
+ return true
160
+ },
161
+ async addChild(el, obj) {
162
+ await sleep()
163
+ return true
164
+ },
165
+ },
166
+ }
167
+
168
+ let mind = new MindElixir(options)
169
+
170
+ mind.install(plugin) // install your plugin
171
+
172
+ // create new map data
173
+ const data = MindElixir.new('new topic')
174
+ // or `example`
175
+ // or the data return from `.getData()`
176
+ mind.init(data)
177
+
178
+ // get a node
179
+ MindElixir.E('node-id')
180
+ ```
181
+
182
+ ### Data Structure
183
+
184
+ ```javascript
185
+ // whole node data structure up to now
186
+ const nodeData = {
187
+ topic: 'node topic',
188
+ id: 'bd1c24420cd2c2f5',
189
+ style: { fontSize: '32', color: '#3298db', background: '#ecf0f1' },
190
+ expanded: true,
191
+ parent: null,
192
+ tags: ['Tag'],
193
+ icons: ['😀'],
194
+ hyperLink: 'https://github.com/ssshooter/mind-elixir-core',
195
+ image: {
196
+ url: 'https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png', // required
197
+ // you need to query the height and width of the image and calculate the appropriate value to display the image
198
+ height: 90, // required
199
+ width: 90, // required
200
+ },
201
+ children: [
202
+ {
203
+ topic: 'child',
204
+ id: 'xxxx',
205
+ // ...
206
+ },
207
+ ],
208
+ }
209
+ ```
210
+
211
+ ### Event Handling
212
+
213
+ ```javascript
214
+ mind.bus.addListener('operation', operation => {
215
+ console.log(operation)
216
+ // return {
217
+ // name: action name,
218
+ // obj: target object
219
+ // }
220
+
221
+ // name: [insertSibling|addChild|removeNode|beginEdit|finishEdit]
222
+ // obj: target
223
+
224
+ // name: moveNode
225
+ // obj: {from:target1,to:target2}
226
+ })
227
+
228
+ mind.bus.addListener('selectNode', node => {
229
+ console.log(node)
230
+ })
231
+
232
+ mind.bus.addListener('expandNode', node => {
233
+ console.log('expandNode: ', node)
234
+ })
235
+ ```
236
+
237
+ ### Data Export And Import
238
+
239
+ ```javascript
240
+ // data export
241
+ const data = mind.getData() // javascript object, see src/example.js
242
+ mind.getDataString() // stringify object
243
+ mind.getDataMd() // markdown
244
+
245
+ // data import
246
+ // initiate
247
+ let mind = new MindElixir(options)
248
+ mind.init(data)
249
+ // data update
250
+ mind.refresh(data)
251
+ ```
252
+
253
+ ### Operation Guards
254
+
255
+ ```javascript
256
+ let mind = new MindElixir({
257
+ // ...
258
+ before: {
259
+ insertSibling(el, obj) {
260
+ console.log(el, obj)
261
+ if (this.currentNode.nodeObj.parent.root) {
262
+ return false
263
+ }
264
+ return true
265
+ },
266
+ async addChild(el, obj) {
267
+ await sleep()
268
+ if (this.currentNode.nodeObj.parent.root) {
269
+ return false
270
+ }
271
+ return true
272
+ },
273
+ },
274
+ })
275
+ ```
276
+
277
+ ## Export as a Image
278
+
279
+ ### Solution 1
280
+
281
+ ```typescript
282
+ const mind = {
283
+ /** mind elixir instance */
284
+ }
285
+ const downloadPng = async () => {
286
+ const blob = await mind.exportPng() // Get a Blob!
287
+ if (!blob) return
288
+ const url = URL.createObjectURL(blob)
289
+ const a = document.createElement('a')
290
+ a.href = url
291
+ a.download = 'filename.png'
292
+ a.click()
293
+ URL.revokeObjectURL(url)
294
+ }
295
+ ```
296
+
297
+ ### Solution 2
298
+
299
+ Install `@ssshooter/modern-screenshot`, then:
300
+
301
+ ```typescript
302
+ import { domToPng } from '@ssshooter/modern-screenshot'
303
+
304
+ const download = async () => {
305
+ const dataUrl = await domToPng(mind.nodes, {
306
+ onCloneNode: node => {
307
+ const n = node as HTMLDivElement
308
+ n.style.position = ''
309
+ n.style.top = ''
310
+ n.style.left = ''
311
+ n.style.bottom = ''
312
+ n.style.right = ''
313
+ },
314
+ padding: 300,
315
+ quality: 1,
316
+ })
317
+ const link = document.createElement('a')
318
+ link.download = 'screenshot.png'
319
+ link.href = dataUrl
320
+ link.click()
321
+ }
322
+ ```
323
+
324
+ ## Theme
325
+
326
+ ```javascript
327
+ const options = {
328
+ // ...
329
+ theme: {
330
+ name: 'Dark',
331
+ // main lines color palette
332
+ palette: ['#848FA0', '#748BE9', '#D2F9FE', '#4145A5', '#789AFA', '#706CF4', '#EF987F', '#775DD5', '#FCEECF', '#DA7FBC'],
333
+ // overwrite css variables
334
+ cssVar: {
335
+ '--main-color': '#ffffff',
336
+ '--main-bgcolor': '#4c4f69',
337
+ '--color': '#cccccc',
338
+ '--bgcolor': '#252526',
339
+ '--panel-color': '255, 255, 255',
340
+ '--panel-bgcolor': '45, 55, 72',
341
+ },
342
+ // all variables see /src/index.less
343
+ },
344
+ // ...
345
+ }
346
+
347
+ // ...
348
+
349
+ mind.changeTheme({
350
+ name: 'Latte',
351
+ palette: ['#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd'],
352
+ cssVar: {
353
+ '--main-color': '#444446',
354
+ '--main-bgcolor': '#ffffff',
355
+ '--color': '#777777',
356
+ '--bgcolor': '#f6f6f6',
357
+ },
358
+ })
359
+ ```
360
+
361
+ Be aware that Mind Elixir will not observe the change of `prefers-color-scheme`. Please change the theme **manually** when the scheme changes.
362
+
363
+ ## Shortcuts
364
+
365
+ | Shortcut | Function |
366
+ | ------------------ | -------------------------------- |
367
+ | Enter | Insert Sibling Node |
368
+ | Tab | Insert Child Node |
369
+ | F1 | Center the Map |
370
+ | F2 | Begin Editing the Current Node |
371
+ | ↑ | Select the Previous Sibling Node |
372
+ | ↓ | Select the Next Sibling Node |
373
+ | ← / → | Select Parent or First Child |
374
+ | PageUp / Alt + ↑ | Move Up Node |
375
+ | PageDown / Alt + ↓ | Move Down Node |
376
+ | Ctrl + ↑ | Change Layout Pattern to Side |
377
+ | Ctrl + ← | Change Layout Pattern to Left |
378
+ | Ctrl + → | Change Layout Pattern to Right |
379
+ | Ctrl + C | Copy the Current Node |
380
+ | Ctrl + V | Paste the Copied Node |
381
+ | Ctrl + "+" | Zoom In Mind Map |
382
+ | Ctrl + "-" | Zoom Out Mind Map |
383
+ | Ctrl + 0 | Reset Zoom Level |
384
+
385
+ ## Ecosystem
386
+
387
+ - [@mind-elixir/node-menu](https://github.com/ssshooter/node-menu)
388
+ - [@mind-elixir/node-menu-neo](https://github.com/ssshooter/node-menu-neo)
389
+ - [@mind-elixir/export-xmind](https://github.com/ssshooter/export-xmind)
390
+ - [@mind-elixir/export-html](https://github.com/ssshooter/export-html)
391
+ - [mind-elixir-react](https://github.com/ssshooter/mind-elixir-react)
392
+
393
+ PRs are welcome!
394
+
395
+ ## Development
396
+
397
+ ```
398
+ pnpm i
399
+ pnpm dev
400
+ ```
401
+
402
+ Test generated files with `dev.dist.ts`:
403
+
404
+ ```
405
+ pnpm build
406
+ pnpm link ./
407
+ ```
408
+
409
+ Update docs:
410
+
411
+ ```
412
+ # Install api-extractor
413
+ pnpm install -g @microsoft/api-extractor
414
+ # Maintain /src/docs.ts
415
+ # Generate docs
416
+ pnpm doc
417
+ pnpm doc:md
418
+ ```
419
+
420
+ ## Thanks
421
+
422
+ - [@viselect/vanilla](https://github.com/simonwep/selection/tree/master/packages/vanilla)
423
+
424
+ ## Contributors
425
+
426
+ Thanks for your contributions to Mind Elixir! Your support and dedication make this project better.
427
+
428
+ <a href="https://github.com/SSShooter/mind-elixir-core/graphs/contributors">
429
+ <img src="https://contrib.rocks/image?repo=SSShooter/mind-elixir-core&columns=6" />
430
+ </a>