Skip to content

Commit 81f967d

Browse files
authored
Merge pull request #96 from webzard-io/ysj/dev
feat: component tree sorting is supported
2 parents c32d614 + 1e2e583 commit 81f967d

File tree

4 files changed

+81
-10
lines changed

4 files changed

+81
-10
lines changed

packages/editor/src/components/StructureTree/ComponentItemView.tsx

+38-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChevronDownIcon, ChevronRightIcon, DeleteIcon } from '@chakra-ui/icons';
1+
import { ArrowDownIcon, ArrowUpIcon, ChevronDownIcon, ChevronRightIcon, DeleteIcon } from '@chakra-ui/icons';
22
import { Box, HStack, IconButton, Text } from '@chakra-ui/react';
33
import { useState } from 'react';
44

@@ -11,6 +11,9 @@ type Props = {
1111
isExpanded?: boolean;
1212
onToggleExpanded?: () => void;
1313
isDroppable?: boolean;
14+
isSortable?: boolean;
15+
onMoveUp?: () => void;
16+
onMoveDown?: () => void;
1417
};
1518

1619
export const ComponentItemView: React.FC<Props> = props => {
@@ -23,6 +26,9 @@ export const ComponentItemView: React.FC<Props> = props => {
2326
onToggleExpanded,
2427
onClickRemove,
2528
isDroppable,
29+
isSortable = false,
30+
onMoveUp,
31+
onMoveDown
2632
} = props;
2733

2834
const [isDragOver, setIsDragOver] = useState(false);
@@ -60,15 +66,37 @@ export const ComponentItemView: React.FC<Props> = props => {
6066
<Text color={isSelected ? 'red.500' : 'black'} onClick={onClick} cursor="pointer">
6167
{title}
6268
</Text>
63-
{onClickRemove ? (
64-
<IconButton
65-
variant="ghost"
66-
size="smx"
67-
aria-label="remove"
68-
icon={<DeleteIcon />}
69-
onClick={onClickRemove}
70-
/>
71-
) : null}
69+
<Box display="flex" alignItems="center">
70+
{onClickRemove ? (
71+
<Box>
72+
<IconButton
73+
variant="ghost"
74+
size="smx"
75+
aria-label="remove"
76+
icon={<DeleteIcon />}
77+
onClick={onClickRemove}
78+
/>
79+
</Box>
80+
) : null}
81+
{isSortable ? (
82+
<Box>
83+
<IconButton
84+
variant="ghost"
85+
size="smx"
86+
aria-label="remove"
87+
icon={<ArrowUpIcon />}
88+
onClick={onMoveUp}
89+
/>
90+
<IconButton
91+
variant="ghost"
92+
size="smx"
93+
aria-label="remove"
94+
icon={<ArrowDownIcon />}
95+
onClick={onMoveDown}
96+
/>
97+
</Box>
98+
) : null}
99+
</Box>
72100
</HStack>
73101
</Box>
74102
);

packages/editor/src/components/StructureTree/ComponentTree.tsx

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { registry } from '../../metaUI';
66
import {
77
CreateComponentOperation,
88
RemoveComponentOperation,
9+
SortComponentOperation,
910
} from '../../operations/Operations';
1011
import { ComponentItemView } from './ComponentItemView';
1112
import { DropComponentWrapper } from './DropComponentWrapper';
@@ -89,6 +90,14 @@ export const ComponentTree: React.FC<Props> = props => {
8990
);
9091
};
9192

93+
const onMoveUp = () => {
94+
eventBus.send('operation', new SortComponentOperation(component.id, 'up'));
95+
};
96+
97+
const onMoveDown = () => {
98+
eventBus.send('operation', new SortComponentOperation(component.id, 'down'));
99+
};
100+
92101
return (
93102
<VStack
94103
key={component.id}
@@ -109,6 +118,9 @@ export const ComponentTree: React.FC<Props> = props => {
109118
isExpanded={isExpanded}
110119
onToggleExpanded={() => setIsExpanded(prev => !prev)}
111120
isDroppable={slots.length > 0}
121+
isSortable={true}
122+
onMoveUp={onMoveUp}
123+
onMoveDown={onMoveDown}
112124
/>
113125
</DropComponentWrapper>
114126
{isExpanded ? slotsEle : null}

packages/editor/src/operations/AppModelManager.ts

+24
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ModifyComponentPropertyOperation,
88
ModifyTraitPropertyOperation,
99
ModifyComponentIdOperation,
10+
SortComponentOperation,
1011
AddTraitOperation,
1112
RemoveTraitOperation,
1213
ModifyTraitPropertiesOperation,
@@ -227,6 +228,29 @@ export class AppModelManager {
227228
c.traits.splice(rto.traitIndex, 1);
228229
}
229230
});
231+
break;
232+
case 'sortComponent':
233+
const sortO = o as SortComponentOperation;
234+
newApp = produce(this.app, draft => {
235+
const iIndex = draft.spec.components.findIndex(c => c.id === sortO.componentId);
236+
const iComponent = this.app.spec.components[iIndex];
237+
const iSlotTrait = iComponent.traits.find(t => t.type === 'core/v1/slot');
238+
if (!iSlotTrait) return;
239+
240+
const findArray = sortO.direction === 'up' ? this.app.spec.components.slice(0, iIndex).reverse() : this.app.spec.components.slice(iIndex + 1);
241+
242+
const jComponent = findArray.find(c => {
243+
const jSlotTrait = c.traits.find(t => t.type === 'core/v1/slot');
244+
if (jSlotTrait){
245+
return _.isEqual(jSlotTrait, iSlotTrait);
246+
}
247+
});
248+
if (!jComponent) return;
249+
250+
const jIndex = this.app.spec.components.findIndex(c => c.id === jComponent.id);
251+
if (jIndex > -1) {
252+
[draft.spec.components[iIndex],draft.spec.components[jIndex]] = [draft.spec.components[jIndex],draft.spec.components[iIndex]];
253+
}
230254
});
231255
break;
232256
}

packages/editor/src/operations/Operations.ts

+7
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,10 @@ export class ModifyTraitPropertiesOperation {
6464
public properties: Record<string, any>
6565
) {}
6666
}
67+
export class SortComponentOperation {
68+
kind = 'sortComponent';
69+
constructor(
70+
public componentId: string,
71+
public direction: 'up' | 'down'
72+
) {}
73+
}

0 commit comments

Comments
 (0)