Skip to content

Commit 02d88a3

Browse files
authored
Merge pull request #53 from idrawjs/dev-v0.4
feat: add export files features
2 parents 19cdfc9 + ccc5c0a commit 02d88a3

File tree

29 files changed

+715
-223
lines changed

29 files changed

+715
-223
lines changed

README.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,7 @@
1313
<a href="https://idraw.js.org/studio/" target="_blank">idraw.js.org/studio/</a>
1414
</p>
1515

16-
> Note:
17-
> At present, the development content of the main branch is v0.4, and it is currently in the development and reconstruction stage, mainly based on the v0.3 version for optimization and reconstruction.
18-
> The npm module is version v0.2.0-alpha.*. If you encounter any problems while using the npm module, you can view the content of this branch: [https://github.com/idrawjs/studio/tree/v0.3](https://github.com/idrawjs/studio/tree/v0.3)
19-
20-
21-
> 注意:
22-
> 当前`main`分支开发内容为`v0.4`,目前处于开发重构阶段,主要基于`v0.3`版本进行优化重构。
23-
> 目前npm 模块是`v0.3 `版本。 如果你在使用npm模块的过程中遇到什么问题,可以查看这个分支的内容: [https://github.com/idrawjs/studio/tree/v0.3](https://github.com/idrawjs/studio/tree/v0.3)
24-
25-
16+
2617
## @idraw/studio Preview
2718

2819
You can click [idraw.js.org/studio/](https://idraw.js.org/studio) to experience it.
@@ -84,7 +75,7 @@ git clone [email protected]:idrawjs/studio.git
8475

8576
cd studio
8677

87-
npm install
78+
pnpm install
8879

8980
npm run dev
9081
```

examples/studio-dist/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ const App = () => {
2424

2525
return (
2626
<Studio
27+
logo={
28+
<span style={{ display: 'inline-flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
29+
<img style={{ width: 24, marginRight: 10 }} src="https://github.com/idrawjs/idraw/assets/8216630/bcf8fbc6-6374-4cb9-a67f-1687d029a863" />
30+
<span>@idraw/studio</span>
31+
</span>
32+
}
2733
width={width}
2834
height={height}
2935
style={style}

examples/studio/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ const App = () => {
2424

2525
return (
2626
<Studio
27+
logo={
28+
<span style={{ display: 'inline-flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
29+
<img style={{ width: 24, marginRight: 10 }} src="https://github.com/idrawjs/idraw/assets/8216630/bcf8fbc6-6374-4cb9-a67f-1687d029a863" />
30+
<span>@idraw/studio</span>
31+
</span>
32+
}
2733
width={width}
2834
height={height}
2935
style={style}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"private": false,
3-
"version": "0.4.0-alpha.5",
3+
"version": "0.4.0-alpha.6",
44
"workspaces": [
55
"packages/*"
66
],
@@ -19,7 +19,7 @@
1919
"upgrade:version": "vite-node ./scripts/upgrade-version.ts && pnpm i"
2020
},
2121
"dependencies": {
22-
"idraw": "0.4.0-beta.1",
22+
"idraw": "0.4.0-beta.4",
2323
"antd": "5.12.1"
2424
},
2525
"devDependencies": {

packages/studio-base/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@idraw/studio-base",
3-
"version": "0.4.0-alpha.5",
3+
"version": "0.4.0-alpha.6",
44
"main": "dist/index.js",
55
"module": "dist/index.js",
66
"types": "dist/index.d.ts",
@@ -22,7 +22,7 @@
2222
"peerDependencies": {
2323
"antd": "^5.12.1",
2424
"classnames": "^2.3.2",
25-
"idraw": "^0.4.0-beta.1",
25+
"idraw": "^0.4.0-beta.4",
2626
"react": "^18.2.0",
2727
"react-color": "^2.19.3",
2828
"react-dom": "^18.2.0"

packages/studio-base/src/css/modules/element-tree.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
top: 0;
4949
bottom: 0;
5050
left: 0;
51-
right: 8px;
51+
right: 0;
5252
display: inline-flex;
5353
// display: none;
5454
float: inline-start;

packages/studio-base/src/css/modules/scale-selector.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
.@{base-scale-selector}-menu-item {
1616
display: inline-flex;
17-
width: 150px;
17+
width: 100px;
1818

1919
.@{base-scale-selector}-input {
2020
width: 100%;

packages/studio-base/src/modules/element-tree/index.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import classnames from 'classnames';
33
import { Tree } from 'antd';
44
import DownOutlined from '@ant-design/icons/DownOutlined';
55
import type { CSSProperties } from 'react';
6-
import type { TreeProps } from 'antd';
6+
import type { TreeProps, TreeDataNode } from 'antd';
77
import type { ElementPosition } from 'idraw';
88
import { ConfigContext } from '../config-provider';
99
import { wrapTreeViewData } from './wrap';
@@ -13,17 +13,15 @@ import type { ElementTreeData } from '../../types';
1313
const { DirectoryTree } = Tree;
1414
const modName = 'base-element-tree';
1515

16-
export type ElementTreeProps = Pick<
17-
TreeNodeProps,
18-
'onTitleChange' | 'onOperationToggle'
19-
> & {
16+
export type ElementTreeProps = Pick<TreeNodeProps, 'onTitleChange' | 'onOperationToggle'> & {
2017
height: number;
2118
className?: string;
2219
style?: CSSProperties;
2320
treeData?: ElementTreeData;
2421
selectedKeys?: string[];
2522
defaultExpandedKeys?: string[];
2623
expandedKeys?: string[];
24+
onExpand?: (keys: string[], e: { expanded: boolean; nativeEvent: React.PointerEvent; node: TreeDataNode }) => void;
2725
defaultExpandAll?: boolean;
2826
onSelect?: (e: { uuids: string[]; positions: ElementPosition[] }) => void;
2927
onDrop?: (e: { from: ElementPosition; to: ElementPosition }) => void;
@@ -36,7 +34,7 @@ const treePosToElementPosition = (pos: string) => {
3634
return elemPos;
3735
};
3836

39-
export const ElementTree = (props: ElementTreeProps) => {
37+
export const ElementTree = React.forwardRef((props: ElementTreeProps, ref: any) => {
4038
const {
4139
height,
4240
className,
@@ -48,7 +46,9 @@ export const ElementTree = (props: ElementTreeProps) => {
4846
selectedKeys,
4947
onDrop,
5048
defaultExpandedKeys,
51-
onDelete
49+
expandedKeys,
50+
onDelete,
51+
onExpand
5252
} = props;
5353
const { createPrefixName } = useContext(ConfigContext);
5454
const getPrefixName = createPrefixName(modName);
@@ -68,16 +68,19 @@ export const ElementTree = (props: ElementTreeProps) => {
6868
getPrefixName,
6969
onTitleChange,
7070
onOperationToggle,
71-
onDelete: onElementDelete
71+
onDelete: onElementDelete,
72+
position: []
7273
});
7374

7475
return (
7576
<DirectoryTree
77+
ref={ref}
7678
height={height}
7779
style={style}
7880
className={classnames(getPrefixName(), className)}
7981
showLine
8082
blockNode
83+
multiple
8184
selectedKeys={selectedKeys}
8285
switcherIcon={<DownOutlined />}
8386
// icon={(props: any) => {
@@ -88,8 +91,9 @@ export const ElementTree = (props: ElementTreeProps) => {
8891
onSelect={onSelectNode}
8992
treeData={wrappedTreeData}
9093
defaultExpandedKeys={defaultExpandedKeys}
91-
// expandedKeys={expandedKeys}
94+
expandedKeys={expandedKeys}
9295
// defaultExpandAll={defaultExpandAll}
96+
onExpand={onExpand as any}
9397
draggable={{
9498
icon: false,
9599
nodeDraggable: () => true
@@ -112,4 +116,4 @@ export const ElementTree = (props: ElementTreeProps) => {
112116
/>
113117
);
114118
}, [className, style, onSelectNode, treeData, selectedKeys]);
115-
};
119+
});

packages/studio-base/src/modules/element-tree/tree-node.tsx

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import React, { useMemo, useState, useRef } from 'react';
1+
import React, { useMemo, useState, useRef, useEffect } from 'react';
22
import type { CSSProperties } from 'react';
33
import classnames from 'classnames';
4-
import type { ElementType, ElementOperations } from 'idraw';
4+
import type { ElementType, ElementOperations, ElementPosition } from 'idraw';
55
import { Input } from 'antd';
6+
import type { InputRef } from 'antd';
67
import IconVisible from '../../icons/visible';
78
import IconInvisible from '../../icons/invisible';
89
// import IconUnlock from '../../icons/unlock';
910
// import IconLock from '../../icons/lock';
10-
import IconCheck from '../../icons/check';
11+
// import IconCheck from '../../icons/check';
1112
import IconRect from '../../icons/rect';
1213
import IconCircle from '../../icons/circle';
1314
import IconText from '../../icons/text';
@@ -16,28 +17,31 @@ import IconStar from '../../icons/star';
1617
import IconImage from '../../icons/image';
1718
import IconPath from '../../icons/path';
1819
import IconHTML from '../../icons/html';
19-
import IconEdit from '../../icons/edit';
20+
// import IconEdit from '../../icons/edit';
2021
// import IconDelete from '../../icons/delete';
2122

2223
import IconCloseCircle from '../../icons/close-circle';
2324

2425
const modName = 'node';
2526

2627
export interface TreeNodeProps {
28+
uuid: string;
2729
nodeKey: string;
2830
title: string;
29-
operatinos: ElementOperations;
31+
operations: ElementOperations;
32+
position: ElementPosition;
3033
className?: string;
3134
type?: ElementType;
3235
style?: CSSProperties;
3336
getPrefixName: (...args: string[]) => string;
3437
onTitleChange?: (e: { uuid: string; value: string }) => void;
3538
onOperationToggle?: (e: { uuid: string; operations: ElementOperations }) => void;
3639
onDelete?: (e: { uuid: string }) => void;
40+
onSelect?: (e: { uuids: string[]; positions: ElementPosition[] }) => void;
3741
}
3842

3943
export const TreeNode = (props: TreeNodeProps) => {
40-
const { className, style, type, nodeKey, title, getPrefixName, onTitleChange, onOperationToggle, onDelete, operatinos } = props;
44+
const { className, style, type, uuid, nodeKey, title, position, getPrefixName, onTitleChange, onOperationToggle, onDelete, onSelect, operations } = props;
4145
const [isEdit, setIsEdit] = useState<boolean>(false);
4246
const [showAction, setShowAction] = useState<boolean>(false);
4347
const refTitle = useRef<string>(title);
@@ -48,6 +52,8 @@ export const TreeNode = (props: TreeNodeProps) => {
4852
const titleInputClassName = getPrefixName(modName, 'title', 'input');
4953
const titleIconClassName = getPrefixName(modName, 'title', 'icon');
5054
const actionClassName = getPrefixName(modName, 'action');
55+
const clickTime = useRef<number>(0);
56+
const refInput = useRef<InputRef | null>(null);
5157

5258
// useEffect(() => {
5359
// refTitle.current = title;
@@ -71,15 +77,21 @@ export const TreeNode = (props: TreeNodeProps) => {
7177
// setIsEdit(true);
7278
// };
7379

80+
useEffect(() => {
81+
if (isEdit === true) {
82+
refInput.current?.focus();
83+
}
84+
}, [isEdit]);
85+
7486
const onTitleInputBlur = (e: React.FocusEvent<HTMLInputElement, Element>) => {
7587
setIsEdit(false);
7688
onTitleChange?.({ uuid: nodeKey, value: e.target.value || '' });
7789
};
78-
const onTitleInputOk = (e: any) => {
79-
e.stopPropagation();
80-
setIsEdit(false);
81-
onTitleChange?.({ uuid: nodeKey, value: refTitle.current || '' });
82-
};
90+
// const onTitleInputOk = (e: any) => {
91+
// e.stopPropagation();
92+
// setIsEdit(false);
93+
// onTitleChange?.({ uuid: nodeKey, value: refTitle.current || '' });
94+
// };
8395
const onTitleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
8496
refTitle.current = e.target.value || '';
8597
};
@@ -105,10 +117,26 @@ export const TreeNode = (props: TreeNodeProps) => {
105117
setShowAction(false);
106118
};
107119

108-
const onClickToEdit = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
109-
e.stopPropagation();
110-
e.preventDefault();
111-
setIsEdit(true);
120+
// const onClickToEdit = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
121+
// e.stopPropagation();
122+
// e.preventDefault();
123+
// setIsEdit(true);
124+
// };
125+
126+
const onClickTitle = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
127+
const nowTime = Date.now();
128+
const countTime = nowTime - clickTime.current;
129+
clickTime.current = nowTime;
130+
131+
onSelect?.({
132+
uuids: [uuid],
133+
positions: [position]
134+
});
135+
if (countTime <= 300 && countTime > 0) {
136+
e.stopPropagation();
137+
e.preventDefault();
138+
setIsEdit(true);
139+
}
112140
};
113141

114142
const onClickToDelete = (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
@@ -125,7 +153,7 @@ export const TreeNode = (props: TreeNodeProps) => {
125153
onOperationToggle?.({
126154
uuid: nodeKey,
127155
operations: {
128-
invisible: !operatinos.invisible
156+
invisible: !operations.invisible
129157
}
130158
});
131159
};
@@ -136,7 +164,7 @@ export const TreeNode = (props: TreeNodeProps) => {
136164
// onOperationToggle?.({
137165
// uuid: nodeKey,
138166
// operations: {
139-
// lock: !operatinos.lock
167+
// lock: !operations.lock
140168
// }
141169
// });
142170
// };
@@ -165,42 +193,50 @@ export const TreeNode = (props: TreeNodeProps) => {
165193
}
166194

167195
return (
168-
<span key={nodeKey} style={style} className={classnames(rootClassName, className)} onMouseOver={onNodeMouseOver} onMouseLeave={onNodeMouseLeave}>
196+
<span
197+
key={nodeKey}
198+
style={style}
199+
className={classnames(rootClassName, className)}
200+
onClick={onClickTitle}
201+
onMouseOver={onNodeMouseOver}
202+
onMouseLeave={onNodeMouseLeave}
203+
>
169204
<span className={titleClassName}>
170205
{getIcon(type)}
171206
<span>{title}</span>
172207
</span>
173208
{showAction && (
174209
<span className={actionClassName}>
175-
{operatinos.invisible ? (
210+
{operations.invisible ? (
176211
<IconInvisible className={iconClassName} onClick={onClickToggleVisible} />
177212
) : (
178213
<IconVisible className={iconClassName} onClick={onClickToggleVisible} />
179214
)}
180-
{/* {operatinos.lock ? (
215+
{/* {operations.lock ? (
181216
<IconLock className={iconClassName} onClick={onClickToggleLock} />
182217
) : (
183218
<IconUnlock className={iconClassName} onClick={onClickToggleLock} />
184219
)} */}
185-
<IconEdit className={iconClassName} onClick={onClickToEdit} />
220+
{/* <IconEdit className={iconClassName} onClick={onClickToEdit} /> */}
186221
<IconCloseCircle className={iconClassName} onClick={onClickToDelete} />
187222
</span>
188223
)}
189224

190225
{isEdit && (
191226
<span className={titleInputClassName}>
192227
<Input
228+
ref={refInput}
193229
size="small"
194230
defaultValue={title}
195231
onBlur={onTitleInputBlur}
196232
onClick={onTitleInputClick}
197233
onKeyDown={onTitleInputKeyDown}
198234
onChange={onTitleInputChange}
199-
addonAfter={<IconCheck onClick={onTitleInputOk} />}
235+
// addonAfter={<IconCheck onClick={onTitleInputOk} />}
200236
/>
201237
</span>
202238
)}
203239
</span>
204240
);
205-
}, [nodeKey, title, isEdit, type, showAction, operatinos]);
241+
}, [nodeKey, title, isEdit, type, showAction, operations]);
206242
};

0 commit comments

Comments
 (0)