Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve multi select drag and drop implementation #4999

Merged
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { SyntheticEvent, useContext, useEffect, useRef, useState } from 'react'
import { DragStructure, FileType, FlatTreeDropProps } from '../types'
import { buildMultiSelectedItemProfiles, getEventTarget } from '../utils/getEventTarget'
import { getEventTarget } from '../utils/getEventTarget'
import { extractParentFromKey } from '@remix-ui/helper'
import { FileSystemContext } from '../contexts'

Expand Down
38 changes: 34 additions & 4 deletions libs/remix-ui/workspace/src/lib/components/flat-tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getPathIcon } from '@remix-ui/helper';
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso'
import { FlatTreeItemInput } from './flat-tree-item-input';
import { FlatTreeDrop } from './flat-tree-drop';
import { buildMultiSelectedItemProfiles, getEventTarget } from '../utils/getEventTarget';
import { getEventTarget } from '../utils/getEventTarget';
import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators';
import { FileHoverIcons } from './file-explorer-hovericons';
import { deletePath } from '../actions';
Expand Down Expand Up @@ -75,6 +75,37 @@ export const FlatTree = (props: FlatTreeProps) => {
const virtuoso = useRef<VirtuosoHandle>(null)
const [selectedItems, setSelectedItems] = useState<DragStructure[]>([])

/**
* When multiple files are selected in FileExplorer,
* and these files are dragged to a target folder,
* this function will build the profile of each selected item
* so they can be moved when dropped on target folder
* @param target - Initial target item in FileExplorer
* @returns - {DragStructure} Array of selected items
*/
const buildMultiSelectedItemProfiles = (target: {
path: string
type: string
content: string
position: {
top: number
left: number
}
}) => {
const selectItems = []
selectItems.push(target)
containerRef.current?.querySelectorAll('li.remixui_selected').forEach(item => {
const dragTarget = {
position: { top: target?.position.top || 0, left: target?.position.left || 0 },
path: item.getAttribute('data-path') || item.getAttribute('data-label-path') || '',
type: item.getAttribute('data-type') || item.getAttribute('data-label-type') || '',
content: item.textContent || ''
}
if (dragTarget.path !== target.path) selectItems.push(dragTarget)
})
setSelectedItems(selectItems)
}

const labelClass = (file: FileType) =>
props.focusEdit.element === file.path
? 'bg-light'
Expand Down Expand Up @@ -116,9 +147,8 @@ export const FlatTree = (props: FlatTreeProps) => {
const target = await getEventTarget(event)
setDragSource(flatTree.find((item) => item.path === target.path))
setIsDragging(true)
const items = buildMultiSelectedItemProfiles(target)
setSelectedItems(items)
setFilesSelected(items.map((item) => item.path))
buildMultiSelectedItemProfiles(target)
setFilesSelected(selectedItems.map((item) => item.path))
}

useEffect(() => {
Expand Down
31 changes: 0 additions & 31 deletions libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,3 @@ export const getEventTarget = async (e: any, useLabel: boolean = false) => {
}
}
}

/**
* When multiple files are selected in FileExplorer,
* and these files are dragged to a target folder,
* this function will build the profile of each selected item
* in FileExplorer so they can be moved when dropped
* @param target - Initial target item in FileExplorer
* @returns - {DragStructure} Array of selected items
*/
export const buildMultiSelectedItemProfiles = (target: {
path: string
type: string
content: string
position: {
top: number
left: number
}
}) => {
const selectItems = []
selectItems.push(target)
document.querySelectorAll('li.remixui_selected').forEach(item => {
const dragTarget = {
position: { top: target?.position.top || 0, left: target?.position.left || 0 },
path: item.getAttribute('data-path') || item.getAttribute('data-label-path') || '',
type: item.getAttribute('data-type') || item.getAttribute('data-label-type') || '',
content: item.textContent || ''
}
if (dragTarget.path !== target.path) selectItems.push(dragTarget)
})
return selectItems
}
Loading