Skip to content

Commit

Permalink
Merge pull request #88 from idrawjs/dev-v0.4
Browse files Browse the repository at this point in the history
feat: improve element tree, redo/undo logic
  • Loading branch information
chenshenhai authored Aug 4, 2024
2 parents e58538a + 62cbc2c commit edb75be
Show file tree
Hide file tree
Showing 27 changed files with 361 additions and 255 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"upgrade:version": "npm run version:reset && pnpm i"
},
"dependencies": {
"idraw": "0.4.0-beta.34",
"idraw": "0.4.0-beta.36",
"antd": "5.19.3"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/studio-base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@rc-component/color-picker": "^1.5.3",
"antd": "^5.19.3",
"classnames": "^2.3.2",
"idraw": "^0.4.0-beta.34",
"idraw": "^0.4.0-beta.36",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
Expand Down
26 changes: 15 additions & 11 deletions packages/studio-base/src/css/modules/element-tree.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,21 @@
.@{base-element-tree} {
// fix antd style
&.ant-tree {
// padding: 10px 0;

&.ant-tree-directory {
.ant-tree-treenode:before {
bottom: 0;
}
}
.ant-tree-iconEle {
display: none;
}

.ant-tree-treenode {
padding-bottom: 0;
}

.ant-tree-title {
display: flex;
width: 100%;
Expand All @@ -33,9 +44,10 @@
position: relative;
display: -webkit-box;
float: inline-start;
height: 28px;
line-height: 28px;
padding-left: 28px;
overflow: hidden;
height: 24px;
padding-left: 24px;
white-space: initial;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
Expand All @@ -50,20 +62,12 @@
left: 0;
right: 0;
display: inline-flex;
// display: none;
float: inline-start;
// overflow: hidden;
// white-space: nowrap;
// text-overflow: ellipsis;

// &.@{base-element-tree}-node-title-input-active {
// display: flex;
// }
}

.@{base-element-tree}-node-title-icon {
position: absolute;
top: 6px;
top: 8px;
left: 6px;
font-size: 12px;
display: inline-flex;
Expand Down
19 changes: 16 additions & 3 deletions packages/studio-base/src/css/modules/page-tree.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@
.@{base-page-tree} {
// fix antd style
&.ant-tree {
// padding: 10px 0;

&.ant-tree-directory {
.ant-tree-treenode:before {
bottom: 0;
}
}

.ant-tree-iconEle {
display: none;
}

.ant-tree-treenode {
padding-bottom: 0;
}

.ant-tree-title {
display: flex;
width: 100%;
Expand All @@ -34,8 +46,9 @@
display: -webkit-box;
float: inline-start;
overflow: hidden;
height: 24px;
padding-left: 24px;
height: 28px;
line-height: 28px;
padding-left: 28px;
white-space: initial;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
Expand Down Expand Up @@ -63,7 +76,7 @@

.@{base-page-tree}-node-title-icon {
position: absolute;
top: 6px;
top: 8px;
left: 6px;
font-size: 14px;
display: inline-flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,8 @@ export const SolidColorPicker: React.FC<ColorPickerProps> = ({ value = '', onCha
className={className}
value={new Color(value)}
onChange={(data) => {
const hex8 = `#${data.toHex8().toUpperCase()}`;
const hex = hex8.endsWith('FF') ? `#${data.toHex().toUpperCase()}` : hex8;

const hex8 = `${data.toHexString().toUpperCase()}`;
const hex = hex8.length === 9 && hex8.endsWith('FF') ? `${data.toHexString().toUpperCase()}` : hex8;
onChange?.(hex);
}}
/>
Expand Down
53 changes: 46 additions & 7 deletions packages/studio-base/src/modules/element-tree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,38 @@ import type { TreeProps, TreeDataNode } from 'antd';
import type { ElementPosition } from 'idraw';
import { wrapTreeViewData } from './wrap';
import type { TreeNodeProps } from './tree-node';
import type { ElementTreeData } from '../../types';
import type { ElementTreeData, ElementTreeNode } from '../../types';
import { IconDown } from '../../icons';
import { generateClassName } from '../../css';

const { DirectoryTree } = Tree;
const modName = 'base-element-tree';

function reverseElementPosition(position: ElementPosition, treeData: ElementTreeData, opts?: { isToPosition: boolean }): ElementPosition {
const newPosition: ElementPosition = [];
let targetNodeList: ElementTreeNode[] = treeData;
for (let i = 0; i < position.length; i++) {
const index = position[i];
let reverseIndex = -1;
if (index === 0) {
reverseIndex = targetNodeList.length - 1;
} else if (index >= targetNodeList.length - 1) {
reverseIndex = 0;
} else {
reverseIndex = targetNodeList.length - 1 - index;
}
newPosition.push(reverseIndex);
targetNodeList = targetNodeList[reverseIndex]?.children as ElementTreeNode[];
}

if (opts?.isToPosition === true) {
if (newPosition.length > 0) {
newPosition[newPosition.length - 1] += 1;
}
}
return newPosition;
}

export type ElementTreeProps = Pick<TreeNodeProps, 'onTitleChange' | 'onOperationToggle'> & {
height: number;
className?: string;
Expand All @@ -27,6 +52,7 @@ export type ElementTreeProps = Pick<TreeNodeProps, 'onTitleChange' | 'onOperatio
onDrop?: (e: { from: ElementPosition; to: ElementPosition }) => void;
onDelete?: (e: { uuid: string }) => void;
onGoToGroup?: (e: { uuid: string; position: ElementPosition }) => void;
reverse?: boolean;
};

const treePosToElementPosition = (pos: string) => {
Expand All @@ -50,13 +76,18 @@ export const ElementTree = React.forwardRef((props: ElementTreeProps, ref: any)
defaultExpandedKeys,
onDelete,
onExpand,
onGoToGroup
onGoToGroup,
// reverse // TODO
reverse = true
} = props;

const onSelectNode: TreeProps['onSelect'] = (selectedKeys, info) => {
const onSelectNode: TreeProps['onSelect'] = (skeys, info) => {
const pos = treePosToElementPosition(info.node.pos);
const positions: ElementPosition[] = [pos];
const uuids = [selectedKeys[0]] as string[];
let positions: ElementPosition[] = [pos];
if (reverse === true) {
positions = [reverseElementPosition(pos, treeData || [])];
}
const uuids = [skeys[0]] as string[];
onSelect?.({ uuids, positions });
};

Expand All @@ -77,7 +108,8 @@ export const ElementTree = React.forwardRef((props: ElementTreeProps, ref: any)
onDelete: onElementDelete,
onGoToGroup,
position: [],
selectedKeys: selectedKeys || []
selectedKeys: selectedKeys || [],
reverse: !!reverse
});

return (
Expand Down Expand Up @@ -113,7 +145,14 @@ export const ElementTree = React.forwardRef((props: ElementTreeProps, ref: any)
} else if (node.dragOver === true) {
to.push(0);
}
onDrop?.({ from, to });
let resultFrom = from;
let resultTo = to;
if (reverse === true) {
resultFrom = reverseElementPosition(from, treeData || []);
resultTo = reverseElementPosition(to, treeData || [], { isToPosition: true });
}

onDrop?.({ from: resultFrom, to: resultTo });
}}
/>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/studio-base/src/modules/element-tree/tree-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ export const TreeNode = (props: TreeNodeProps) => {
style={style}
className={classnames(rootClassName, className, isSelected ? selectedClassName : null)}
onClick={onClickTitle}
onMouseOver={onNodeMouseOver}
onMouseLeave={onNodeMouseLeave}
// onMouseOver={onNodeMouseOver}
// onMouseLeave={onNodeMouseLeave}
onContextMenu={onNodeContextMenu}
>
<span className={titleClassName}>
Expand Down
41 changes: 30 additions & 11 deletions packages/studio-base/src/modules/element-tree/wrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,28 @@ type WrapOptions = Pick<TreeNodeProps, 'onTitleChange' | 'onOperationToggle' | '
onSelect?: (e: { uuids: string[]; positions: ElementPosition[] }) => void;
onContextMenu?: (e: { uuids: string[]; positions: ElementPosition[] }) => void;
selectedKeys: string[];
reverse: boolean;
};

export function wrapTreeViewData(elementTree: ElementTreeData, opts: WrapOptions): ElementTreeViewData {
const tree: ElementTreeViewData = [];
const { position } = opts;
const { position, reverse } = opts;
if (Array.isArray(elementTree)) {
const pos = [...position];
elementTree.forEach((node, i) => {
pos.push(i);
tree.push(wrapTreeViewNode(node, { ...opts, ...{ position: [...pos] } }));
pos.pop();
});
if (reverse === true) {
for (let i = elementTree.length - 1; i >= 0; i--) {
const node = elementTree[i];
pos.push(i);
tree.push(wrapTreeViewNode(node, { ...opts, ...{ position: [...pos] } }));
pos.pop();
}
} else {
elementTree.forEach((node, i) => {
pos.push(i);
tree.push(wrapTreeViewNode(node, { ...opts, ...{ position: [...pos] } }));
pos.pop();
});
}
}
return tree;
}
Expand Down Expand Up @@ -55,11 +65,20 @@ const wrapTreeViewNode = (treeNode: ElementTreeNode, opts: WrapOptions) => {
};
if (Array.isArray(treeNode.children)) {
const pos = [...position];
treeNode.children.forEach((child, i) => {
pos.push(i);
node.children.push(wrapTreeViewNode(child, { ...opts, ...{ position: [...pos] } }));
pos.pop();
});
if (opts.reverse === true) {
for (let i = treeNode.children.length - 1; i >= 0; i--) {
const child = treeNode.children[i];
pos.push(i);
node.children.push(wrapTreeViewNode(child, { ...opts, ...{ position: [...pos] } }));
pos.pop();
}
} else {
treeNode.children.forEach((child, i) => {
pos.push(i);
node.children.push(wrapTreeViewNode(child, { ...opts, ...{ position: [...pos] } }));
pos.pop();
});
}
}
return node;
};
59 changes: 54 additions & 5 deletions packages/studio-base/src/modules/page-tree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type PageTreeProps = Pick<TreeNodeProps, 'onTitleChange' | 'onOperationTo
onSelect?: (e: { uuids: string[]; positions: ElementPosition[] }) => void;
onDrop?: (e: { from: ElementPosition; to: ElementPosition }) => void;
onDelete?: (e: { uuid: string }) => void;
reverse?: boolean;
};

const treePosToElementPosition = (pos: string) => {
Expand All @@ -32,12 +33,52 @@ const treePosToElementPosition = (pos: string) => {
return elemPos;
};

function reverseElementPosition(position: ElementPosition, treeData: PageTreeData, opts?: { isToPosition: boolean }): ElementPosition {
const newPosition: ElementPosition = [];
for (let i = 0; i < position.length; i++) {
const index = position[i];
let reverseIndex = -1;
if (index === 0) {
reverseIndex = treeData.length - 1;
} else if (index >= treeData.length - 1) {
reverseIndex = 0;
} else {
reverseIndex = treeData.length - 1 - index;
}
newPosition.push(reverseIndex);
}

if (opts?.isToPosition === true) {
if (newPosition.length > 0) {
newPosition[newPosition.length - 1] += 1;
}
}
return newPosition;
}

export const PageTree = React.forwardRef((props: PageTreeProps, ref: any) => {
const { height, className, style, treeData, onTitleChange, onOperationToggle, onSelect, selectedKeys, onDrop, defaultExpandedKeys, expandedKeys, onDelete } =
props;
const {
height,
className,
style,
treeData,
onTitleChange,
onOperationToggle,
onSelect,
selectedKeys,
onDrop,
defaultExpandedKeys,
expandedKeys,
onDelete,
// reverse // TODO
reverse = true
} = props;
const onSelectNode: TreeProps['onSelect'] = (selectedKeys, info) => {
const pos = treePosToElementPosition(info.node.pos);
const positions: ElementPosition[] = [pos];
let positions: ElementPosition[] = [pos];
if (reverse === true) {
positions = [reverseElementPosition(pos, treeData || [])];
}
const uuids = [selectedKeys[0]] as string[];
onSelect?.({ uuids, positions });
};
Expand All @@ -54,7 +95,8 @@ export const PageTree = React.forwardRef((props: PageTreeProps, ref: any) => {
onOperationToggle,
onDelete: onElementDelete,
position: [],
selectedKeys: selectedKeys || []
selectedKeys: selectedKeys || [],
reverse: !!reverse
});

return (
Expand Down Expand Up @@ -94,7 +136,14 @@ export const PageTree = React.forwardRef((props: PageTreeProps, ref: any) => {
} else if (node.dragOver === true) {
to.push(0);
}
onDrop?.({ from, to });
let resultFrom = from;
let resultTo = to;
if (reverse === true) {
resultFrom = reverseElementPosition(from, treeData || []);
resultTo = reverseElementPosition(to, treeData || [], { isToPosition: true });
}

onDrop?.({ from: resultFrom, to: resultTo });
}}
/>
);
Expand Down
Loading

0 comments on commit edb75be

Please sign in to comment.