Add initial work on component drag and drop refactor
This commit is contained in:
parent
f91c8f43fd
commit
050f4900b3
|
@ -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 */
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue