Skip to content

Commit 0b93a46

Browse files
authored
Add parent inspector and hover through inspector (#51)
* Add parent inspector and hover through inspector * Update element layout * Update icons
1 parent 0e1d6f4 commit 0b93a46

File tree

12 files changed

+222
-74
lines changed

12 files changed

+222
-74
lines changed

src/components/inspector/ActionButton.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ interface Props
1111
icon: IconButtonProps['icon']
1212
as?: IconButtonProps['as']
1313
label: string
14-
onClick?: () => void
14+
onClick?: IconButtonProps['onClick']
15+
variantColor?: IconButtonProps['variantColor']
1516
}
1617

1718
const ActionButton: React.FC<Props> = ({
1819
icon,
1920
as,
2021
label,
2122
onClick,
23+
variantColor,
2224
...props
2325
}) => {
2426
return (
@@ -30,6 +32,7 @@ const ActionButton: React.FC<Props> = ({
3032
onClick={onClick}
3133
icon={icon}
3234
aria-label={label}
35+
variantColor={variantColor}
3336
/>
3437
</Tooltip>
3538
)

src/components/inspector/ChildrenInspector.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react'
22
import { useSelector } from 'react-redux'
33
import { getSelectedComponentChildren } from '../../core/selectors/components'
4-
import ChildrenList from './children/ChildrenList'
4+
import ElementsList from './elements-list/ElementsList'
55
import useDispatch from '../../hooks/useDispatch'
66

77
const ChildrenInspector = () => {
@@ -19,11 +19,21 @@ const ChildrenInspector = () => {
1919
dispatch.components.select(id)
2020
}
2121

22+
const onHoverChild = (id: IComponent['id']) => {
23+
dispatch.components.hover(id)
24+
}
25+
26+
const onUnhoverChild = () => {
27+
dispatch.components.unhover()
28+
}
29+
2230
return (
23-
<ChildrenList
24-
childrenList={childrenComponent}
31+
<ElementsList
32+
elements={childrenComponent}
2533
moveItem={moveChildren}
2634
onSelect={onSelectChild}
35+
onHover={onHoverChild}
36+
onUnhover={onUnhoverChild}
2737
/>
2838
)
2939
}

src/components/inspector/Inspector.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const Inspector = () => {
1919
const { type, rootParentType, id, children } = component
2020

2121
const isRoot = id === 'root'
22+
const parentIsRoot = component.parent === 'root'
2223

2324
const docType = rootParentType || type
2425
const componentHasChildren = children.length > 0
@@ -88,7 +89,11 @@ const Inspector = () => {
8889
<Panels component={component} isRoot={isRoot} />
8990
</Box>
9091

91-
<StylesPanel isRoot={isRoot} showChildren={componentHasChildren} />
92+
<StylesPanel
93+
isRoot={isRoot}
94+
showChildren={componentHasChildren}
95+
parentIsRoot={parentIsRoot}
96+
/>
9297
</>
9398
)
9499
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react'
2+
import { useSelector } from 'react-redux'
3+
import { getSelectedComponentParent } from '../../core/selectors/components'
4+
import ElementListItem from './elements-list/ElementListItem'
5+
import useDispatch from '../../hooks/useDispatch'
6+
7+
const ParentInspector = () => {
8+
const parentComponent = useSelector(getSelectedComponentParent)
9+
const dispatch = useDispatch()
10+
11+
const onSelect = () => {
12+
dispatch.components.select(parentComponent.id)
13+
}
14+
15+
const onHover = () => {
16+
dispatch.components.hover(parentComponent.id)
17+
}
18+
19+
const onUnhover = () => {
20+
dispatch.components.unhover()
21+
}
22+
23+
return (
24+
<ElementListItem
25+
type={parentComponent.type}
26+
onMouseOver={onHover}
27+
onMouseOut={onUnhover}
28+
onSelect={onSelect}
29+
/>
30+
)
31+
}
32+
33+
export default ParentInspector

src/components/inspector/children/ChildrenList.tsx

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React, { forwardRef } from 'react'
2+
import { Icon, PseudoBox, Text, PseudoBoxProps, Flex } from '@chakra-ui/core'
3+
import ActionButton from '../ActionButton'
4+
5+
interface Props extends Pick<IComponent, 'type'> {
6+
opacity?: number
7+
onSelect: PseudoBoxProps['onClick']
8+
onMouseOver: PseudoBoxProps['onMouseOver']
9+
onMouseOut: PseudoBoxProps['onMouseOut']
10+
draggable?: boolean
11+
}
12+
13+
const ElementListItem = forwardRef(
14+
(
15+
{ type, opacity = 1, onSelect, onMouseOut, onMouseOver, draggable }: Props,
16+
ref: React.Ref<HTMLDivElement>,
17+
) => {
18+
return (
19+
<PseudoBox
20+
boxSizing="border-box"
21+
transition="margin 200ms"
22+
my={1}
23+
rounded="md"
24+
p={1}
25+
display="flex"
26+
alignItems="center"
27+
cursor={draggable ? 'move' : undefined}
28+
opacity={opacity}
29+
ref={ref}
30+
onMouseOver={onMouseOver}
31+
onMouseOut={onMouseOut}
32+
>
33+
<Flex justify="space-between" align="center" w="100%">
34+
<Flex align="center">
35+
{draggable && <Icon fontSize="xs" mr={2} name="arrow-up-down" />}
36+
<Text letterSpacing="wide" fontSize="sm" textTransform="capitalize">
37+
{type}
38+
</Text>
39+
</Flex>
40+
<ActionButton
41+
label="Inspect"
42+
onClick={onSelect}
43+
icon="settings"
44+
variantColor="blackAlpha"
45+
/>
46+
</Flex>
47+
</PseudoBox>
48+
)
49+
},
50+
)
51+
52+
export default ElementListItem
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import React, { useRef } from 'react'
22
import { XYCoord, useDrop, DragObjectWithType, useDrag } from 'react-dnd'
3-
import { PseudoBox, Icon, Text } from '@chakra-ui/core'
3+
import ElementListItem from './ElementListItem'
44

5-
interface Props extends Pick<IComponent, 'type'> {
5+
interface Props extends Pick<IComponent, 'type' | 'id'> {
66
index: number
7-
moveItem: (dragIndex: number, hoverIndex: number) => void
8-
id: IComponent['id']
7+
moveItem?: (dragIndex: number, hoverIndex: number) => void
98
onSelect: (id: IComponent['id']) => void
9+
onHover: (id: IComponent['id']) => void
10+
onUnhover: () => void
1011
}
1112

12-
const ITEM_TYPE = 'childElement'
13+
const ITEM_TYPE = 'elementItem'
1314

14-
const ChildElement: React.FC<Props> = ({
15+
const ElementListItemDraggable: React.FC<Props> = ({
1516
type,
1617
id,
1718
onSelect,
1819
moveItem,
1920
index,
21+
onHover,
22+
onUnhover,
2023
}) => {
2124
const ref = useRef<HTMLDivElement>(null)
2225
const [, drop] = useDrop({
@@ -42,7 +45,9 @@ const ChildElement: React.FC<Props> = ({
4245
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
4346
return
4447
}
45-
moveItem(dragIndex, hoverIndex)
48+
if (moveItem) {
49+
moveItem(dragIndex, hoverIndex)
50+
}
4651
// @ts-ignore
4752
item.index = hoverIndex
4853
},
@@ -58,30 +63,25 @@ const ChildElement: React.FC<Props> = ({
5863

5964
drag(drop(ref))
6065

61-
const onSelectChild = () => {
66+
const onSelectElement = () => {
6267
onSelect(id)
6368
}
6469

70+
const onMouseOver = () => {
71+
onHover(id)
72+
}
73+
6574
return (
66-
<PseudoBox
67-
boxSizing="border-box"
68-
transition="margin 200ms"
69-
my={1}
70-
rounded="md"
71-
p={1}
72-
display="flex"
73-
alignItems="center"
74-
cursor="move"
75-
opacity={opacity}
75+
<ElementListItem
7676
ref={ref}
77-
onClick={onSelectChild}
78-
>
79-
<Icon fontSize="xs" mr={2} name="drag-handle" />
80-
<Text letterSpacing="wide" fontSize="sm" textTransform="capitalize">
81-
{type}
82-
</Text>
83-
</PseudoBox>
77+
onSelect={onSelectElement}
78+
opacity={opacity}
79+
onMouseOver={onMouseOver}
80+
onMouseOut={onUnhover}
81+
type={type}
82+
draggable
83+
/>
8484
)
8585
}
8686

87-
export default ChildElement
87+
export default ElementListItemDraggable
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from 'react'
2+
import { Box } from '@chakra-ui/core'
3+
import ElementListItem from './ElementListItemDraggable'
4+
5+
interface Props {
6+
elements: IComponent[]
7+
moveItem: (fromIndex: number, toIndex: number) => void
8+
onSelect: (id: IComponent['id']) => void
9+
onHover: (id: IComponent['id']) => void
10+
onUnhover: () => void
11+
}
12+
13+
const ElementsList: React.FC<Props> = ({
14+
elements,
15+
moveItem,
16+
onSelect,
17+
onHover,
18+
onUnhover,
19+
}) => {
20+
return (
21+
<Box mx={2} h="100%">
22+
{elements.map(
23+
(element, index) =>
24+
element && (
25+
<ElementListItem
26+
key={element.id}
27+
type={element.type}
28+
index={index}
29+
moveItem={moveItem}
30+
id={element.id}
31+
onSelect={onSelect}
32+
onHover={onHover}
33+
onUnhover={onUnhover}
34+
/>
35+
),
36+
)}
37+
</Box>
38+
)
39+
}
40+
41+
export default ElementsList

src/components/inspector/panels/StylesPanel.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,26 @@ import AccordionContainer from '../AccordionContainer'
1010
import ColorsControl from '../controls/ColorsControl'
1111
import EffectsPanel from './styles/EffectsPanel'
1212
import ChildrenInspector from '../ChildrenInspector'
13+
import ParentInspector from '../ParentInspector'
1314

1415
interface Props {
1516
isRoot: boolean
1617
showChildren: boolean
18+
parentIsRoot: boolean
1719
}
1820

19-
const StylesPanel: React.FC<Props> = ({ isRoot, showChildren }) => (
21+
const StylesPanel: React.FC<Props> = ({
22+
isRoot,
23+
showChildren,
24+
parentIsRoot,
25+
}) => (
2026
<Accordion defaultIndex={[0]} allowMultiple>
27+
{!isRoot && !parentIsRoot && (
28+
<AccordionContainer title="Parent">
29+
<ParentInspector />
30+
</AccordionContainer>
31+
)}
32+
2133
{showChildren && (
2234
<AccordionContainer title="Children">
2335
<ChildrenInspector />

src/core/models/components.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { duplicateComponent, deleteComponent } from '../../utils/recursive'
77
export type ComponentsState = {
88
components: IComponents
99
selectedId: IComponent['id']
10+
hoveredId?: IComponent['id']
1011
}
1112
export type ComponentsStateWithUndo = {
1213
past: ComponentsState[]
@@ -269,6 +270,21 @@ const components = createModel({
269270
}
270271
return state
271272
},
273+
hover(
274+
state: ComponentsState,
275+
componentId: IComponent['id'],
276+
): ComponentsState {
277+
return {
278+
...state,
279+
hoveredId: componentId,
280+
}
281+
},
282+
unhover(state: ComponentsState): ComponentsState {
283+
return {
284+
...state,
285+
hoveredId: undefined,
286+
}
287+
},
272288
},
273289
})
274290

0 commit comments

Comments
 (0)