remix-project mirror
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.
 
 
 
 
 
remix-project/libs/remix-ui/drag-n-drop/src/lib/drag-n-drop.tsx

120 lines
3.2 KiB

import { extractParentFromKey } from '@remix-ui/helper'
import React, { useContext, useRef, useState } from 'react'
import { MoveContext } from './context/moveContext'
import { DraggableType, DragType } from './types'
export const Drag = (props: DragType) => {
const [dragged, setDragged] = useState<{path: string; isDirectory: boolean}>({} as {path: string; isDirectory: boolean})
return (
<MoveContext.Provider
value={{
dragged: dragged,
moveFile: props.onFileMoved,
moveFolder: props.onFolderMoved,
currentlyMoved: (path) => {
setDragged(() => path)
},
dragStatus: props.dragStatus
}}
>
{props.children}
</MoveContext.Provider>
)
}
export const Draggable = (props: DraggableType) => {
const dragRef = useRef<HTMLSpanElement>(null),
destination = props.file,
context = useContext(MoveContext)
// delay timer
const [timer, setTimer] = useState<NodeJS.Timeout>()
// folder to open
const [folderToOpen, setFolderToOpen] = useState<string>()
const handleDrop = (event: React.DragEvent<HTMLSpanElement>) => {
event.preventDefault()
if (destination.isDirectory) {
if (context.dragged.isDirectory) {
context.moveFolder(destination.path, context.dragged.path)
} else {
context.moveFile(destination.path, context.dragged.path)
}
} else {
const path = extractParentFromKey(destination.path) || '/'
if (context.dragged.isDirectory) {
context.moveFolder(path, context.dragged.path)
} else {
context.moveFile(path, context.dragged.path)
}
}
}
const handleDragover = (event: React.DragEvent<HTMLSpanElement>) => {
//Checks if the folder is opened
event.preventDefault()
if (destination.isDirectory && !props.expandedPath.includes(destination.path) && folderToOpen !== destination.path && props.handleClickFolder) {
setFolderToOpen(destination.path)
timer && clearTimeout(timer)
setTimer(
setTimeout(() => {
props.handleClickFolder(destination.path, destination.type)
setFolderToOpen(null)
}, 600)
)
}
}
const handleDrag = () => {
context.dragStatus(true)
if (context.dragged.path !== destination.path) {
context.currentlyMoved({
path: destination.path,
isDirectory: destination.isDirectory
})
}
}
const handleDragEnd = () => {
context.dragStatus(false)
}
return (
<>
{props.isDraggable ? (
props.children
) : (
<span
ref={dragRef}
draggable
onDrop={(event) => {
handleDrop(event)
}}
onDragStart={(event) => {
if (destination && destination.path === '/'){
event.preventDefault()
event.stopPropagation
} else
if (destination) {
handleDrag()
}
}}
onDragEnd={(event) => {
handleDragEnd()
}}
onDragOver={(event) => {
if (destination) {
handleDragover(event)
}
}}
>
{props.children}
</span>
)}
</>
)
}