parent
85b63b9268
commit
c13301fda9
@ -0,0 +1,59 @@ |
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import React, { useEffect, useRef } from 'react' |
||||
import { FileType } from '../types' |
||||
|
||||
export interface FileLabelProps { |
||||
file: FileType, |
||||
focusEdit: { |
||||
element: string |
||||
type: string |
||||
isNew: boolean |
||||
lastEdit: string |
||||
} |
||||
editModeOff: (content: string) => void |
||||
} |
||||
|
||||
export const FileLabel = (props: FileLabelProps) => { |
||||
const { file, focusEdit, editModeOff } = props |
||||
const isEditable = focusEdit.element === file.path |
||||
const labelRef = useRef(null) |
||||
|
||||
useEffect(() => { |
||||
if (isEditable) { |
||||
setTimeout(() => { |
||||
labelRef.current.focus() |
||||
}, 0) |
||||
} |
||||
}, [isEditable]) |
||||
|
||||
const handleEditInput = (event: React.KeyboardEvent<HTMLDivElement>) => { |
||||
if (event.which === 13) { |
||||
event.preventDefault() |
||||
editModeOff(labelRef.current.innerText) |
||||
} |
||||
} |
||||
|
||||
const handleEditBlur = (event: React.SyntheticEvent) => { |
||||
event.stopPropagation() |
||||
editModeOff(labelRef.current.innerText) |
||||
} |
||||
|
||||
return ( |
||||
<div |
||||
className='remixui_items d-inline-block w-100' |
||||
ref={labelRef} |
||||
suppressContentEditableWarning={true} |
||||
contentEditable={isEditable} |
||||
onKeyDown={handleEditInput} |
||||
onBlur={handleEditBlur} |
||||
> |
||||
<span |
||||
title={file.path} |
||||
className={'remixui_label ' + (file.isDirectory ? 'folder' : 'remixui_leaf')} |
||||
data-path={file.path} |
||||
> |
||||
{ file.name } |
||||
</span> |
||||
</div> |
||||
) |
||||
} |
@ -0,0 +1,116 @@ |
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import React, { SyntheticEvent, useState } from 'react' |
||||
import { FileType } from '../types' |
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { TreeView, TreeViewItem } from '@remix-ui/tree-view' |
||||
import { getPathIcon } from '@remix-ui/helper' |
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { FileLabel } from './file-label' |
||||
|
||||
export interface RenderFileProps { |
||||
file: FileType, |
||||
index: number, |
||||
focusEdit: { element: string, type: string, isNew: boolean, lastEdit: string }, |
||||
focusElement: { key: string, type: 'file' | 'folder' | 'gist' }[], |
||||
focusContext: { element: string, x: number, y: number, type: string }, |
||||
ctrlKey: boolean, |
||||
expandPath: string[], |
||||
editModeOff: (content: string) => void, |
||||
handleClickFolder: (path: string, type: string) => void, |
||||
handleClickFile: (path: string, type: string) => void, |
||||
handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void |
||||
} |
||||
|
||||
export const FileRender = (props: RenderFileProps) => { |
||||
const { file } = props |
||||
|
||||
if (!file || !file.path || typeof file === 'string' || typeof file === 'number' || typeof file === 'boolean') return |
||||
const [hover, setHover] = useState<boolean>(false) |
||||
const labelClass = props.focusEdit.element === file.path |
||||
? 'bg-light' : props.focusElement.findIndex(item => item.key === file.path) !== -1 |
||||
? 'bg-secondary' : hover |
||||
? 'bg-light border' : (props.focusContext.element === file.path) && (props.focusEdit.element !== file.path) |
||||
? 'bg-light border' : '' |
||||
const icon = getPathIcon(file.path) |
||||
const spreadProps = { |
||||
onClick: (e) => e.stopPropagation() |
||||
} |
||||
|
||||
const handleFolderClick = (event: SyntheticEvent) => { |
||||
event.stopPropagation() |
||||
if (props.focusEdit.element !== file.path) props.handleClickFolder(file.path, file.type) |
||||
} |
||||
|
||||
const handleFileClick = (event: SyntheticEvent) => { |
||||
event.stopPropagation() |
||||
if (props.focusEdit.element !== file.path) props.handleClickFile(file.path, file.type) |
||||
} |
||||
|
||||
const handleContextMenu = (event: PointerEvent) => { |
||||
event.preventDefault() |
||||
event.stopPropagation() |
||||
props.handleContextMenu(event.pageX, event.pageY, file.path, (event.target as HTMLElement).textContent, file.type) |
||||
} |
||||
|
||||
const handleMouseOut = (event: SyntheticEvent) => { |
||||
event.stopPropagation() |
||||
setHover(false) |
||||
} |
||||
|
||||
const handleMouseOver = (event: SyntheticEvent) => { |
||||
event.stopPropagation() |
||||
setHover(true) |
||||
} |
||||
|
||||
if (file.isDirectory) { |
||||
return ( |
||||
<TreeViewItem |
||||
id={`treeViewItem${file.path}`} |
||||
iconX='pr-3 fa fa-folder' |
||||
iconY='pr-3 fa fa-folder-open' |
||||
key={`${file.path + props.index}`} |
||||
label={<FileLabel file={file} focusEdit={props.focusEdit} editModeOff={props.editModeOff} />} |
||||
onClick={handleFolderClick} |
||||
onContextMenu={handleContextMenu} |
||||
labelClass={labelClass} |
||||
controlBehaviour={ props.ctrlKey } |
||||
expand={props.expandPath.includes(file.path)} |
||||
onMouseOver={handleMouseOver} |
||||
onMouseOut={handleMouseOut} |
||||
> |
||||
{ |
||||
file.child ? <TreeView id={`treeView${file.path}`} key={`treeView${file.path}`} {...spreadProps }>{ |
||||
Object.keys(file.child).map((key, index) => <FileRender |
||||
file={file.child[key]} |
||||
index={index} |
||||
focusContext={props.focusContext} |
||||
focusEdit={props.focusEdit} |
||||
focusElement={props.focusElement} |
||||
ctrlKey={props.ctrlKey} |
||||
editModeOff={props.editModeOff} |
||||
handleClickFile={props.handleClickFile} |
||||
handleClickFolder={props.handleClickFolder} |
||||
handleContextMenu={props.handleContextMenu} |
||||
expandPath={props.expandPath} |
||||
/>) |
||||
} |
||||
</TreeView> : <TreeView id={`treeView${file.path}`} key={`treeView${file.path}`} {...spreadProps }/> |
||||
} |
||||
</TreeViewItem> |
||||
) |
||||
} else { |
||||
return ( |
||||
<TreeViewItem |
||||
id={`treeViewItem${file.path}`} |
||||
key={`treeView${file.path}`} |
||||
label={<FileLabel file={file} focusEdit={props.focusEdit} editModeOff={props.editModeOff} />} |
||||
onClick={handleFileClick} |
||||
onContextMenu={handleContextMenu} |
||||
icon={icon} |
||||
labelClass={labelClass} |
||||
onMouseOver={handleMouseOver} |
||||
onMouseOut={handleMouseOut} |
||||
/> |
||||
) |
||||
} |
||||
} |
@ -1,61 +0,0 @@ |
||||
.remixui_container { |
||||
display : flex; |
||||
flex-direction : row; |
||||
width : 100%; |
||||
height : 100%; |
||||
box-sizing : border-box; |
||||
} |
||||
.remixui_fileexplorer { |
||||
display : flex; |
||||
flex-direction : column; |
||||
position : relative; |
||||
width : 100%; |
||||
padding-left : 6px; |
||||
padding-right : 6px; |
||||
padding-top : 6px; |
||||
} |
||||
.remixui_fileExplorerTree { |
||||
cursor : default; |
||||
} |
||||
.remixui_gist { |
||||
padding : 10px; |
||||
} |
||||
.remixui_gist i { |
||||
cursor : pointer; |
||||
} |
||||
.remixui_gist i:hover { |
||||
color : orange; |
||||
} |
||||
.remixui_connectToLocalhost { |
||||
padding : 10px; |
||||
} |
||||
.remixui_connectToLocalhost i { |
||||
cursor : pointer; |
||||
} |
||||
.remixui_connectToLocalhost i:hover { |
||||
color : var(--secondary) |
||||
} |
||||
.remixui_uploadFile { |
||||
padding : 10px; |
||||
} |
||||
.remixui_uploadFile label:hover { |
||||
color : var(--secondary) |
||||
} |
||||
.remixui_uploadFile label { |
||||
cursor : pointer; |
||||
} |
||||
.remixui_treeview { |
||||
overflow-y : auto; |
||||
} |
||||
.remixui_dialog { |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
.remixui_dialogParagraph { |
||||
margin-bottom: 2em; |
||||
word-break: break-word; |
||||
} |
||||
.remixui_menuicon { |
||||
padding-right : 10px; |
||||
} |
||||
|
Loading…
Reference in new issue