From 5e38ec104c5c0e7e5f685abe1b07ed610afa81ca Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 17:28:41 +0200 Subject: [PATCH 01/10] multi select plus multi delete --- .../src/lib/file-explorer-context-menu.tsx | 48 +++++++-- .../file-explorer/src/lib/file-explorer.tsx | 101 +++++++++++++----- .../file-explorer/src/lib/types/index.ts | 9 +- .../src/lib/tree-view-item/tree-view-item.tsx | 2 +- package.json | 1 - 5 files changed, 119 insertions(+), 42 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index 3e6b308a35..2263889191 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -1,12 +1,11 @@ import React, { useRef, useEffect } from 'react' // eslint-disable-line -import { FileExplorerContextMenuProps } from './types' +import { action, FileExplorerContextMenuProps } from './types' import './css/file-explorer-context-menu.css' export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => { - const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, publishToGist, runScript, emit, pageX, pageY, path, type, ...otherProps } = props + const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, publishToGist, runScript, emit, pageX, pageY, path, type, focus, ...otherProps } = props const contextMenuRef = useRef(null) - useEffect(() => { contextMenuRef.current.focus() }, []) @@ -22,13 +21,42 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => } }, [pageX, pageY]) + const filterItem = (item: action) => { + /** + * if there are multiple elements focused we need to take this and all conditions must be met plus the action must be set to 'multi' + * for example : 'downloadAsZip' with type ['file','folder','multi'] will work on files and folders when multiple are selected + **/ + const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + if (nonRootFocus.length > 1) { + for (const element of nonRootFocus) { + if (!itemMatchesCondition(item, element.type, element.key)) return false + } + return (item.type.includes('multi')) + } else { + return itemMatchesCondition(item, type, path) + } + } + + const itemMatchesCondition = (item: action, itemType: string, itemPath: string) => { + if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === itemType) !== -1)) return true + else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === itemPath) !== -1)) return true + else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => itemPath.endsWith(ext)) !== -1)) return true + else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => itemPath.match(new RegExp(value))).length > 0)) return true + else return false + } + + const getPath = () => { + const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + if (nonRootFocus.length > 1) { + return nonRootFocus.map((element) => { return element.key }) + } else { + return path + } + } + const menu = () => { return actions.filter(item => { - if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === type) !== -1)) return true - else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === path) !== -1)) return true - else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => path.endsWith(ext)) !== -1)) return true - else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => path.match(new RegExp(value))).length > 0)) return true - else return false + return filterItem(item) }).map((item, index) => { return
  • renamePath(path, type) break case 'Delete': - deletePath(path) + deletePath(getPath()) break case 'Push changes to gist': publishToGist() @@ -56,7 +84,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => runScript(path) break default: - emit && emit(item.id, path) + emit && emit(item.id, getPath()) break } hideContextMenu() diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index fc8c89450a..8282855d76 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -19,10 +19,7 @@ const queryParams = new QueryParams() export const FileExplorer = (props: FileExplorerProps) => { const { name, registry, plugin, focusRoot, contextMenuItems, displayInput, externalUploads } = props const [state, setState] = useState({ - focusElement: [{ - key: '', - type: 'folder' - }], + focusElement: [{ key: '', type: 'folder' }], focusPath: null, files: [], fileManager: null, @@ -52,7 +49,7 @@ export const FileExplorer = (props: FileExplorerProps) => { }, { id: 'delete', name: 'Delete', - type: ['file', 'folder'], + type: ['file', 'folder', 'multi'], path: [], extension: [], pattern: [] @@ -70,6 +67,13 @@ export const FileExplorer = (props: FileExplorerProps) => { path: [], extension: ['.js'], pattern: [] + }, { + id: 'test', + name: 'test', + type: ['file', 'folder', 'multi'], + path: [], + extension: [], + pattern: [] }], focusContext: { element: null, @@ -88,6 +92,7 @@ export const FileExplorer = (props: FileExplorerProps) => { hide: true, title: '', message: '', + children: <>, ok: { label: '', fn: () => {} @@ -203,7 +208,8 @@ export const FileExplorer = (props: FileExplorerProps) => { message: prevState.modals[0].message, ok: prevState.modals[0].ok, cancel: prevState.modals[0].cancel, - handleHide: prevState.modals[0].handleHide + handleHide: prevState.modals[0].handleHide, + children: prevState.modals[0].children } prevState.modals.shift() @@ -216,6 +222,31 @@ export const FileExplorer = (props: FileExplorerProps) => { } }, [state.modals]) + useEffect(() => { + const keyPressHandler = (e: KeyboardEvent) => { + if (e.key === 'Shift') { + setState(prevState => { + return { ...prevState, ctrlKey: true } + }) + } + } + + const keyUpHandler = (e: KeyboardEvent) => { + if (e.key === 'Shift') { + setState(prevState => { + return { ...prevState, ctrlKey: false } + }) + } + } + + document.addEventListener('keydown', keyPressHandler) + document.addEventListener('keyup', keyUpHandler) + return () => { + document.removeEventListener('keydown', keyPressHandler) + document.removeEventListener('keyup', keyUpHandler) + } + }, []) + const extractNameFromKey = (key: string):string => { const keyPath = key.split('/') @@ -280,29 +311,32 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const deletePath = async (path: string) => { + const deletePath = async (path: string | string[]) => { const filesProvider = fileSystem.provider.provider - - if (filesProvider.isReadOnly(path)) { - return toast('cannot delete file. ' + name + ' is a read only explorer') + if (!Array.isArray(path)) path = [path] + const children: React.ReactFragment =
    Are you sure you want to delete {path.length > 1 ? 'these items' : 'this item'}?
    {path.map((item, i) => (
  • {item}
  • ))} + for (const p of path) { + if (filesProvider.isReadOnly(p)) { + return toast('cannot delete file. ' + name + ' is a read only explorer') + } } - const isDir = state.fileManager.isDirectory(path) - - modal(`Delete ${isDir ? 'folder' : 'file'}`, `Are you sure you want to delete ${path} ${isDir ? 'folder' : 'file'}?`, { + modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, '', { label: 'OK', fn: async () => { - try { - const fileManager = state.fileManager - - await fileManager.remove(path) - } catch (e) { - toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${path}.`) + const fileManager = state.fileManager + for (const p of path) { + try { + await fileManager.remove(p) + } catch (e) { + const isDir = state.fileManager.isDirectory(p) + toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${p}.`) + } } } }, { label: 'Cancel', fn: () => {} - }) + }, children) } const renamePath = async (oldPath: string, newPath: string) => { @@ -526,7 +560,7 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const emitContextMenuEvent = (id: string, path: string) => { + const emitContextMenuEvent = (id: string, path: string | string[]) => { plugin.emit(id, path) } @@ -536,13 +570,14 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const modal = (title: string, message: string, ok: { label: string, fn: () => void }, cancel: { label: string, fn: () => void }) => { + const modal = (title: string, message: string, ok: { label: string, fn: () => void }, cancel: { label: string, fn: () => void }, children?:React.ReactNode) => { setState(prevState => { return { ...prevState, modals: [...prevState.modals, { message, + children, title, ok, cancel, @@ -560,10 +595,22 @@ export const FileExplorer = (props: FileExplorerProps) => { const handleClickFile = (path: string) => { path = path.indexOf(props.name + '/') === 0 ? path.replace(props.name + '/', '') : path - state.fileManager.open(path) - setState(prevState => { - return { ...prevState, focusElement: [{ key: path, type: 'file' }] } - }) + if (!state.ctrlKey) { + state.fileManager.open(path) + setState(prevState => { + return { ...prevState, focusElement: [{ key: path, type: 'file' }] } + }) + } else { + if (state.focusElement.findIndex(item => item.key === path) !== -1) { + setState(prevState => { + return { ...prevState, focusElement: [...prevState.focusElement.filter(item => item.key !== path)] } + }) + } else { + setState(prevState => { + return { ...prevState, focusElement: [...prevState.focusElement, { key: path, type: 'file' }] } + }) + } + } } const handleClickFolder = async (path: string) => { @@ -864,6 +911,7 @@ export const FileExplorer = (props: FileExplorerProps) => { id={ props.name } title={ state.focusModal.title } message={ state.focusModal.message } + children={ state.focusModal.children } hide={ state.focusModal.hide } ok={ state.focusModal.ok } cancel={ state.focusModal.cancel } @@ -885,6 +933,7 @@ export const FileExplorer = (props: FileExplorerProps) => { pageY={state.focusContext.y} path={state.focusContext.element} type={state.focusContext.type} + focus={state.focusElement} onMouseOver={(e) => { e.stopPropagation() handleMouseOver(state.focusContext.element) diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 17d6975414..6f6dadc44a 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -27,20 +27,21 @@ export interface FileExplorerMenuProps { publishToGist: () => void, uploadFile: (target: EventTarget & HTMLInputElement) => void } - +export type action = { name: string, type: string[], path: string[], extension: string[], pattern: string[], id: string } export interface FileExplorerContextMenuProps { - actions: { name: string, type: string[], path: string[], extension: string[], pattern: string[], id: string }[], + actions: action[], createNewFile: (folder?: string) => void, createNewFolder: (parentFolder?: string) => void, - deletePath: (path: string) => void, + deletePath: (path: string | string[]) => void, renamePath: (path: string, type: string) => void, hideContextMenu: () => void, publishToGist?: () => void, runScript?: (path: string) => void, - emit?: (id: string, path: string) => void, + emit?: (id: string, path: string | string[]) => void, pageX: number, pageY: number, path: string, type: string, + focus: {key:string, type:string}[] onMouseOver?: (...args) => void } diff --git a/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx b/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx index 6f7028f4cb..c570de5f07 100644 --- a/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx +++ b/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx @@ -14,7 +14,7 @@ export const TreeViewItem = (props: TreeViewItemProps) => { return (
  • !controlBehaviour && setIsExpanded(!isExpanded)}> - { controlBehaviour ? null : children ?
    : icon ?
    : null } + { children ?
    : icon ?
    : null } { label } diff --git a/package.json b/package.json index 0e3b262c5e..6302cb48fd 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,6 @@ "isbinaryfile": "^3.0.2", "jquery": "^3.3.1", "jszip": "^3.6.0", - "lodash": "^4.17.21", "latest-version": "^5.1.0", "lodash": "^4.17.21", "merge": "^1.2.0", From 9080409a0ed7c348f989ebb4a9071bcbd5cad2fb Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 17:31:59 +0200 Subject: [PATCH 02/10] rm test --- libs/remix-ui/file-explorer/src/lib/file-explorer.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 8282855d76..2358fd49c9 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -67,13 +67,6 @@ export const FileExplorer = (props: FileExplorerProps) => { path: [], extension: ['.js'], pattern: [] - }, { - id: 'test', - name: 'test', - type: ['file', 'folder', 'multi'], - path: [], - extension: [], - pattern: [] }], focusContext: { element: null, From 7ef49ca8fcce96b2010e54c55d9a5db5f33ee14d Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 17:42:26 +0200 Subject: [PATCH 03/10] use shiftkey --- libs/remix-ui/file-explorer/src/lib/file-explorer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 2358fd49c9..e911dbf2a4 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -217,7 +217,7 @@ export const FileExplorer = (props: FileExplorerProps) => { useEffect(() => { const keyPressHandler = (e: KeyboardEvent) => { - if (e.key === 'Shift') { + if (e.shiftKey) { setState(prevState => { return { ...prevState, ctrlKey: true } }) @@ -225,7 +225,7 @@ export const FileExplorer = (props: FileExplorerProps) => { } const keyUpHandler = (e: KeyboardEvent) => { - if (e.key === 'Shift') { + if (!e.shiftKey) { setState(prevState => { return { ...prevState, ctrlKey: false } }) From 55d6244de6f0bfafa85a0e49b6fdc6513d533591 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 17:28:41 +0200 Subject: [PATCH 04/10] multi select plus multi delete --- .../src/lib/file-explorer-context-menu.tsx | 48 ++++++++-- .../file-explorer/src/lib/file-explorer.tsx | 96 ++++++++++++++----- .../file-explorer/src/lib/types/index.ts | 11 ++- .../src/lib/tree-view-item/tree-view-item.tsx | 2 +- 4 files changed, 119 insertions(+), 38 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index f7c5302b06..6f57b616be 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -1,12 +1,11 @@ import React, { useRef, useEffect } from 'react' // eslint-disable-line -import { FileExplorerContextMenuProps } from './types' +import { action, FileExplorerContextMenuProps } from './types' import './css/file-explorer-context-menu.css' export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => { - const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, paste, runScript, emit, pageX, pageY, path, type, ...otherProps } = props + const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, paste, runScript, emit, pageX, pageY, path, type, focus, ...otherProps } = props const contextMenuRef = useRef(null) - useEffect(() => { contextMenuRef.current.focus() }, []) @@ -22,13 +21,42 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => } }, [pageX, pageY]) + const filterItem = (item: action) => { + /** + * if there are multiple elements focused we need to take this and all conditions must be met plus the action must be set to 'multi' + * for example : 'downloadAsZip' with type ['file','folder','multi'] will work on files and folders when multiple are selected + **/ + const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + if (nonRootFocus.length > 1) { + for (const element of nonRootFocus) { + if (!itemMatchesCondition(item, element.type, element.key)) return false + } + return (item.type.includes('multi')) + } else { + return itemMatchesCondition(item, type, path) + } + } + + const itemMatchesCondition = (item: action, itemType: string, itemPath: string) => { + if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === itemType) !== -1)) return true + else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === itemPath) !== -1)) return true + else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => itemPath.endsWith(ext)) !== -1)) return true + else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => itemPath.match(new RegExp(value))).length > 0)) return true + else return false + } + + const getPath = () => { + const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + if (nonRootFocus.length > 1) { + return nonRootFocus.map((element) => { return element.key }) + } else { + return path + } + } + const menu = () => { return actions.filter(item => { - if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === type) !== -1)) return true - else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === path) !== -1)) return true - else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => path.endsWith(ext)) !== -1)) return true - else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => path.match(new RegExp(value))).length > 0)) return true - else return false + return filterItem(item) }).map((item, index) => { return
  • renamePath(path, type) break case 'Delete': - deletePath(path) + deletePath(getPath()) break case 'Push changes to gist': pushChangesToGist(path, type) @@ -68,7 +96,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => paste(path, type) break default: - emit && emit(item.id, path) + emit && emit(item.id, getPath()) break } hideContextMenu() diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index a433300e68..5d5317867b 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -51,7 +51,7 @@ export const FileExplorer = (props: FileExplorerProps) => { }, { id: 'delete', name: 'Delete', - type: ['file', 'folder', 'gist'], + type: ['file', 'folder', 'gist', 'multi'], path: [], extension: [], pattern: [] @@ -90,6 +90,13 @@ export const FileExplorer = (props: FileExplorerProps) => { path: [], extension: [], pattern: [] + }, { + id: 'test', + name: 'test', + type: ['file', 'folder', 'multi'], + path: [], + extension: [], + pattern: [] }], focusContext: { element: null, @@ -108,6 +115,7 @@ export const FileExplorer = (props: FileExplorerProps) => { hide: true, title: '', message: '', + children: <>, okLabel: '', okFn: () => {}, cancelLabel: '', @@ -211,7 +219,8 @@ export const FileExplorer = (props: FileExplorerProps) => { okFn: prevState.modals[0].okFn, cancelLabel: prevState.modals[0].cancelLabel, cancelFn: prevState.modals[0].cancelFn, - handleHide: prevState.modals[0].handleHide + handleHide: prevState.modals[0].handleHide, + children: prevState.modals[0].children } prevState.modals.shift() @@ -224,6 +233,31 @@ export const FileExplorer = (props: FileExplorerProps) => { } }, [state.modals]) + useEffect(() => { + const keyPressHandler = (e: KeyboardEvent) => { + if (e.key === 'Shift') { + setState(prevState => { + return { ...prevState, ctrlKey: true } + }) + } + } + + const keyUpHandler = (e: KeyboardEvent) => { + if (e.key === 'Shift') { + setState(prevState => { + return { ...prevState, ctrlKey: false } + }) + } + } + + document.addEventListener('keydown', keyPressHandler) + document.addEventListener('keyup', keyUpHandler) + return () => { + document.removeEventListener('keydown', keyPressHandler) + document.removeEventListener('keyup', keyUpHandler) + } + }, []) + useEffect(() => { if (canPaste) { addMenuItems([{ @@ -325,23 +359,26 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const deletePath = async (path: string) => { + const deletePath = async (path: string | string[]) => { const filesProvider = fileSystem.provider.provider - - if (filesProvider.isReadOnly(path)) { - return toast('cannot delete file. ' + name + ' is a read only explorer') + if (!Array.isArray(path)) path = [path] + const children: React.ReactFragment =
    Are you sure you want to delete {path.length > 1 ? 'these items' : 'this item'}?
    {path.map((item, i) => (
  • {item}
  • ))} + for (const p of path) { + if (filesProvider.isReadOnly(p)) { + return toast('cannot delete file. ' + name + ' is a read only explorer') + } } - const isDir = state.fileManager.isDirectory(path) - - modal(`Delete ${isDir ? 'folder' : 'file'}`, `Are you sure you want to delete ${path} ${isDir ? 'folder' : 'file'}?`, 'OK', async () => { - try { - const fileManager = state.fileManager - - await fileManager.remove(path) - } catch (e) { - toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${path}.`) + modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, '', 'OK', async () => { + const fileManager = state.fileManager + for (const p of path) { + try { + await fileManager.remove(p) + } catch (e) { + const isDir = state.fileManager.isDirectory(p) + toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${p}.`) + } } - }, 'Cancel', () => {}) + }, 'Cancel', () => {}, children) } const renamePath = async (oldPath: string, newPath: string) => { @@ -556,7 +593,7 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const emitContextMenuEvent = (id: string, path: string) => { + const emitContextMenuEvent = (id: string, path: string | string[]) => { plugin.emit(id, path) } @@ -566,13 +603,14 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const modal = (title: string, message: string, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => { + const modal = (title: string, message: string, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void, children?:React.ReactNode) => { setState(prevState => { return { ...prevState, modals: [...prevState.modals, { message, + children, title, okLabel, okFn, @@ -592,10 +630,22 @@ export const FileExplorer = (props: FileExplorerProps) => { const handleClickFile = (path: string, type: string) => { path = path.indexOf(props.name + '/') === 0 ? path.replace(props.name + '/', '') : path - state.fileManager.open(path) - setState(prevState => { - return { ...prevState, focusElement: [{ key: path, type }] } - }) + if (!state.ctrlKey) { + state.fileManager.open(path) + setState(prevState => { + return { ...prevState, focusElement: [{ key: path, type }] } + }) + } else { + if (state.focusElement.findIndex(item => item.key === path) !== -1) { + setState(prevState => { + return { ...prevState, focusElement: [...prevState.focusElement.filter(item => item.key !== path)] } + }) + } else { + setState(prevState => { + return { ...prevState, focusElement: [...prevState.focusElement, { key: path, type }] } + }) + } + } } const handleClickFolder = async (path: string, type: string) => { @@ -918,6 +968,7 @@ export const FileExplorer = (props: FileExplorerProps) => { id={ props.name } title={ state.focusModal.title } message={ state.focusModal.message } + children={ state.focusModal.children } hide={ state.focusModal.hide } okLabel={ state.focusModal.okLabel } okFn={ state.focusModal.okFn } @@ -943,6 +994,7 @@ export const FileExplorer = (props: FileExplorerProps) => { pageY={state.focusContext.y} path={state.focusContext.element} type={state.focusContext.type} + focus={state.focusElement} onMouseOver={(e) => { e.stopPropagation() handleMouseOver(state.focusContext.element) diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index e89361378c..880f8aafc3 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -28,12 +28,12 @@ export interface FileExplorerMenuProps { publishToGist: (path?: string) => void, uploadFile: (target: EventTarget & HTMLInputElement) => void } - +export type action = { name: string, type: string[], path: string[], extension: string[], pattern: string[], id: string } export interface FileExplorerContextMenuProps { - actions: { name: string, type: string[], path: string[], extension: string[], pattern: string[], id: string }[], + actions: action[], createNewFile: (folder?: string) => void, createNewFolder: (parentFolder?: string) => void, - deletePath: (path: string) => void, + deletePath: (path: string | string[]) => void, renamePath: (path: string, type: string) => void, hideContextMenu: () => void, publishToGist?: (path?: string, type?: string) => void, @@ -41,12 +41,13 @@ export interface FileExplorerContextMenuProps { publishFolderToGist?: (path?: string, type?: string) => void, publishFileToGist?: (path?: string, type?: string) => void, runScript?: (path: string) => void, - emit?: (id: string, path: string) => void, + emit?: (id: string, path: string | string[]) => void, pageX: number, pageY: number, path: string, type: string, + focus: {key:string, type:string}[], onMouseOver?: (...args) => void, - copy?: (path: string, type: string) => void + copy?: (path: string, type: string) => void, paste?: (destination: string, type: string) => void } diff --git a/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx b/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx index 6f7028f4cb..c570de5f07 100644 --- a/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx +++ b/libs/remix-ui/tree-view/src/lib/tree-view-item/tree-view-item.tsx @@ -14,7 +14,7 @@ export const TreeViewItem = (props: TreeViewItemProps) => { return (
  • !controlBehaviour && setIsExpanded(!isExpanded)}> - { controlBehaviour ? null : children ?
    : icon ?
    : null } + { children ?
    : icon ?
    : null } { label } From 25ee25b351ac0277df5c339196fd73fc3a1f0eec Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 17:31:59 +0200 Subject: [PATCH 05/10] rm test --- libs/remix-ui/file-explorer/src/lib/file-explorer.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 5d5317867b..a50e6d7cb3 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -90,13 +90,6 @@ export const FileExplorer = (props: FileExplorerProps) => { path: [], extension: [], pattern: [] - }, { - id: 'test', - name: 'test', - type: ['file', 'folder', 'multi'], - path: [], - extension: [], - pattern: [] }], focusContext: { element: null, From 010e192b0bb60b881b54ffdc95b26f831fa34d30 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Fri, 14 May 2021 17:42:26 +0200 Subject: [PATCH 06/10] use shiftkey --- libs/remix-ui/file-explorer/src/lib/file-explorer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index a50e6d7cb3..5a41ff1e7a 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -228,7 +228,7 @@ export const FileExplorer = (props: FileExplorerProps) => { useEffect(() => { const keyPressHandler = (e: KeyboardEvent) => { - if (e.key === 'Shift') { + if (e.shiftKey) { setState(prevState => { return { ...prevState, ctrlKey: true } }) @@ -236,7 +236,7 @@ export const FileExplorer = (props: FileExplorerProps) => { } const keyUpHandler = (e: KeyboardEvent) => { - if (e.key === 'Shift') { + if (!e.shiftKey) { setState(prevState => { return { ...prevState, ctrlKey: false } }) From 63e2b01a23ef223384ec9287cd1fb094dedc4611 Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Fri, 28 May 2021 12:54:49 +0100 Subject: [PATCH 07/10] Refactor delete all for multi-select --- .../src/lib/file-explorer-context-menu.tsx | 41 +++------- .../file-explorer/src/lib/file-explorer.tsx | 82 +++++++++++++------ .../file-explorer/src/lib/types/index.ts | 7 +- package-lock.json | 4 +- 4 files changed, 76 insertions(+), 58 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index 6f57b616be..0b92216fe8 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -6,6 +6,7 @@ import './css/file-explorer-context-menu.css' export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => { const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, copy, paste, runScript, emit, pageX, pageY, path, type, focus, ...otherProps } = props const contextMenuRef = useRef(null) + useEffect(() => { contextMenuRef.current.focus() }, []) @@ -21,43 +22,24 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => } }, [pageX, pageY]) - const filterItem = (item: action) => { - /** - * if there are multiple elements focused we need to take this and all conditions must be met plus the action must be set to 'multi' - * for example : 'downloadAsZip' with type ['file','folder','multi'] will work on files and folders when multiple are selected - **/ - const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) - if (nonRootFocus.length > 1) { - for (const element of nonRootFocus) { - if (!itemMatchesCondition(item, element.type, element.key)) return false - } - return (item.type.includes('multi')) - } else { - return itemMatchesCondition(item, type, path) - } - } - - const itemMatchesCondition = (item: action, itemType: string, itemPath: string) => { - if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === itemType) !== -1)) return true - else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === itemPath) !== -1)) return true - else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => itemPath.endsWith(ext)) !== -1)) return true - else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => itemPath.match(new RegExp(value))).length > 0)) return true + const itemMatchesCondition = (item: action) => { + if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === type) !== -1)) return true + else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === path) !== -1)) return true + else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => path.endsWith(ext)) !== -1)) return true + else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => path.match(new RegExp(value))).length > 0)) return true else return false } const getPath = () => { - const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) - if (nonRootFocus.length > 1) { - return nonRootFocus.map((element) => { return element.key }) + if (focus.length > 1) { + return focus.map((element) => element.key) } else { return path } } const menu = () => { - return actions.filter(item => { - return filterItem(item) - }).map((item, index) => { + return actions.filter(item => itemMatchesCondition(item)).map((item, index) => { return
  • renamePath(path, type) break case 'Delete': - deletePath(getPath()) + deletePath(path) break case 'Push changes to gist': pushChangesToGist(path, type) @@ -95,6 +77,9 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => case 'Paste': paste(path, type) break + case 'Delete All': + deletePath(getPath()) + break default: emit && emit(item.id, getPath()) break diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 5a41ff1e7a..ba7e43e8c2 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -6,7 +6,7 @@ import { Toaster } from '@remix-ui/toaster' // eslint-disable-line import Gists from 'gists' import { FileExplorerMenu } from './file-explorer-menu' // eslint-disable-line import { FileExplorerContextMenu } from './file-explorer-context-menu' // eslint-disable-line -import { FileExplorerProps, File } from './types' +import { FileExplorerProps, File, MenuItems } from './types' import { fileSystemReducer, fileSystemInitialState } from './reducers/fileSystem' import { fetchDirectory, init, resolveDirectory, addInputField, removeInputField } from './actions/fileSystem' import * as helper from '../../../../../apps/remix-ide/src/lib/helper' @@ -33,63 +33,80 @@ export const FileExplorer = (props: FileExplorerProps) => { type: ['folder', 'gist'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'newFolder', name: 'New Folder', type: ['folder', 'gist'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'rename', name: 'Rename', type: ['file', 'folder'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'delete', name: 'Delete', - type: ['file', 'folder', 'gist', 'multi'], + type: ['file', 'folder', 'gist'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'run', name: 'Run', type: [], path: [], extension: ['.js'], - pattern: [] + pattern: [], + multiselect: false }, { id: 'pushChangesToGist', name: 'Push changes to gist', type: ['gist'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'publishFolderToGist', name: 'Publish folder to gist', type: ['folder'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'publishFileToGist', name: 'Publish file to gist', type: ['file'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }, { id: 'copy', name: 'Copy', type: ['folder', 'file'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false + }, { + id: 'deleteAll', + name: 'Delete All', + type: ['folder', 'file'], + path: [], + extension: [], + pattern: [], + multiselect: true }], focusContext: { element: null, @@ -108,7 +125,6 @@ export const FileExplorer = (props: FileExplorerProps) => { hide: true, title: '', message: '', - children: <>, okLabel: '', okFn: () => {}, cancelLabel: '', @@ -212,8 +228,7 @@ export const FileExplorer = (props: FileExplorerProps) => { okFn: prevState.modals[0].okFn, cancelLabel: prevState.modals[0].cancelLabel, cancelFn: prevState.modals[0].cancelFn, - handleHide: prevState.modals[0].handleHide, - children: prevState.modals[0].children + handleHide: prevState.modals[0].handleHide } prevState.modals.shift() @@ -259,14 +274,15 @@ export const FileExplorer = (props: FileExplorerProps) => { type: ['folder', 'file'], path: [], extension: [], - pattern: [] + pattern: [], + multiselect: false }]) } else { removeMenuItems(['paste']) } }, [canPaste]) - const addMenuItems = (items: { id: string, name: string, type: string[], path: string[], extension: string[], pattern: string[] }[]) => { + const addMenuItems = (items: MenuItems) => { setState(prevState => { // filter duplicate items const actions = items.filter(({ name }) => prevState.actions.findIndex(action => action.name === name) === -1) @@ -355,13 +371,12 @@ export const FileExplorer = (props: FileExplorerProps) => { const deletePath = async (path: string | string[]) => { const filesProvider = fileSystem.provider.provider if (!Array.isArray(path)) path = [path] - const children: React.ReactFragment =
    Are you sure you want to delete {path.length > 1 ? 'these items' : 'this item'}?
    {path.map((item, i) => (
  • {item}
  • ))} for (const p of path) { if (filesProvider.isReadOnly(p)) { return toast('cannot delete file. ' + name + ' is a read only explorer') } } - modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, '', 'OK', async () => { + modal(`Delete ${path.length > 1 ? 'items' : 'item'}`, deleteMessage(path), 'OK', async () => { const fileManager = state.fileManager for (const p of path) { try { @@ -371,7 +386,7 @@ export const FileExplorer = (props: FileExplorerProps) => { toast(`Failed to remove ${isDir ? 'folder' : 'file'} ${p}.`) } } - }, 'Cancel', () => {}, children) + }, 'Cancel', () => {}) } const renamePath = async (oldPath: string, newPath: string) => { @@ -596,14 +611,13 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const modal = (title: string, message: string, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void, children?:React.ReactNode) => { + const modal = (title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => { setState(prevState => { return { ...prevState, modals: [...prevState.modals, { message, - children, title, okLabel, okFn, @@ -631,11 +645,14 @@ export const FileExplorer = (props: FileExplorerProps) => { } else { if (state.focusElement.findIndex(item => item.key === path) !== -1) { setState(prevState => { - return { ...prevState, focusElement: [...prevState.focusElement.filter(item => item.key !== path)] } + return { ...prevState, focusElement: prevState.focusElement.filter(item => item.key !== path) } }) } else { setState(prevState => { - return { ...prevState, focusElement: [...prevState.focusElement, { key: path, type }] } + const nonRootFocus = prevState.focusElement.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + + nonRootFocus.push({ key: path, type }) + return { ...prevState, focusElement: nonRootFocus } }) } } @@ -649,7 +666,10 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } else { setState(prevState => { - return { ...prevState, focusElement: [...prevState.focusElement, { key: path, type }] } + const nonRootFocus = prevState.focusElement.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + + nonRootFocus.push({ key: path, type }) + return { ...prevState, focusElement: nonRootFocus } }) } } else { @@ -806,6 +826,17 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } + const deleteMessage = (path: string[]) => { + return ( +
    +
    Are you sure you want to delete {path.length > 1 ? 'these items' : 'this item'}?
    + { + path.map((item, i) => (
  • {item}
  • )) + } +
    + ) + } + const label = (file: File) => { return (
    { id={ props.name } title={ state.focusModal.title } message={ state.focusModal.message } - children={ state.focusModal.children } hide={ state.focusModal.hide } okLabel={ state.focusModal.okLabel } okFn={ state.focusModal.okFn } @@ -973,7 +1003,7 @@ export const FileExplorer = (props: FileExplorerProps) => { { state.showContextMenu && 1 ? state.actions.filter(item => item.multiselect) : state.actions.filter(item => !item.multiselect)} hideContextMenu={hideContextMenu} createNewFile={handleNewFileInput} createNewFolder={handleNewFolderInput} diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 880f8aafc3..511d1b79a1 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -6,7 +6,7 @@ export interface FileExplorerProps { menuItems?: string[], plugin: any, focusRoot: boolean, - contextMenuItems: { id: string, name: string, type: string[], path: string[], extension: string[], pattern: string[] }[], + contextMenuItems: MenuItems, displayInput?: boolean, externalUploads?: EventTarget & HTMLInputElement } @@ -28,7 +28,10 @@ export interface FileExplorerMenuProps { publishToGist: (path?: string) => void, uploadFile: (target: EventTarget & HTMLInputElement) => void } -export type action = { name: string, type: string[], path: string[], extension: string[], pattern: string[], id: string } + +export type action = { name: string, type: string[], path: string[], extension: string[], pattern: string[], id: string, multiselect: boolean } + +export type MenuItems = action[] export interface FileExplorerContextMenuProps { actions: action[], createNewFile: (folder?: string) => void, diff --git a/package-lock.json b/package-lock.json index ef1e85062f..144c35c778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17419,7 +17419,7 @@ "express-ws": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-4.0.0.tgz", - "integrity": "sha512-KEyUw8AwRET2iFjFsI1EJQrJ/fHeGiJtgpYgEWG3yDv4l/To/m3a2GaYfeGyB3lsWdvbesjF5XCMx+SVBgAAYw==", + "integrity": "sha1-2r2NyXRRZBiQKkH+bjDtlJtNNsQ=", "requires": { "ws": "^5.2.0" }, @@ -17427,7 +17427,7 @@ "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "integrity": "sha1-3/7xSGa46NyRM1glFNG++vlumA8=", "requires": { "async-limiter": "~1.0.0" } From d88b848b049aacd07ec9f6d18599812076335b0d Mon Sep 17 00:00:00 2001 From: filip mertens Date: Mon, 31 May 2021 12:25:04 +0200 Subject: [PATCH 08/10] fixing multi focused items --- .../src/lib/file-explorer-context-menu.tsx | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index 8d64091673..2c96080866 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -21,11 +21,27 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => } }, [pageX, pageY]) - const itemMatchesCondition = (item: action) => { - if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === type) !== -1)) return true - else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === path) !== -1)) return true - else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => path.endsWith(ext)) !== -1)) return true - else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => path.match(new RegExp(value))).length > 0)) return true + const filterItem = (item: action) => { + /** + * if there are multiple elements focused we need to take this and all conditions must be met + * for example : 'downloadAsZip' with type ['file','folder','multi'] will work on files and folders when multiple are selected + **/ + const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) + if (nonRootFocus.length > 1) { + for (const element of nonRootFocus) { + if (!itemMatchesCondition(item, element.type, element.key)) return false + } + return true + } else { + return itemMatchesCondition(item, type, path) + } + } + + const itemMatchesCondition = (item: action, itemType: string, itemPath: string) => { + if (item.type && Array.isArray(item.type) && (item.type.findIndex(name => name === itemType) !== -1)) return true + else if (item.path && Array.isArray(item.path) && (item.path.findIndex(key => key === itemPath) !== -1)) return true + else if (item.extension && Array.isArray(item.extension) && (item.extension.findIndex(ext => itemPath.endsWith(ext)) !== -1)) return true + else if (item.pattern && Array.isArray(item.pattern) && (item.pattern.filter(value => itemPath.match(new RegExp(value))).length > 0)) return true else return false } @@ -38,7 +54,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => } const menu = () => { - return actions.filter(item => itemMatchesCondition(item)).map((item, index) => { + return actions.filter(item => filterItem(item)).map((item, index) => { return
  • Date: Mon, 31 May 2021 18:00:09 +0200 Subject: [PATCH 09/10] Update file-explorer-context-menu.tsx --- .../file-explorer/src/lib/file-explorer-context-menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index 2c96080866..c049a93a65 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -24,7 +24,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => const filterItem = (item: action) => { /** * if there are multiple elements focused we need to take this and all conditions must be met - * for example : 'downloadAsZip' with type ['file','folder','multi'] will work on files and folders when multiple are selected + * for example : 'downloadAsZip' with type ['file','folder'] will work on files and folders when multiple are selected **/ const nonRootFocus = focus.filter((el) => { return !(el.key === '' && el.type === 'folder') }) if (nonRootFocus.length > 1) { From 8ce3ff28c81dc116a53274de3311926eb79c41f2 Mon Sep 17 00:00:00 2001 From: filip mertens Date: Tue, 1 Jun 2021 10:59:48 +0200 Subject: [PATCH 10/10] prop children --- libs/remix-ui/file-explorer/src/lib/file-explorer.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 9f9893f487..ba7e43e8c2 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -992,7 +992,6 @@ export const FileExplorer = (props: FileExplorerProps) => { id={ props.name } title={ state.focusModal.title } message={ state.focusModal.message } - children={ state.focusModal.children } hide={ state.focusModal.hide } okLabel={ state.focusModal.okLabel } okFn={ state.focusModal.okFn }