Commit 882251f6 authored by ioedeveloper's avatar ioedeveloper

Remove file-explorer react library

parent 3550cda6
{
"presets": ["@nrwl/react/babel"],
"plugins": []
}
{
"env": {
"browser": true,
"es6": true
},
"extends": "../../../.eslintrc",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 11,
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error"
}
}
# remix-ui-file-explorer
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test remix-ui-file-explorer` to execute the unit tests via [Jest](https://jestjs.io).
export * from './lib/file-explorer'
export * from './lib/types'
export * from './lib/utils'
.remixui_contextContainer
{
display: block;
position: fixed;
border-radius: 2px;
z-index: 1000;
box-shadow: 0 0 4px var(--dark);
}
.remixui_contextContainer:focus {
outline: none;
}
.remixui_liitem
{
padding: 2px;
padding-left: 6px;
cursor: pointer;
color: var(--text-dark);
background-color: var(--light);
}
.remixui_liitem:hover
{
background-color: var(--secondary);
}
#remixui_menuitems
{
list-style: none;
margin: 0px;
}
\ No newline at end of file
.remixui_label {
margin-top : 4px;
}
.remixui_leaf {
overflow : hidden;
text-overflow : ellipsis;
width : 90%;
margin-bottom : 0px;
}
.remixui_fileexplorer {
box-sizing : border-box;
user-select : none;
}
input[type="file"] {
display: none;
}
.remixui_folder,
.remixui_file {
font-size : 14px;
cursor : pointer;
}
.remixui_file {
padding : 4px;
}
.remixui_newFile {
padding-right : 10px;
}
.remixui_newFile i {
cursor : pointer;
}
.remixui_newFile:hover {
transform : scale(1.3);
}
.remixui_menu {
margin-left : 20px;
}
.remixui_items {
display : inline
}
.remixui_remove {
margin-left : auto;
padding-left : 5px;
padding-right : 5px;
}
.remixui_activeMode {
display : flex;
width : 100%;
margin-right : 10px;
padding-right : 19px;
}
.remixui_activeMode > div {
min-width : 10px;
}
ul {
padding : 0;
}
import React, { useRef, useEffect } from 'react' // eslint-disable-line
import { action, FileExplorerContextMenuProps } from './types'
import './css/file-explorer-context-menu.css'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel'
declare global {
interface Window {
_paq: any
}
}
const _paq = window._paq = window._paq || [] //eslint-disable-line
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()
}, [])
useEffect(() => {
const menuItemsContainer = contextMenuRef.current
const boundary = menuItemsContainer.getBoundingClientRect()
if (boundary.bottom > (window.innerHeight || document.documentElement.clientHeight)) {
menuItemsContainer.style.position = 'fixed'
menuItemsContainer.style.bottom = '10px'
menuItemsContainer.style.top = null
}
}, [pageX, pageY])
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'] 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
}
const getPath = () => {
if (focus.length > 1) {
return focus.map((element) => element.key)
} else {
return path
}
}
const menu = () => {
return actions.filter(item => filterItem(item)).map((item, index) => {
return <li
id={`menuitem${item.name.toLowerCase()}`}
key={index}
className='remixui_liitem'
onClick={(e) => {
e.stopPropagation()
switch (item.name) {
case 'New File':
createNewFile(path)
break
case 'New Folder':
createNewFolder(path)
break
case 'Rename':
renamePath(path, type)
break
case 'Delete':
deletePath(getPath())
break
case 'Push changes to gist':
_paq.push(['trackEvent', 'fileExplorer', 'pushToChangesoGist'])
pushChangesToGist(path, type)
break
case 'Publish folder to gist':
_paq.push(['trackEvent', 'fileExplorer', 'publishFolderToGist'])
publishFolderToGist(path, type)
break
case 'Publish file to gist':
_paq.push(['trackEvent', 'fileExplorer', 'publishFileToGist'])
publishFileToGist(path, type)
break
case 'Run':
_paq.push(['trackEvent', 'fileExplorer', 'runScript'])
runScript(path)
break
case 'Copy':
copy(path, type)
break
case 'Paste':
paste(path, type)
break
case 'Delete All':
deletePath(getPath())
break
default:
_paq.push(['trackEvent', 'fileExplorer', 'customAction', `${item.id}/${item.name}`])
emit && emit({ ...item, path: [path] } as customAction)
break
}
hideContextMenu()
}}>{item.label || item.name}</li>
})
}
return (
<div
id="menuItemsContainer"
className="p-1 remixui_contextContainer bg-light shadow border"
style={{ left: pageX, top: pageY }}
ref={contextMenuRef}
onBlur={hideContextMenu}
tabIndex={500}
{...otherProps}
>
<ul id='remixui_menuitems'>{menu()}</ul>
</div>
)
}
export default FileExplorerContextMenu
import React, { useState, useEffect } from 'react' //eslint-disable-line
import { FileExplorerMenuProps } from './types'
export const FileExplorerMenu = (props: FileExplorerMenuProps) => {
const [state, setState] = useState({
menuItems: [
{
action: 'createNewFile',
title: 'Create New File',
icon: 'far fa-file'
},
{
action: 'createNewFolder',
title: 'Create New Folder',
icon: 'far fa-folder'
},
{
action: 'publishToGist',
title: 'Publish all the current workspace files (only root) to a github gist',
icon: 'fab fa-github'
},
{
action: 'uploadFile',
title: 'Load a local file into current workspace',
icon: 'fa fa-upload'
},
{
action: 'updateGist',
title: 'Update the current [gist] explorer',
icon: 'fab fa-github'
}
].filter(item => props.menuItems && props.menuItems.find((name) => { return name === item.action })),
actions: {}
})
useEffect(() => {
const actions = {
updateGist: () => {}
}
setState(prevState => {
return { ...prevState, actions }
})
}, [])
return (
<>
<span className='remixui_label' title={props.title} data-path={props.title} style={{ fontWeight: 'bold' }}>{ props.title }</span>
<span className="pl-2">{
state.menuItems.map(({ action, title, icon }, index) => {
if (action === 'uploadFile') {
return (
<label
id={action}
data-id={'fileExplorerUploadFile' + action }
className={icon + ' mb-0 remixui_newFile'}
title={title}
key={index}
>
<input id="fileUpload" data-id="fileExplorerFileUpload" type="file" onChange={(e) => {
e.stopPropagation()
props.uploadFile(e.target)
e.target.value = null
}}
multiple />
</label>
)
} else {
return (
<span
id={action}
data-id={'fileExplorerNewFile' + action}
onClick={(e) => {
e.stopPropagation()
if (action === 'createNewFile') {
props.createNewFile()
} else if (action === 'createNewFolder') {
props.createNewFolder()
} else if (action === 'publishToGist') {
props.publishToGist()
} else {
state.actions[action]()
}
}}
className={'newFile ' + icon + ' remixui_newFile'}
title={title}
key={index}
>
</span>
)
}
})}
</span>
</>
)
}
export default FileExplorerMenu
This diff is collapsed.
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel'
export type MenuItems = action[] // eslint-disable-line no-use-before-define
/* eslint-disable-next-line */
export interface FileExplorerProps {
name: string,
menuItems?: string[],
focusRoot: boolean,
contextMenuItems: MenuItems,
removedContextMenuItems: MenuItems,
displayInput?: boolean,
externalUploads?: EventTarget & HTMLInputElement,
resetFocus?: (value: boolean) => void,
files: { [x: string]: Record<string, File> }
}
export interface File {
path: string,
name: string,
isDirectory: boolean,
type: 'folder' | 'file' | 'gist',
child?: File[]
}
export interface FileExplorerMenuProps {
title: string,
menuItems: string[],
createNewFile: (folder?: string) => void,
createNewFolder: (parentFolder?: string) => void,
publishToGist: (path?: string) => void,
uploadFile: (target: EventTarget & HTMLInputElement) => void
}
export type action = { name: string, type?: Array<'folder' | 'gist' | 'file'>, path?: string[], extension?: string[], pattern?: string[], id: string, multiselect: boolean, label: string }
export interface FileExplorerContextMenuProps {
actions: action[],
createNewFile: (folder?: string) => void,
createNewFolder: (parentFolder?: string) => void,
deletePath: (path: string | string[]) => void,
renamePath: (path: string, type: string) => void,
hideContextMenu: () => void,
publishToGist?: (path?: string, type?: string) => void,
pushChangesToGist?: (path?: string, type?: string) => void,
publishFolderToGist?: (path?: string, type?: string) => void,
publishFileToGist?: (path?: string, type?: string) => void,
runScript?: (path: string) => void,
emit?: (cmd: customAction) => void,
pageX: number,
pageY: number,
path: string,
type: string,
focus: {key:string, type:string}[],
onMouseOver?: (...args) => void,
copy?: (path: string, type: string) => void,
paste?: (destination: string, type: string) => void
}
export interface FileExplorerState {
ctrlKey: boolean
newFileName: string
actions: {
id: string
name: string
type?: Array<'folder' | 'gist' | 'file'>
path?: string[]
extension?: string[]
pattern?: string[]
multiselect: boolean
label: string
}[]
focusContext: {
element: string
x: number
y: number
type: string
}
focusEdit: {
element: string
type: string
isNew: boolean
lastEdit: string
}
expandPath: string[]
mouseOverElement: string
showContextMenu: boolean
reservedKeywords: string[]
copyElement: {
key: string
type: 'folder' | 'gist' | 'file'
}[]
}
import { MenuItems } from '../types'
export const extractNameFromKey = (key: string): string => {
const keyPath = key.split('/')
return keyPath[keyPath.length - 1]
}
export const extractParentFromKey = (key: string):string => {
if (!key) return
const keyPath = key.split('/')
keyPath.pop()
return keyPath.join('/')
}
export const contextMenuActions: MenuItems = [{
id: 'newFile',
name: 'New File',
type: ['folder', 'gist'],
multiselect: false,
label: ''
}, {
id: 'newFolder',
name: 'New Folder',
type: ['folder', 'gist'],
multiselect: false,
label: ''
}, {
id: 'rename',
name: 'Rename',
type: ['file', 'folder'],
multiselect: false,
label: ''
}, {
id: 'delete',
name: 'Delete',
type: ['file', 'folder', 'gist'],
multiselect: false,
label: ''
}, {
id: 'run',
name: 'Run',
extension: ['.js'],
multiselect: false,
label: ''
}, {
id: 'pushChangesToGist',
name: 'Push changes to gist',
type: ['gist'],
multiselect: false,
label: ''
}, {
id: 'publishFolderToGist',
name: 'Publish folder to gist',
type: ['folder'],
multiselect: false,
label: ''
}, {
id: 'publishFileToGist',
name: 'Publish file to gist',
type: ['file'],
multiselect: false,
label: ''
}, {
id: 'copy',
name: 'Copy',
type: ['folder', 'file'],
multiselect: false,
label: ''
}, {
id: 'deleteAll',
name: 'Delete All',
type: ['folder', 'file'],
multiselect: true,
label: ''
}]
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}
import { extractNameFromKey, File } from '@remix-ui/file-explorer'
import { extractNameFromKey } from '@remix-ui/helper'
import * as _ from 'lodash'
interface Action {
type: string
......
import React, { useState, useEffect, useRef, useContext } from 'react' // eslint-disable-line
import { FileExplorer } from '@remix-ui/file-explorer' // eslint-disable-line
import { FileExplorer } from './components/file-explorer' // eslint-disable-line
import './remix-ui-workspace.css'
import { WorkspaceProps, WorkspaceState } from './types'
import { FileSystemContext } from './contexts'
......
......@@ -88,9 +88,6 @@
"remix-ui-toaster": {
"tags": []
},
"remix-ui-file-explorer": {
"tags": []
},
"debugger": {
"tags": []
},
......
......@@ -45,8 +45,12 @@
"@remix-ui/checkbox": ["libs/remix-ui/checkbox/src/index.ts"],
"@remix-ui/settings": ["libs/remix-ui/settings/src/index.ts"],
"@remix-project/core-plugin": ["libs/remix-core-plugin/src/index.ts"],
"@remix-ui/solidity-compiler": ["libs/remix-ui/solidity-compiler/src/index.ts"],
"@remix-ui/publish-to-storage": ["libs/remix-ui/publish-to-storage/src/index.ts"],
"@remix-ui/solidity-compiler": [
"libs/remix-ui/solidity-compiler/src/index.ts"
],
"@remix-ui/publish-to-storage": [
"libs/remix-ui/publish-to-storage/src/index.ts"
],
"@remix-ui/plugin-manager": ["libs/remix-ui/plugin-manager/src/index.ts"],
"@remix-ui/renderer": ["libs/remix-ui/renderer/src/index.ts"],
"@remix-ui/terminal": ["libs/remix-ui/terminal/src/index.ts"],
......
......@@ -623,25 +623,6 @@
}
}
},
"remix-ui-file-explorer": {
"root": "libs/remix-ui/file-explorer",
"sourceRoot": "libs/remix-ui/file-explorer/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": ["libs/remix-ui/file-explorer/tsconfig.lib.json"],
"exclude": [
"**/node_modules/**",
"!libs/remix-ui/file-explorer/**/*"
]
}
}
}
},
"debugger": {
"root": "apps/debugger",
"sourceRoot": "apps/debugger/src",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment