1 | <p align="center">
|
2 | <a href="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 | [中文 README](https://github.com/ssshooter/mind-elixir-core/blob/master/readme.cn.md)
|
27 |
|
28 | Mind elixir is a free open source mind map core.
|
29 |
|
30 | - Zero dependency
|
31 | - High performance
|
32 | - Lightweight
|
33 | - Framework agnostic
|
34 | - Pluginable
|
35 | - Build-in drag and drop / node edit plugin
|
36 | - Styling your node with CSS
|
37 | - Undo / Redo
|
38 |
|
39 | <details>
|
40 | <summary>Table of Contents</summary>
|
41 |
|
42 | - [Try now](#try-now)
|
43 | - [Playground](#playground)
|
44 | - [Usage](#usage)
|
45 | - [Install](#install)
|
46 | - [NPM](#npm)
|
47 | - [Script tag](#script-tag)
|
48 | - [Init](#init)
|
49 | - [Data Structure](#data-structure)
|
50 | - [Event Handling](#event-handling)
|
51 | - [Data Export And Import](#data-export-and-import)
|
52 | - [Operation Guards](#operation-guards)
|
53 | - [Methods](#methods)
|
54 | - [Theme](#theme)
|
55 | - [Not only core](#not-only-core)
|
56 | - [Development](#development)
|
57 |
|
58 | </details>
|
59 |
|
60 | ## Try now
|
61 |
|
62 | ![mindelixir](https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/screenshot2.png)
|
63 |
|
64 | https://mind-elixir.com/
|
65 |
|
66 | ### Playground
|
67 |
|
68 | - Vanilla JS - https://codepen.io/ssshooter/pen/OJrJowN
|
69 | - React - https://codesandbox.io/s/mind-elixir-3-x-react-18-x-vy9fcq
|
70 | - Vue3 - https://codesandbox.io/s/mind-elixir-3-x-vue3-lth484
|
71 | - Vue2 - https://codesandbox.io/s/mind-elixir-3-x-vue-2-x-5kdfjp
|
72 |
|
73 | ## Usage
|
74 |
|
75 | ### Install
|
76 |
|
77 | #### NPM
|
78 |
|
79 | ```bash
|
80 | npm i mind-elixir -S
|
81 | ```
|
82 |
|
83 | ```javascript
|
84 | import MindElixir from 'mind-elixir'
|
85 | ```
|
86 |
|
87 | #### Script tag
|
88 |
|
89 | ```html
|
90 | <script src="https://cdn.jsdelivr.net/npm/mind-elixir/dist/MindElixir.js"></script>
|
91 | ```
|
92 |
|
93 | ### Init
|
94 |
|
95 | ```html
|
96 | <div id="map"></div>
|
97 | <style>
|
98 | #map {
|
99 | height: 500px;
|
100 | width: 100%;
|
101 | }
|
102 | </style>
|
103 | ```
|
104 |
|
105 | **Breaking Change** since 1.0.0, `data` should be passed to `init()`, not `options`.
|
106 |
|
107 | ```javascript
|
108 | import MindElixir from 'mind-elixir'
|
109 | import example from 'mind-elixir/dist/example1'
|
110 |
|
111 | let options = {
|
112 | el: '#map', // or HTMLDivElement
|
113 | direction: MindElixir.LEFT,
|
114 | draggable: true, // default true
|
115 | contextMenu: true, // default true
|
116 | toolBar: true, // default true
|
117 | nodeMenu: true, // default true
|
118 | keypress: true, // default true
|
119 | locale: 'en', // [zh_CN,zh_TW,en,ja,pt,ru] waiting for PRs
|
120 | overflowHidden: false, // default false
|
121 | mainLinkStyle: 2, // [1,2] default 1
|
122 | contextMenuOption: {
|
123 | focus: true,
|
124 | link: true,
|
125 | extend: [
|
126 | {
|
127 | name: 'Node edit',
|
128 | onclick: () => {
|
129 | alert('extend menu')
|
130 | },
|
131 | },
|
132 | ],
|
133 | },
|
134 | before: {
|
135 | insertSibling(el, obj) {
|
136 | return true
|
137 | },
|
138 | async addChild(el, obj) {
|
139 | await sleep()
|
140 | return true
|
141 | },
|
142 | },
|
143 | }
|
144 |
|
145 | let mind = new MindElixir(options)
|
146 |
|
147 | mind.install(plugin) // install your plugin
|
148 |
|
149 | // create new map data
|
150 | const data = MindElixir.new('new topic')
|
151 | // or `example`
|
152 | // or the data return from `.getData()`
|
153 | mind.init(data)
|
154 |
|
155 | // get a node
|
156 | MindElixir.E('node-id')
|
157 | ```
|
158 |
|
159 | ### Data Structure
|
160 |
|
161 | ```javascript
|
162 | // whole node data structure up to now
|
163 | const nodeData = {
|
164 | topic: 'node topic',
|
165 | id: 'bd1c24420cd2c2f5',
|
166 | style: { fontSize: '32', color: '#3298db', background: '#ecf0f1' },
|
167 | expanded: true,
|
168 | parent: null,
|
169 | tags: ['Tag'],
|
170 | icons: ['😀'],
|
171 | hyperLink: 'https://github.com/ssshooter/mind-elixir-core',
|
172 | image: {
|
173 | url: 'https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png', // required
|
174 | // you need to query the height and width of the image and calculate the appropriate value to display the image
|
175 | height: 90, // required
|
176 | width: 90, // required
|
177 | },
|
178 | children: [
|
179 | {
|
180 | topic: 'child',
|
181 | id: 'xxxx',
|
182 | // ...
|
183 | },
|
184 | ],
|
185 | }
|
186 | ```
|
187 |
|
188 | ### Event Handling
|
189 |
|
190 | ```javascript
|
191 | mind.bus.addListener('operation', operation => {
|
192 | console.log(operation)
|
193 | // return {
|
194 | // name: action name,
|
195 | // obj: target object
|
196 | // }
|
197 |
|
198 | // name: [insertSibling|addChild|removeNode|beginEdit|finishEdit]
|
199 | // obj: target
|
200 |
|
201 | // name: moveNode
|
202 | // obj: {from:target1,to:target2}
|
203 | })
|
204 |
|
205 | mind.bus.addListener('selectNode', node => {
|
206 | console.log(node)
|
207 | })
|
208 |
|
209 | mind.bus.addListener('expandNode', node => {
|
210 | console.log('expandNode: ', node)
|
211 | })
|
212 | ```
|
213 |
|
214 | ### Data Export And Import
|
215 |
|
216 | ```javascript
|
217 | // data export
|
218 | const data = mind.getData() // javascript object, see src/example.js
|
219 | mind.getDataString() // stringify object
|
220 | mind.getDataMd() // markdown
|
221 |
|
222 | // data import
|
223 | // initiate
|
224 | let mind = new MindElixir(options)
|
225 | mind.init(data)
|
226 | // data update
|
227 | mind.refresh(data)
|
228 | ```
|
229 |
|
230 | ### Operation Guards
|
231 |
|
232 | ```javascript
|
233 | let mind = new MindElixir({
|
234 | // ...
|
235 | before: {
|
236 | insertSibling(el, obj) {
|
237 | console.log(el, obj)
|
238 | if (this.currentNode.nodeObj.parent.root) {
|
239 | return false
|
240 | }
|
241 | return true
|
242 | },
|
243 | async addChild(el, obj) {
|
244 | await sleep()
|
245 | if (this.currentNode.nodeObj.parent.root) {
|
246 | return false
|
247 | }
|
248 | return true
|
249 | },
|
250 | },
|
251 | })
|
252 | ```
|
253 |
|
254 | ## Methods
|
255 |
|
256 | https://github.com/ssshooter/mind-elixir-core/blob/master/api/mind-elixir.api.md
|
257 |
|
258 | ## Theme
|
259 |
|
260 | ```javascript
|
261 | const options = {
|
262 | // ...
|
263 | theme: {
|
264 | name: 'Dark',
|
265 | // main lines color palette
|
266 | palette: ['#848FA0', '#748BE9', '#D2F9FE', '#4145A5', '#789AFA', '#706CF4', '#EF987F', '#775DD5', '#FCEECF', '#DA7FBC'],
|
267 | // overwrite css variables
|
268 | cssVar: {
|
269 | '--main-color': '#ffffff',
|
270 | '--main-bgcolor': '#4c4f69',
|
271 | '--color': '#cccccc',
|
272 | '--bgcolor': '#252526',
|
273 | '--panel-color': '255, 255, 255',
|
274 | '--panel-bgcolor': '45, 55, 72',
|
275 | },
|
276 | // all variables see /src/index.less
|
277 | },
|
278 | // ...
|
279 | }
|
280 |
|
281 | // ...
|
282 |
|
283 | mind.changeTheme({
|
284 | name: 'Latte',
|
285 | palette: ['#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd'],
|
286 | cssVar: {
|
287 | '--main-color': '#444446',
|
288 | '--main-bgcolor': '#ffffff',
|
289 | '--color': '#777777',
|
290 | '--bgcolor': '#f6f6f6',
|
291 | },
|
292 | })
|
293 | ```
|
294 |
|
295 | Be aware that Mind Elixir will not observe the change of `prefers-color-scheme`. Please change the theme **manually** when the scheme changes.
|
296 |
|
297 | ## Not only core
|
298 |
|
299 | - [@mind-elixir/node-menu](https://github.com/ssshooter/node-menu)
|
300 | - [@mind-elixir/node-menu-neo](https://github.com/ssshooter/node-menu-neo)
|
301 | - [@mind-elixir/export-xmind](https://github.com/ssshooter/export-xmind)
|
302 | - [@mind-elixir/export-html](https://github.com/ssshooter/export-html)
|
303 | - [@mind-elixir/export-image](https://github.com/ssshooter/export-image) (WIP🚧)
|
304 | - [mind-elixir-react](https://github.com/ssshooter/mind-elixir-react)
|
305 |
|
306 | ## Development
|
307 |
|
308 | ```
|
309 | pnpm i
|
310 | npm start
|
311 | ```
|
312 |
|
313 | Test generated files with `dev.dist.ts`:
|
314 |
|
315 | ```
|
316 | npm run build
|
317 | npm link
|
318 | npm link mind-elixir
|
319 | ```
|