mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
structure tree can toggle show children & hide slotName
This commit is contained in:
parent
259db6be0f
commit
7ab90ca6ec
@ -1,27 +1,53 @@
|
||||
import { DeleteIcon } from '@chakra-ui/icons';
|
||||
import { HStack, IconButton, Text } from '@chakra-ui/react';
|
||||
import { ChevronDownIcon, ChevronRightIcon, DeleteIcon } from '@chakra-ui/icons';
|
||||
import { Box, HStack, IconButton, Text } from '@chakra-ui/react';
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
isSelected: boolean;
|
||||
onClick: () => void;
|
||||
onClickRemove: () => void;
|
||||
noChevron: boolean;
|
||||
isExpanded?: boolean;
|
||||
onToggleExpanded?: () => void;
|
||||
};
|
||||
|
||||
export const ComponentItemView: React.FC<Props> = props => {
|
||||
const { title, isSelected, onClick, onClickRemove } = props;
|
||||
const {
|
||||
title,
|
||||
isSelected,
|
||||
noChevron,
|
||||
isExpanded,
|
||||
onClick,
|
||||
onToggleExpanded,
|
||||
onClickRemove,
|
||||
} = props;
|
||||
|
||||
const expandIcon = (
|
||||
<IconButton
|
||||
position="absolute"
|
||||
left="-5"
|
||||
aria-label="showChildren"
|
||||
size="xs"
|
||||
variant="unstyled"
|
||||
onClick={onToggleExpanded}
|
||||
icon={isExpanded ? <ChevronDownIcon /> : <ChevronRightIcon />}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<HStack width="full" justify="space-between">
|
||||
<Text color={isSelected ? 'red.500' : 'black'} onClick={onClick}>
|
||||
{title}
|
||||
</Text>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
aria-label="remove"
|
||||
icon={<DeleteIcon />}
|
||||
onClick={onClickRemove}
|
||||
/>
|
||||
</HStack>
|
||||
<Box width="full">
|
||||
{noChevron ? null : expandIcon}
|
||||
<HStack width="full" justify="space-between">
|
||||
<Text color={isSelected ? 'red.500' : 'black'} onClick={onClick}>
|
||||
{title}
|
||||
</Text>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
size="smx"
|
||||
aria-label="remove"
|
||||
icon={<DeleteIcon />}
|
||||
onClick={onClickRemove}
|
||||
/>
|
||||
</HStack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Box, Text } from '@chakra-ui/react';
|
||||
import { Box, Text, VStack } from '@chakra-ui/react';
|
||||
import { ApplicationComponent } from '@meta-ui/core';
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { eventBus } from '../../eventBus';
|
||||
import { registry } from '../../metaUI';
|
||||
import {
|
||||
@ -20,6 +20,7 @@ type Props = {
|
||||
export const ComponentTree: React.FC<Props> = props => {
|
||||
const { component, childrenMap, selectedComponentId, onSelectComponent } = props;
|
||||
const slots = registry.getComponentByType(component.type).spec.slots;
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
|
||||
const slotsEle = useMemo(() => {
|
||||
if (slots.length === 0) {
|
||||
@ -49,6 +50,8 @@ export const ComponentTree: React.FC<Props> = props => {
|
||||
);
|
||||
}
|
||||
const onDrop = (e: React.DragEvent) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const creatingComponent = e.dataTransfer?.getData('component') || '';
|
||||
|
||||
eventBus.send(
|
||||
@ -56,12 +59,21 @@ export const ComponentTree: React.FC<Props> = props => {
|
||||
new CreateComponentOperation(creatingComponent, component.id, slot)
|
||||
);
|
||||
};
|
||||
|
||||
const slotName = (
|
||||
<Text color="gray.500" fontWeight="medium" onDrop={onDrop}>
|
||||
Slot: {slot}
|
||||
</Text>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box key={slot} paddingLeft="6">
|
||||
<Text color="gray.500" fontWeight="medium" onDrop={onDrop}>
|
||||
Slot: {slot}
|
||||
</Text>
|
||||
{slotContent}
|
||||
<Box key={slot} paddingLeft="5" width="full" onDrop={onDrop}>
|
||||
{/* although component can have multiple slots, but for now, most components have only one slot
|
||||
so we hide slot name to save more view area */}
|
||||
{slots.length > 1 ? slotName : null}
|
||||
<VStack spacing="2" width="full" alignItems="start">
|
||||
{slotContent}
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
@ -71,8 +83,28 @@ export const ComponentTree: React.FC<Props> = props => {
|
||||
eventBus.send('operation', new RemoveComponentOperation(component.id));
|
||||
};
|
||||
|
||||
const onDropInComponent = (e: React.DragEvent) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (slots.length === 0) return;
|
||||
|
||||
const creatingComponent = e.dataTransfer?.getData('component') || '';
|
||||
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new CreateComponentOperation(creatingComponent, component.id, 'content')
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box key={component.id} width="full">
|
||||
<VStack
|
||||
key={component.id}
|
||||
position="relative"
|
||||
spacing="2"
|
||||
width="full"
|
||||
alignItems="start"
|
||||
onDrop={onDropInComponent}
|
||||
>
|
||||
<ComponentItemView
|
||||
title={component.id}
|
||||
isSelected={component.id === selectedComponentId}
|
||||
@ -80,8 +112,11 @@ export const ComponentTree: React.FC<Props> = props => {
|
||||
onSelectComponent(component.id);
|
||||
}}
|
||||
onClickRemove={onClickRemove}
|
||||
noChevron={slots.length === 0}
|
||||
isExpanded={isExpanded}
|
||||
onToggleExpanded={() => setIsExpanded(prev => !prev)}
|
||||
/>
|
||||
{slotsEle}
|
||||
</Box>
|
||||
{isExpanded ? slotsEle : null}
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
@ -66,12 +66,13 @@ export const StructureTree: React.FC<Props> = props => {
|
||||
onSelectComponent(dummy.id);
|
||||
}}
|
||||
onClickRemove={onClickRemove}
|
||||
noChevron={true}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<VStack spacing="2" padding="4" alignItems="start">
|
||||
<VStack spacing="2" padding="5" alignItems="start">
|
||||
<Text fontSize="lg" fontWeight="bold">
|
||||
Components
|
||||
</Text>
|
||||
|
Loading…
Reference in New Issue
Block a user