Budibase is an open-source low-code platform for creating internal apps in minutes. Supports PostgreSQL, MySQL, MSSQL, MongoDB, Rest API, Docker, K8s 🚀
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.6 KiB

import { writable, get } from "svelte/store"
import { store as frontendStore } from "builderStore"
import { findComponentPath } from "builderStore/storeUtils"
export const DropEffect = {
MOVE: "move",
COPY: "copy",
}
export const DropPosition = {
ABOVE: "above",
BELOW: "below",
INSIDE: "inside",
}
export default function() {
const store = writable({})
store.actions = {
dragstart: component => {
store.update(state => {
state.dragged = component
return state
})
},
dragover: ({
component,
index,
canHaveChildrenButIsEmpty,
mousePosition,
}) => {
store.update(state => {
state.targetComponent = component
// only allow dropping inside when container is empty
// if container has children, drag over them
if (canHaveChildrenButIsEmpty && index === 0) {
// hovered above center of target
if (mousePosition < 0.4) {
state.dropPosition = DropPosition.ABOVE
}
// hovered around bottom of target
if (mousePosition > 0.8) {
state.dropPosition = DropPosition.BELOW
}
// hovered in center of target
if (mousePosition > 0.4 && mousePosition < 0.8) {
state.dropPosition = DropPosition.INSIDE
}
return state
}
// bottom half
if (mousePosition > 0.5) {
state.dropPosition = DropPosition.BELOW
} else {
state.dropPosition = canHaveChildrenButIsEmpty
? DropPosition.INSIDE
: DropPosition.ABOVE
}
return state
})
},
reset: () => {
store.update(state => {
state.dropPosition = ""
state.targetComponent = null
state.dragged = null
return state
})
},
drop: () => {
const state = get(store)
// Stop if the target and source are the same
if (state.targetComponent === state.dragged) {
return
}
// Stop if the target or source are null
if (!state.targetComponent || !state.dragged) {
return
}
// Stop if the target is a child of source
const path = findComponentPath(state.dragged, state.targetComponent._id)
const ids = path.map(component => component._id)
if (ids.includes(state.targetComponent._id)) {
return
}
// Cut and paste the component
frontendStore.actions.components.copy(state.dragged, true)
frontendStore.actions.components.paste(
state.targetComponent,
state.dropPosition
)
store.actions.reset()
},
}
return store
}