Giter VIP home page Giter VIP logo

mind-elixir-core's Introduction

mindelixir logo2

Mind Elixir

version license code quality dependency-count package size

中文 README

Mind elixir is a free open source mind map core.

  • Lightweight
  • High performance
  • Framework agnostic
  • Pluginable
  • Export as SVG or PNG
  • Build-in drag and drop / node edit plugin
  • Summarize nodes
  • Bulk operations supported
  • Undo / Redo
  • Efficient shortcuts
  • Styling your node with CSS
Table of Contents

Try now

mindelixir

https://mind-elixir.com/

Playground

Usage

Install

NPM

npm i mind-elixir -S
import MindElixir from 'mind-elixir'

Script tag

<script src="https://cdn.jsdelivr.net/npm/mind-elixir/dist/MindElixir.js"></script>

Init

<div id="map"></div>
<style>
  #map {
    height: 500px;
    width: 100%;
  }
</style>

Breaking Change since 1.0.0, data should be passed to init(), not options.

import MindElixir from 'mind-elixir'
import example from 'mind-elixir/dist/example1'

let options = {
  el: '#map', // or HTMLDivElement
  direction: MindElixir.LEFT,
  draggable: true, // default true
  contextMenu: true, // default true
  toolBar: true, // default true
  nodeMenu: true, // default true
  keypress: true, // default true
  locale: 'en', // [zh_CN,zh_TW,en,ja,pt,ru] waiting for PRs
  overflowHidden: false, // default false
  mainLinkStyle: 2, // [1,2] default 1
  mouseSelectionButton: 0, // 0 for left button, 2 for right button, default 0
  contextMenuOption: {
    focus: true,
    link: true,
    extend: [
      {
        name: 'Node edit',
        onclick: () => {
          alert('extend menu')
        },
      },
    ],
  },
  before: {
    insertSibling(el, obj) {
      return true
    },
    async addChild(el, obj) {
      await sleep()
      return true
    },
  },
}

let mind = new MindElixir(options)

mind.install(plugin) // install your plugin

// create new map data
const data = MindElixir.new('new topic')
// or `example`
// or the data return from `.getData()`
mind.init(data)

// get a node
MindElixir.E('node-id')

Data Structure

// whole node data structure up to now
const nodeData = {
  topic: 'node topic',
  id: 'bd1c24420cd2c2f5',
  style: { fontSize: '32', color: '#3298db', background: '#ecf0f1' },
  expanded: true,
  parent: null,
  tags: ['Tag'],
  icons: ['😀'],
  hyperLink: 'https://github.com/ssshooter/mind-elixir-core',
  image: {
    url: 'https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png', // required
    // you need to query the height and width of the image and calculate the appropriate value to display the image
    height: 90, // required
    width: 90, // required
  },
  children: [
    {
      topic: 'child',
      id: 'xxxx',
      // ...
    },
  ],
}

Event Handling

mind.bus.addListener('operation', operation => {
  console.log(operation)
  // return {
  //   name: action name,
  //   obj: target object
  // }

  // name: [insertSibling|addChild|removeNode|beginEdit|finishEdit]
  // obj: target

  // name: moveNode
  // obj: {from:target1,to:target2}
})

mind.bus.addListener('selectNode', node => {
  console.log(node)
})

mind.bus.addListener('expandNode', node => {
  console.log('expandNode: ', node)
})

Data Export And Import

// data export
const data = mind.getData() // javascript object, see src/example.js
mind.getDataString() // stringify object
mind.getDataMd() // markdown

// data import
// initiate
let mind = new MindElixir(options)
mind.init(data)
// data update
mind.refresh(data)

Operation Guards

let mind = new MindElixir({
  // ...
  before: {
    insertSibling(el, obj) {
      console.log(el, obj)
      if (this.currentNode.nodeObj.parent.root) {
        return false
      }
      return true
    },
    async addChild(el, obj) {
      await sleep()
      if (this.currentNode.nodeObj.parent.root) {
        return false
      }
      return true
    },
  },
})

Export as a Image

const mind = {
  /** mind elixir instance */
}
const downloadPng = async () => {
  const blob = await mind.exportPng() // Get a Blob!
  if (!blob) return
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = 'filename.png'
  a.click()
  URL.revokeObjectURL(url)
}

APIs

https://github.com/ssshooter/mind-elixir-core/blob/master/api/mind-elixir.api.md

Theme

const options = {
  // ...
  theme: {
    name: 'Dark',
    // main lines color palette
    palette: ['#848FA0', '#748BE9', '#D2F9FE', '#4145A5', '#789AFA', '#706CF4', '#EF987F', '#775DD5', '#FCEECF', '#DA7FBC'],
    // overwrite css variables
    cssVar: {
      '--main-color': '#ffffff',
      '--main-bgcolor': '#4c4f69',
      '--color': '#cccccc',
      '--bgcolor': '#252526',
      '--panel-color': '255, 255, 255',
      '--panel-bgcolor': '45, 55, 72',
    },
    // all variables see /src/index.less
  },
  // ...
}

// ...

mind.changeTheme({
  name: 'Latte',
  palette: ['#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd'],
  cssVar: {
    '--main-color': '#444446',
    '--main-bgcolor': '#ffffff',
    '--color': '#777777',
    '--bgcolor': '#f6f6f6',
  },
})

Be aware that Mind Elixir will not observe the change of prefers-color-scheme. Please change the theme manually when the scheme changes.

Shortcuts

Shortcut Function
Enter Insert Sibling Node
Tab Insert Child Node
F1 Center the Map
F2 Begin Editing the Current Node
Select the Previous Sibling Node
Select the Next Sibling Node
← / → Select Parent or First Child
PageUp / Alt + ↑ Move Up Node
PageDown / Alt + ↓ Move Down Node
Ctrl + ↑ Change Layout Pattern to Side
Ctrl + ← Change Layout Pattern to Left
Ctrl + → Change Layout Pattern to Right
Ctrl + C Copy the Current Node
Ctrl + V Paste the Copied Node
Ctrl + "+" Zoom In Mind Map
Ctrl + "-" Zoom Out Mind Map
Ctrl + 0 Reset Zoom Level

Not only core

Development

pnpm i
pnpm dev

Test generated files with dev.dist.ts:

npm run build
npm link
npm link mind-elixir

Thanks

mind-elixir-core's People

Contributors

asith-w avatar bqx619 avatar codacy-badger avatar darksoulssssss avatar dependabot[bot] avatar guilhermebentomarques avatar malenconiaprincep avatar micahgodbolt avatar phyng avatar ssshooter avatar wjw020206 avatar yurgeman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mind-elixir-core's Issues

右键菜单优化定制化

是否考虑一下把右键菜单中的增加子节点、增加同级节点和删除节点都能定制化?

How to provide name for min-map image?

My team is facing an issue while using your package, that is, the mind-map image generated has the name of the center node but with underscores at random positions in the name. Is there a way to set a name of our choice?

firefox对onDrag和onDragend的兼容性

通过

<script src="https://cdn.jsdelivr.net/npm/regenerator-runtime"></script> <script src="https://cdn.jsdelivr.net/npm/mind-elixir/dist/mind-elixir.js"></script>

或者源码编译导入

在mind-exlixir.js中对firefox(版本84.0 (64 位))存在兼容性问题,drag和dragend中的e.clientX和e.clientY的值始终都为0,会导致拖拽更换位置失败,
个人临时方案为通过dragover将值传递给drag和dargend以临时解决

Data import Gives [object object]

      console.log('d', d)
      let mind = new MindElixir({
        el: '#map',
        direction: MindElixir.LEFT,
        data: MindElixir.new(d), // can also set data return from .getAllData()
        draggable: true, // default true
        contextMenu: true, // default true
        toolBar: true, // default true
        nodeMenu: true, // default true
        keypress: true, // default true
      })
      mind.init()

Where d in console

linkData: Object {  }
nodeData: Object { id: "root", topic: "Solid Map", root: true, … }

image

Any ideas?

How to init new mind map along with previous?

I have initialized one mind map by following the code of the repo, now I want to initialize another mind map bu it throws the error- "Cannot read property 'className' of null at me.init".

My source code is-

// vue file

<v-btn color="primary" @click="initializeSecond()">Add one more mind map</v-btn>
<v-row no-gutters>
       <v-col sm="6">
         <div id="map-1" style="width: 100%; height: 500px"></div>
       </v-col>
       <v-col sm="6">
         <div id="map-2" style="width: 100%; height: 500px"></div>
       </v-col>
</v-row>

// Js code

import MindElixir, { E } from "mind-elixir";

data() {
    return {
    ME: null,
    ME_1: null   
 }
},

mounted() {
  let options = {
    el: '#map-1',
    direction: MindElixir.LEFT,
    // the data return from `.getAllData()`
    data: dummyData,
    draggable: true, // default true
    contextMenu: true, // default true
    toolBar: true, // default true
    nodeMenu: true, // default true
    keypress: true, // default true
    locale: 'en', // [zh_CN,zh_TW,en,ja] waiting for PRs
    overflowHidden: false, // default false
    primaryLinkStyle: 2, // [1,2] default 1
    primaryNodeVerticalGap: 15, // default 25
    primaryNodeHorizontalGap: 15, // default 65
    contextMenuOption: {
      focus: true,
      link: true,
      extend: [
        {
          name: 'Node edit',
          onclick: () => {
            alert('extend menu')
          },
        },
      ],
    },
    allowUndo: false
  }

  this.ME = new MindElixir(options);
  this.ME.init();
},

methods: {
    async initializeSecond() {
      try {
      let option = {
        el: '#map-2',
        direction: MindElixir.LEFT,
        // the data return from `.getAllData()`
        data: dummyData,
        draggable: true, // default true
        contextMenu: true, // default true
        toolBar: true, // default true
        nodeMenu: true, // default true
        keypress: true, // default true
        locale: 'en', // [zh_CN,zh_TW,en,ja] waiting for PRs
        overflowHidden: false, // default false
        primaryLinkStyle: 2, // [1,2] default 1
        primaryNodeVerticalGap: 15, // default 25
        primaryNodeHorizontalGap: 15, // default 65
        contextMenuOption: {
          focus: true,
          link: true,
          extend: [
            {
              name: 'Node edit',
              onclick: () => {
                alert('extend menu')
              },
            },
          ],
        },
        allowUndo: false
      }
      this.ME_1 = await new MindElixir(option);
      this.ME_1.init();
      } catch (error) {
        console.error('______', error)
      }
    }
}

// Error

Screenshot from 2021-01-18 12-00-32

Could you please help? @SSShooter

issues

  • 删除节点,节点不消失,点击左边(显示按钮)刷新一下消失(火狐浏览器有问题,谷歌浏览器正常)
  • 全屏模式下,左右两边的菜单都不显示

Vue 引入报错:mind-elixir.js?3d5a:1 Uncaught TypeError: Cannot set property 'container' of null

<script type="text/ecmascript-6"> import MindElixir, { E } from 'mind-elixir' export default { name: 'Minder', created() { console.log('MindElixir.SIDE', MindElixir.SIDE) let mind = new MindElixir({ el: '#map', direction: MindElixir.LEFT, data: { nodeData: { id: 'root', topic: 'Mind Elixir', root: true, children: [] }, linkData: {}, }, // 也可以把 getDataAll 得到的数据初始化 draggable: true, // 启用拖动 default true contextMenu: true, // 启用右键菜单 default true toolBar: true, // 启用工具栏 default true nodeMenu: true, // 启用节点菜单 default true keypress: true, // 启用快捷键 default true }) mind.init() console.log('test E function') // get a node // E('node-id') }, } </script> <style> .outer { position: relative; margin: 50px; } #map { height: 500px; width: 100%; overflow: auto; } </style>

Missing License

Great project, but I can not find the license info, please add one so we can safely use it or not according the the license.

专注模式下两个问题

1、专注模式下getAllDataString()获取的content和专注前不一致,导致比较判断是否有新变更不准(明明没做任何变更)。
2、专注模式下getAllDataString()获取content保存后,下次加载编辑时对应专注节点无法再次进入专注模式了。

Context menu on iPad

How do you get the context menu to appear on touch screens like the iPad and iPhone

It works fine on Windows Surface and Android devices.

[Question] Control Scale/Fit?

I'm rendering the mindmap in a small div.

Is there a way to control the zoom/scale/fit before it renders?

There's also some bugs in the toolbars when the parent div has height and width are set to 100%, I might just have to manually set some styling (it looks like the padding isn't calculated properly)

image

URL for nodes

In node menu, add URL field. URL would be applied to topic text or to an icon (added if there is a link).

默认Node下的子Node无法退出专注模式.

我使用如下代码进行初始化, 其中data使用的是MindElixir.new方法创建一个默认的Topic.

import MindElixir, { E } from 'mind-elixir'

let options = {
  el: '#map',
  direction: MindElixir.LEFT,
  // create new map data
  data: MindElixir.new('new topic'),
  draggable: true, // default true
  contextMenu: true, // default true
  toolBar: true, // default true
  nodeMenu: true, // default true
  keypress: true, // default true
  locale: 'zh_CN', // [zh_CN,zh_TW,en,ja] waiting for PRs
  overflowHidden: false, // default false
  primaryLinkStyle: 2, // [1,2] default 1
  primaryNodeVerticalGap: 15, // default 25
  primaryNodeHorizontalGap: 15, // default 65
  allowUndo: false,
}

let mind = new MindElixir(options)
mind.init()

操作流程

当我在默认的Topic下创建子Node, 并且在子Node上打开右键菜单, 点击 专注 , 此时是可以进入子Node的专注模式的. 但是这时候在进入专注模式的子Node上点击右键菜单的 取消专注 , 此时无法退回到 new topic 这个默认根Node上.

How to import markdown ?

Hello I'm looking for create a mind map from a markdown file which was import. And I am searching How to support markdown with title and bullet and export markdown with title and bullet from the mind map? @SSShooter

Error Help

Error

xmind.html:30 Uncaught TypeError: MindElixir.new is not a function
    at xmind.html:30

HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/mind-elixir.js"></script>

</head>
<body>

<div class="outer">
    <div id="map"></div>
</div>
<style>
    .outer {
        position: relative;
        margin: 50px;
    }
    #map {
        height: 500px;
        width: 100%;
        overflow: auto;
    }
</style>
<script type="text/javascript">
    
    let mind = new MindElixir({
        el: '#map',
        direction: MindElixir.LEFT,
        data: MindElixir.new('new topic'), // can also set data return from .getAllData()
        draggable: true, // default true
        contextMenu: true, // default true
        toolBar: true, // default true
        nodeMenu: true, // default true
        keypress: true, // default true
    })
    mind.init()

    // mind.getAllData()
    E('node-id')
</script>
</body>
</html>

Uncaught TypeError: Cannot read property 'className' of null

Hi When I embed the package in my React application It returned this error :

Uncaught TypeError: Cannot read property 'className' of null
    at be.init (modules.js?hash=ebcd0e163cd7e6204aeb0085474fd08407040388:90811)
    at module (App.jsx:57)
    at fileEvaluate (modules-runtime-hot.js?hash=d12281259a6cee99786429a66f76b05f13449c7f:388)
    at Module.require (modules-runtime-hot.js?hash=d12281259a6cee99786429a66f76b05f13449c7f:270)
    at Module.moduleLink [as link] (modules.js?hash=ebcd0e163cd7e6204aeb0085474fd08407040388:309)
    at module (main.jsx:1)
    at fileEvaluate (modules-runtime-hot.js?hash=d12281259a6cee99786429a66f76b05f13449c7f:388)
    at Module.require (modules-runtime-hot.js?hash=d12281259a6cee99786429a66f76b05f13449c7f:270)
    at require (modules-runtime-hot.js?hash=d12281259a6cee99786429a66f76b05f13449c7f:310)
    at app.js?hash=b94593292eb30aa3f5e883365e84509373d0f757:157

My code :

import React from 'react';
import Editor from "rich-markdown-editor";
import MindElixir, {E} from 'mind-elixir'

export const App = () => (<div>
  <h1>Atomical</h1>
  <Editor defaultValue="# Votre Titre
    * \
    \" onChange={(value) => {
      console.log(value());
    }}/>
  <div id="map"></div>

</div>);

let options = {
  el: '#map',
  direction: MindElixir.LEFT,
  // create new map data
  data: MindElixir.new('new topic'),

  draggable: true, // default true
  contextMenu: true, // default true
  toolBar: true, // default true
  nodeMenu: true, // default true
  keypress: true, // default true
  locale: 'en', // [zh_CN,zh_TW,en,ja] waiting for PRs
  overflowHidden: false, // default false
  primaryLinkStyle: 2, // [1,2] default 1
  primaryNodeVerticalGap: 15, // default 25
  primaryNodeHorizontalGap: 15, // default 65
  contextMenuOption: {
    focus: true,
    link: true,
    extend: [
      {
        name: 'Node edit',
        onclick: () => {
          alert('extend menu')
        }
      }
    ]
  },
  allowUndo: false,
  before: {
    insertSibling(el, obj) {
      return true
    },
    async addChild(el, obj) {
      await sleep()
      return true
    }
  }
}

let mind = new MindElixir(options)
mind.init()

<width> must be 100% always ?

I prefer to resize the "map" to my parent element,
but I guess it's set as 100% (even it's parent has just 500px)..
Is there anyway to resize the map width ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.