Skip to content

Commit

Permalink
Merge pull request #77 from idrawjs/dev-v0.4
Browse files Browse the repository at this point in the history
feat: add editMode
  • Loading branch information
chenshenhai authored Apr 6, 2024
2 parents 90e6e94 + d16fb0e commit d63a0a3
Show file tree
Hide file tree
Showing 37 changed files with 1,304 additions and 140 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"private": false,
"version": "0.4.0-alpha.19",
"version": "0.4.0-alpha.20",
"workspaces": [
"packages/*"
],
Expand All @@ -19,7 +19,7 @@
"upgrade:version": "vite-node ./scripts/upgrade-version.ts && pnpm i"
},
"dependencies": {
"idraw": "0.4.0-beta.19",
"idraw": "0.4.0-beta.20",
"antd": "5.12.1"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/studio-base/src/css/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@import './modules/theme-switch.less';
@import './modules/locale-selector.less';
@import './modules/scale-selector.less';
@import './modules/page-tree.less';
@import './modules/element-tree.less';
@import './modules/element-detail.less';
@import './modules/layout-detail.less';
96 changes: 96 additions & 0 deletions packages/studio-base/src/css/modules/page-tree.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// @import "../variable.less";

@base-page-tree: ~'@{prefix}-base-page-tree';

.@{base-page-tree} {
// fix antd style
&.ant-tree {
.ant-tree-iconEle {
display: none;
}

.ant-tree-title {
display: flex;
width: 100%;
}

.ant-tree-switcher {
display: flex;
justify-content: center;
align-items: center;
}
}

.@{base-page-tree}-node {
position: relative;
display: flex;
width: 100%;
flex-direction: row;
justify-content: space-between;
}

.@{base-page-tree}-node-title {
position: relative;
display: -webkit-box;
float: inline-start;
overflow: hidden;
height: 24px;
padding-left: 24px;
white-space: initial;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}

.@{base-page-tree}-node-title-input {
background: ~'var(--@{prefix}-bg-color)';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: inline-flex;
// display: none;
float: inline-start;
// overflow: hidden;
// white-space: nowrap;
// text-overflow: ellipsis;

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

.@{base-page-tree}-node-title-icon {
position: absolute;
top: 6px;
left: 6px;
font-size: 14px;
display: inline-flex;
width: 14px;
margin-right: 6px;
}

.@{base-page-tree}-node-action {
position: absolute;
top: 0;
bottom: 0;
right: 0;
display: inline-flex;
float: inline-end;
padding: 0 8px;
background: ~'var(--@{prefix}-bg-color)';
}

.@{base-page-tree}-node-icon {
font-size: 12px;
margin-left: 4px;
cursor: pointer;
}

.@{base-page-tree}-node-selected {
.@{base-page-tree}-node-action {
background: ~'var(--@{prefix}-common-primary-color)';
}
}
}
1 change: 1 addition & 0 deletions packages/studio-base/src/css/theme/dark.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
--@{prefix}-text-color: @gray-4;
--@{prefix}-text-hover-color: @gray-1;
--@{prefix}-border-color: @gray-6;
--@{prefix}-shadow-color: @gray-7;
--@{prefix}-border-outline-color: @gray-2;
--@{prefix}-primary-color: @blue-6;

Expand Down
1 change: 1 addition & 0 deletions packages/studio-base/src/css/theme/light.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
--@{prefix}-text-color: @gray-6;
--@{prefix}-text-hover-color: @gray-10;
--@{prefix}-border-color: @gray-4;
--@{prefix}-shadow-color: @gray-3;
--@{prefix}-border-outline-color: @gray-8;
--@{prefix}-primary-color: @blue-5;

Expand Down
2 changes: 2 additions & 0 deletions packages/studio-base/src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import IconIndent from './indent';
import IconImage from './image';
import IconInvisible from './invisible';
import IconLayer from './layer';
import IconLayout from './layout';
import IconLeft from './left';
import IconLight from './light';
import IconLike from './like';
Expand Down Expand Up @@ -118,6 +119,7 @@ export {
IconImage,
IconInvisible,
IconLayer,
IconLayout,
IconLeft,
IconLight,
IconLike,
Expand Down
15 changes: 15 additions & 0 deletions packages/studio-base/src/icons/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { IconWrapper } from './util';
import type { IconWrapperProps } from './util';

const Icon = (props: IconWrapperProps) => {
return (
<IconWrapper {...props}>
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor">
<path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32z m-696 72h136v656H184V184z m656 656H384V384h456v456zM384 320V184h456v136H384z"></path>
</svg>
</IconWrapper>
);
};

export default Icon;
4 changes: 3 additions & 1 deletion packages/studio-base/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ export { ThemeSwitch, type ThemeSwitchProps } from './modules/theme-switch';
export { LocaleSelector, type LocaleSelectorProps } from './modules/locale-selector';
export { ScaleSelector, type ScaleSelectorProps } from './modules/scale-selector';
export { ElementTree, type ElementTreeProps } from './modules/element-tree';
export { PageTree, type PageTreeProps } from './modules/page-tree';
export { ElementDetail, type ElementDetailProps } from './modules/element-detail';
export { LayoutDetail, type LayoutDetailProps } from './modules/layout-detail';

export { getElementTree } from './tools';
export { getElementTree, getPageTree } from './tools';
export { setClassNameTopPrefix, generateClassName } from './css/index';
export { useThemeClassName } from './hooks/theme';
export * from './locale/types';
Expand Down Expand Up @@ -60,6 +61,7 @@ export {
IconImage,
IconInvisible,
IconLayer,
IconLayout,
IconLeft,
IconLight,
IconLike,
Expand Down
3 changes: 2 additions & 1 deletion packages/studio-base/src/modules/element-tree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const ElementTree = React.forwardRef((props: ElementTreeProps, ref: any)
onExpand,
onGoToGroup
} = props;

const onSelectNode: TreeProps['onSelect'] = (selectedKeys, info) => {
const pos = treePosToElementPosition(info.node.pos);
const positions: ElementPosition[] = [pos];
Expand Down Expand Up @@ -83,7 +84,7 @@ export const ElementTree = React.forwardRef((props: ElementTreeProps, ref: any)
className={classnames(generateClassName(modName), className)}
showLine
blockNode
multiple
// multiple
selectedKeys={selectedKeys}
switcherIcon={<IconDown />}
// icon={(props: any) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/studio-base/src/modules/element-tree/wrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ type WrapOptions = Pick<TreeNodeProps, 'onTitleChange' | 'onOperationToggle' | '
selectedKeys: string[];
};

export function wrapTreeViewData(treeData: ElementTreeData, opts: WrapOptions): ElementTreeViewData {
export function wrapTreeViewData(elementTree: ElementTreeData, opts: WrapOptions): ElementTreeViewData {
const tree: ElementTreeViewData = [];
const { position } = opts;
if (Array.isArray(treeData)) {
if (Array.isArray(elementTree)) {
const pos = [...position];
treeData.forEach((node, i) => {
elementTree.forEach((node, i) => {
pos.push(i);
tree.push(wrapTreeViewNode(node, { ...opts, ...{ position: [...pos] } }));
pos.pop();
Expand Down
102 changes: 102 additions & 0 deletions packages/studio-base/src/modules/page-tree/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React, { useMemo } from 'react';
import classnames from 'classnames';
import { Tree } from 'antd';
import type { CSSProperties } from 'react';
import type { TreeProps } from 'antd';
import type { ElementPosition } from 'idraw';
import { wrapTreeViewData } from './wrap';
import type { TreeNodeProps } from './tree-node';
import type { PageTreeData } from '../../types';
import { IconDown } from '../../icons';
import { generateClassName } from '../../css';

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

export type PageTreeProps = Pick<TreeNodeProps, 'onTitleChange' | 'onOperationToggle'> & {
height: number;
className?: string;
style?: CSSProperties;
treeData?: PageTreeData;
selectedKeys?: string[];
defaultExpandedKeys?: string[];
expandedKeys?: string[];
onSelect?: (e: { uuids: string[]; positions: ElementPosition[] }) => void;
onDrop?: (e: { from: ElementPosition; to: ElementPosition }) => void;
onDelete?: (e: { uuid: string }) => void;
};

const treePosToElementPosition = (pos: string) => {
const elemPos: ElementPosition = pos.split('-').map((i) => parseInt(i));
elemPos.shift();
return elemPos;
};

export const PageTree = React.forwardRef((props: PageTreeProps, ref: any) => {
const { height, className, style, treeData, onTitleChange, onOperationToggle, onSelect, selectedKeys, onDrop, defaultExpandedKeys, expandedKeys, onDelete } =
props;
const onSelectNode: TreeProps['onSelect'] = (selectedKeys, info) => {
const pos = treePosToElementPosition(info.node.pos);
const positions: ElementPosition[] = [pos];
const uuids = [selectedKeys[0]] as string[];
onSelect?.({ uuids, positions });
};

const onElementDelete: PageTreeProps['onDelete'] = ({ uuid }) => {
onDelete?.({ uuid });
};

return useMemo(() => {
const wrappedTreeData = wrapTreeViewData(treeData || [], {
parentModName: modName,
generateClassName,
onTitleChange,
onOperationToggle,
onDelete: onElementDelete,
position: [],
selectedKeys: selectedKeys || []
});

return (
<DirectoryTree
ref={ref}
height={height}
style={style}
className={classnames(generateClassName(modName), className)}
showLine
blockNode
// multiple
selectedKeys={selectedKeys}
switcherIcon={<IconDown />}
// icon={(props: any) => {
// const type: ElementType | undefined = props?.data?.title?.props?.type;
// return getIcon(type);
// }}
icon={null}
onSelect={onSelectNode}
treeData={wrappedTreeData}
defaultExpandedKeys={defaultExpandedKeys}
expandedKeys={expandedKeys}
draggable={{
icon: false,
nodeDraggable: () => true
}}
onDrop={(info) => {
const { dragNode, node, dropToGap, dropPosition } = info;
const from: ElementPosition = treePosToElementPosition(dragNode.pos);
const to: ElementPosition = treePosToElementPosition(node.pos);
if (dropToGap === true && dropPosition >= 0) {
to[to.length - 1] = dropPosition;
} else if (node.dragOverGapBottom === true) {
to[to.length - 1] = to[to.length - 1] + 1;
} else if (node.dragOverGapTop === true) {
to[to.length - 1] = Math.max(0, to[to.length - 1] - 1);
} else if (node.dragOver === true) {
to.push(0);
}
onDrop?.({ from, to });
}}
/>
);
}, [className, style, onSelectNode, treeData, selectedKeys]);
});
Loading

0 comments on commit d63a0a3

Please sign in to comment.