Add initial work on component drag and drop refactor

This commit is contained in:
Andrew Kingston 2022-05-19 19:14:12 +01:00
parent f91c8f43fd
commit 050f4900b3
3 changed files with 47 additions and 46 deletions

View File

@ -138,6 +138,7 @@
overflow: hidden; overflow: hidden;
position: relative; position: relative;
padding-left: var(--spacing-l); padding-left: var(--spacing-l);
pointer-events: none;
} }
/* Needed to fully display the actions icon */ /* Needed to fully display the actions icon */

View File

@ -19,6 +19,7 @@
export let dragDropStore export let dragDropStore
let closedNodes = {} let closedNodes = {}
let indicatorY = 0
const dragstart = component => e => { const dragstart = component => e => {
e.dataTransfer.dropEffect = DropEffect.MOVE e.dataTransfer.dropEffect = DropEffect.MOVE
@ -29,18 +30,19 @@
const definition = store.actions.components.getDefinition( const definition = store.actions.components.getDefinition(
component._component component._component
) )
const canHaveChildrenButIsEmpty = const canHaveChildren = definition?.hasChildren
definition?.hasChildren && !component._children?.length
e.dataTransfer.dropEffect = DropEffect.COPY e.dataTransfer.dropEffect = DropEffect.COPY
// how far down the mouse pointer is on the drop target // how far down the mouse pointer is on the drop target
const mousePosition = e.offsetY / e.currentTarget.offsetHeight const mousePosition = e.offsetY / e.currentTarget.offsetHeight
indicatorY = e.currentTarget.offsetTop
dragDropStore.actions.dragover({ dragDropStore.actions.dragover({
component, component,
index, index,
canHaveChildrenButIsEmpty, canHaveChildren,
mousePosition, mousePosition,
}) })
@ -62,9 +64,13 @@
return def?.icon return def?.icon
} }
const componentHasChildren = component => { const componentSupportsChildren = component => {
const def = store.actions.components.getDefinition(component?._component) const def = store.actions.components.getDefinition(component?._component)
return def?.hasChildren && component._children?.length return def?.hasChildren
}
const componentHasChildren = component => {
return componentSupportsChildren(component) && component._children?.length
} }
function toggleNodeOpen(componentId) { function toggleNodeOpen(componentId) {
@ -111,13 +117,17 @@
$store.selectedComponentId = component._id $store.selectedComponentId = component._id
}} }}
> >
{#if $dragDropStore?.targetComponent === component && $dragDropStore.dropPosition === DropPosition.ABOVE} {#if dragDropStore && $dragDropStore?.targetComponent === component}
<div <div
class:above={$dragDropStore.dropPosition === DropPosition.ABOVE}
class:below={$dragDropStore.dropPosition === DropPosition.BELOW}
class:inside={$dragDropStore.dropPosition === DropPosition.INSIDE}
on:drop={onDrop} on:drop={onDrop}
ondragover="return false" ondragover="return false"
ondragenter="return false" ondragenter="return false"
class="drop-item" class="drop-item"
style="margin-left: {(level + 1) * 16}px" style="--indicatorX: {(level + 2) *
14}px; --indicatorY:{indicatorY}px;"
/> />
{/if} {/if}
@ -148,18 +158,6 @@
level={level + 1} level={level + 1}
/> />
{/if} {/if}
{#if $dragDropStore?.targetComponent === component && ($dragDropStore.dropPosition === DropPosition.INSIDE || $dragDropStore.dropPosition === DropPosition.BELOW)}
<div
on:drop={onDrop}
ondragover="return false"
ondragenter="return false"
class="drop-item"
style="margin-left: {(level +
($dragDropStore.dropPosition === DropPosition.INSIDE ? 3 : 1)) *
16}px"
/>
{/if}
</li> </li>
{/each} {/each}
</ul> </ul>
@ -183,8 +181,25 @@
} }
.drop-item { .drop-item {
border-radius: var(--border-radius-m); height: 2px;
background: green;
z-index: 999;
position: absolute;
top: calc(var(--indicatorY) - 1px);
left: var(--indicatorX);
width: 100px;
}
.drop-item.above {
background: red;
}
.drop-item.below {
background: blue;
margin-top: 32px;
}
.drop-item.inside {
background: transparent;
border: 2px solid green;
height: 32px; height: 32px;
background: var(--grey-3); pointer-events: none;
} }
</style> </style>

View File

@ -23,44 +23,29 @@ export default function () {
return state return state
}) })
}, },
dragover: ({ dragover: ({ component, canHaveChildren, mousePosition }) => {
component,
index,
canHaveChildrenButIsEmpty,
mousePosition,
}) => {
store.update(state => { store.update(state => {
state.targetComponent = component state.targetComponent = component
// only allow dropping inside when container is empty // only allow dropping inside when container is empty
// if container has children, drag over them // if container has children, drag over them
if (canHaveChildrenButIsEmpty && index === 0) { if (canHaveChildren) {
// hovered above center of target if (mousePosition <= 0.33) {
if (mousePosition < 0.4) { // hovered above center of target
state.dropPosition = DropPosition.ABOVE state.dropPosition = DropPosition.ABOVE
} } else if (mousePosition >= 0.66) {
// hovered around bottom of target
// hovered around bottom of target
if (mousePosition > 0.8) {
state.dropPosition = DropPosition.BELOW state.dropPosition = DropPosition.BELOW
} } else {
// hovered in center of target
// hovered in center of target
if (mousePosition > 0.4 && mousePosition < 0.8) {
state.dropPosition = DropPosition.INSIDE state.dropPosition = DropPosition.INSIDE
} }
return state return state
} }
// bottom half // bottom half
if (mousePosition > 0.5) { state.dropPosition =
state.dropPosition = DropPosition.BELOW mousePosition > 0.5 ? DropPosition.BELOW : DropPosition.ABOVE
} else {
state.dropPosition = canHaveChildrenButIsEmpty
? DropPosition.INSIDE
: DropPosition.ABOVE
}
return state return state
}) })
}, },