bade-mind-react
bade-mind
React 框架封装库
Installation
NPM
npm install bade-mind-react
Usage
import * as React from 'react'
import { useState } from 'react'
import ReactDom from 'react-dom'
import { BadeMind, BadeMindReact } from 'bade-mind-react'
const root: BadeMindReact.Root = {
negative: [
{
attachData: 'Negative 1 leaf',
id: 'n-1-l'
}
],
node: {
attachData: 'Root',
id: 'root'
},
positive: [
{
attachData: 'Positive 1 leaf',
id: 'p-1-l'
}
]
}
const generateChildren = () => {
const result: BadeMindReact.Node[] = []
const num = Math.ceil(3 * Math.random())
for (let counter = 0; counter < num; counter++) {
result.push({
attachData: Math.random().toFixed(6),
draggable: true,
id: Math.random().toString()
})
}
return result
}
const Render = (props: {
node: BadeMind.Node
onClick: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void
}) => {
const { node, onClick } = props
return (
<div className={'node'} onClick={onClick}>
{node.attachData}
</div>
)
}
const options: BadeMind.Options = {
nodeSeparate: 20,
rankSeparate: 60,
childAlignMode: BadeMind.ChildAlignMode.structured
}
const Demo = () => {
const [data, setData] = useState<BadeMind.Root>(root)
const [anchor, setAnchor] = useState<string | undefined>()
const onDragEnd = useCallback<BadeMindReact.DragEndEvent>(
(event) => {
const { attach, node, original } = event
if (attach && attach.index >= 0) {
let children: BadeMindReact.Node[] = []
if (attach.parent.id === data.node.id) {
if (attach.orientation === BadeMind.Orientation.positive) {
children = data.positive = data.positive || []
} else {
children = data.negative = data.negative || []
}
} else {
children = attach.parent.children = attach.parent.children || []
}
children.splice(attach.index, 0, {
...node
})
let originalPlaceNodes = []
if (original.parent.id === data.node.id) {
originalPlaceNodes =
original.orientation === BadeMind.Orientation.positive ? data.positive : data.negative
} else {
originalPlaceNodes = original.parent.children
}
const dragNodeIndex = originalPlaceNodes.indexOf(node)
if (dragNodeIndex >= 0) {
originalPlaceNodes.splice(dragNodeIndex, 1)
}
setAnchor(attach.parent.id)
setData((pre) => ({ ...pre }))
}
},
[data]
)
return (
<BadeMindReact.Graphic
data={data}
anchor={anchor}
scrollbar={true}
onDragEnd={onDragEnd}
render={(node) => (
<Render
node={node}
onClick={(e) => {
setAnchor(node.id)
if (node.id !== root.node.id) {
if (!node.children) {
node.children = []
}
node.children.push(...generateChildren())
setData((pre) => {
return { ...pre }
})
}
}}
/>
)}
options={options}
/>
)
}
ReactDom.render(<Demo />, document.getElementById('root'))
Result
Export
BadeMind
组件依赖的bade-mind
库导出
BadeMindReact
Node
组件内部已自动实现sizeof
函数,故而不需要用户配置
interface Node extends Omit<BadeMind.Node, 'sizeof' | 'children'> {
size?: BadeMind.Size
beProtected?: boolean
alwaysVisible?: boolean
disableSizeCache?: boolean
children?: Node[]
draggable?: boolean
droppable?: boolean
}
Root
interface Root {
node: Node
positive?: Node[]
negative?: Node[]
}
GraphicProps
export interface GraphicProps {
options?: BadeMind.Options
data: Root
render: Render
anchor?: string
scrollbar?: boolean
onUpdated?: (mind: BadeMind.Graphic) => void
className?: string
style?: React.CSSProperties
wheelMoveSpeed?: number
onDragStart?: DragStartEvent
onDrag?: DragEvent
onDragEnd?: DragEndEvent
}
GraphicRef
interface GraphicRef {
mind?: BadeMind.Graphic
}
Render
type Render = (data: Node, mirror: boolean) => React.ReactNode
DragStartEvent
type DragStartEvent = (event: { node: Node }) => void
DragEvent
type DragEvent = (event: {
node: Node
attach:
| {
parent: Node
orientation: BadeMind.Orientation
}
| undefined
mirrorPosition: BadeMind.Coordinate
}) => void
DragEndEvent
type DragEndEvent = (event: {
node: Node
attach:
| {
parent: Node
orientation: BadeMind.Orientation
index: number
}
| undefined
original: {
parent: Node
orientation: BadeMind.Orientation
}
}) => void
Tips
渲染初始定位
可使用onUpdated
在渲染完成之后,改变位移缩放等
- 谨记,
onUpdated
会在每一次渲染更新完成之后调用
onUpdated={(mind) => {
mind.nodeTranslateTo({
diff: {
x: 0,
y: 0
},
id: 'root',
relative: {
x: BadeMind.RelativeX.middle,
y: BadeMind.RelativeY.top
}
})
}