jjb-lc-designable
Version:
基于alibaba-designable源码二次封装的表单设计器。
167 lines • 5.75 kB
JavaScript
import React, { useRef, useContext, useEffect } from 'react';
import { ClosestPosition, CursorStatus, DragMoveEvent } from 'jjb-lc-designable/core';
import { isFn } from 'jjb-lc-designable/shared';
import { autorun } from 'jjb-lc-formily/reactive';
import { observer } from 'jjb-lc-formily/reactive-react';
import { usePrefix, useCursor, useSelection, useMoveHelper, useDesigner } from '../../hooks';
import { IconWidget } from '../IconWidget';
import { NodeTitleWidget } from '../NodeTitleWidget';
import { NodeContext } from './context';
import cls from 'classnames';
import './styles.less';
export const OutlineTreeNode = observer(({
node,
className,
style,
workspaceId
}) => {
const prefix = usePrefix('outline-tree-node');
const engine = useDesigner();
const ref = useRef();
const ctx = useContext(NodeContext);
const request = useRef(null);
const cursor = useCursor();
const selection = useSelection(workspaceId);
const moveHelper = useMoveHelper(workspaceId);
useEffect(() => {
return engine.subscribeTo(DragMoveEvent, () => {
const closestNodeId = moveHelper?.closestNode?.id;
const closestDirection = moveHelper?.outlineClosestDirection;
const id = node.id;
if (!ref.current) return;
if (closestNodeId === id && closestDirection === ClosestPosition.Inner) {
if (!ref.current.classList.contains('droppable')) {
ref.current.classList.add('droppable');
}
if (!ref.current.classList.contains('expanded')) {
if (request.current) {
clearTimeout(request.current);
request.current = null;
}
request.current = setTimeout(() => {
ref.current.classList.add('expanded');
}, 600);
}
} else {
if (request.current) {
clearTimeout(request.current);
request.current = null;
}
if (ref.current.classList.contains('droppable')) {
ref.current.classList.remove('droppable');
}
}
});
}, [node, moveHelper, cursor]);
useEffect(() => {
return autorun(() => {
const selectedIds = selection?.selected || [];
const id = node.id;
if (!ref.current) return;
if (selectedIds.includes(id)) {
if (!ref.current.classList.contains('selected')) {
ref.current.classList.add('selected');
}
} else {
if (ref.current.classList.contains('selected')) {
ref.current.classList.remove('selected');
}
}
if (cursor.status === CursorStatus.Dragging && moveHelper?.dragNodes?.length) {
if (ref.current.classList.contains('selected')) {
ref.current.classList.remove('selected');
}
}
});
}, [node, selection, moveHelper]);
if (!node) return null;
const renderIcon = node => {
const icon = node.designerProps.icon;
if (icon) {
return /*#__PURE__*/React.createElement(IconWidget, {
infer: icon,
size: 12
});
}
if (node === node?.root) {
return /*#__PURE__*/React.createElement(IconWidget, {
infer: "Page",
size: 12
});
} else if (node.designerProps?.droppable) {
return /*#__PURE__*/React.createElement(IconWidget, {
infer: "Container",
size: 12
});
}
return /*#__PURE__*/React.createElement(IconWidget, {
infer: "Component",
size: 12
});
};
const renderTitle = node => {
if (isFn(ctx.renderTitle)) return ctx.renderTitle(node);
return /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(NodeTitleWidget, {
node: node
}));
};
const renderActions = node => {
if (isFn(ctx.renderActions)) return ctx.renderActions(node);
};
return /*#__PURE__*/React.createElement("div", {
style: style,
ref: ref,
className: cls(prefix, className, 'expanded'),
"data-designer-outline-node-id": node.id
}, /*#__PURE__*/React.createElement("div", {
className: prefix + '-header'
}, /*#__PURE__*/React.createElement("div", {
className: prefix + '-header-head',
style: {
left: -node.depth * 16,
width: node.depth * 16
}
}), /*#__PURE__*/React.createElement("div", {
className: prefix + '-header-content'
}, /*#__PURE__*/React.createElement("div", {
className: prefix + '-header-base'
}, (node?.children?.length > 0 || node === node.root) && /*#__PURE__*/React.createElement("div", {
className: prefix + '-expand',
onClick: e => {
e.preventDefault();
e.stopPropagation();
if (ref.current?.classList?.contains('expanded')) {
ref.current?.classList.remove('expanded');
} else {
ref.current?.classList.add('expanded');
}
}
}, /*#__PURE__*/React.createElement(IconWidget, {
infer: "Expand",
size: 10
})), /*#__PURE__*/React.createElement("div", {
className: prefix + '-icon'
}, renderIcon(node)), /*#__PURE__*/React.createElement("div", {
className: prefix + '-title'
}, renderTitle(node))), /*#__PURE__*/React.createElement("div", {
className: prefix + '-header-actions',
"data-click-stop-propagation": true
}, renderActions(node), node !== node.root && /*#__PURE__*/React.createElement(IconWidget, {
className: cls(prefix + '-hidden-icon', {
hidden: node.hidden
}),
infer: node.hidden ? 'EyeClose' : 'Eye',
size: 14,
onClick: () => {
node.hidden = !node.hidden;
}
})))), /*#__PURE__*/React.createElement("div", {
className: prefix + '-children'
}, node.children?.map(child => {
return /*#__PURE__*/React.createElement(OutlineTreeNode, {
node: child,
key: child.id,
workspaceId: workspaceId
});
})));
});