Merge branch 'master' of https://github.com/ethereum/remix-project into app-react
commit
4a6f6ca8bc
@ -0,0 +1,4 @@ |
|||||||
|
{ |
||||||
|
"presets": ["@nrwl/react/babel"], |
||||||
|
"plugins": [] |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
{ |
||||||
|
"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" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
{ |
||||||
|
"tabWidth": 2, |
||||||
|
"singleQuote": true, |
||||||
|
"semi": false |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
# remix-ui-vertical-icons-panel |
||||||
|
|
||||||
|
React library for RemixIde vertical icons Panel |
||||||
|
|
||||||
|
## Running unit tests |
||||||
|
|
||||||
|
Run `nx test remix-ui-vertical-icons-panel` to execute the unit tests via [Jest](https://jestjs.io). |
@ -0,0 +1 @@ |
|||||||
|
export * from './lib/remix-ui-vertical-icons-panel' |
@ -0,0 +1,68 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, useEffect, useReducer } from 'react' |
||||||
|
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer' |
||||||
|
import { BadgeStatus, IconProfile, IconStatus } from './Icon' |
||||||
|
|
||||||
|
interface BadgeProps { |
||||||
|
badgeStatus: BadgeStatus |
||||||
|
} |
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
function Badge ({ badgeStatus }: BadgeProps) { |
||||||
|
/** |
||||||
|
* resolve a classes list for @arg key |
||||||
|
* @param {Object} key |
||||||
|
* @param {Object} type |
||||||
|
*/ |
||||||
|
function resolveClasses (key: string, type: string) { |
||||||
|
let classes = 'remixui_status' |
||||||
|
switch (key) { |
||||||
|
case 'succeed': |
||||||
|
classes += ' fas fa-check-circle text-' + type + ' ' + 'remixui_statusCheck' |
||||||
|
break |
||||||
|
case 'edited': |
||||||
|
classes += ' fas fa-sync text-' + type + ' ' + 'remixui_statusCheck' |
||||||
|
break |
||||||
|
case 'loading': |
||||||
|
classes += ' fas fa-spinner text-' + type + ' ' + 'remixui_statusCheck' |
||||||
|
break |
||||||
|
case 'failed': |
||||||
|
classes += ' fas fa-exclamation-triangle text-' + type + ' ' + 'remixui_statusCheck' |
||||||
|
break |
||||||
|
default: { |
||||||
|
classes += ' badge badge-pill badge-' + type |
||||||
|
} |
||||||
|
} |
||||||
|
return classes |
||||||
|
} |
||||||
|
|
||||||
|
function checkStatusKeyValue (value: any, type: string) { |
||||||
|
if (value === 'succeed' || value === 'edited' || value === 'loading' || value === 'failed' || |
||||||
|
typeof value === 'number' || type === 'warning' || type === 'error' || type === 'success' || type === 'info' || type === 'danger') { |
||||||
|
return true |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
{ |
||||||
|
badgeStatus && checkStatusKeyValue(badgeStatus.key, badgeStatus.type) ? ( |
||||||
|
<i |
||||||
|
title={badgeStatus.title} |
||||||
|
className={resolveClasses(badgeStatus.key, badgeStatus.type!)} |
||||||
|
aria-hidden="true" |
||||||
|
> |
||||||
|
{badgeStatus.text} |
||||||
|
</i> |
||||||
|
) : null |
||||||
|
} |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Badge |
@ -0,0 +1,14 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
import React from 'react' |
||||||
|
|
||||||
|
function BasicLogo () { |
||||||
|
return (<svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 105 100"> |
||||||
|
<path d="M91.84,35a.09.09,0,0,1-.1-.07,41,41,0,0,0-79.48,0,.09.09,0,0,1-.1.07C9.45,35,1,35.35,1,42.53c0,8.56,1,16,6,20.32,2.16,1.85,5.81,2.3,9.27,2.22a44.4,44.4,0,0,0,6.45-.68.09.09,0,0,0,.06-.15A34.81,34.81,0,0,1,17,45c0-.1,0-.21,0-.31a35,35,0,0,1,70,0c0,.1,0,.21,0,.31a34.81,34.81,0,0,1-5.78,19.24.09.09,0,0,0,.06.15,44.4,44.4,0,0,0,6.45.68c3.46.08,7.11-.37,9.27-2.22,5-4.27,6-11.76,6-20.32C103,35.35,94.55,35,91.84,35Z"/> |
||||||
|
<path d="M52,74,25.4,65.13a.1.1,0,0,0-.1.17L51.93,91.93a.1.1,0,0,0,.14,0L78.7,65.3a.1.1,0,0,0-.1-.17L52,74A.06.06,0,0,1,52,74Z"/> |
||||||
|
<path d="M75.68,46.9,82,45a.09.09,0,0,0,.08-.09,29.91,29.91,0,0,0-.87-6.94.11.11,0,0,0-.09-.08l-6.43-.58a.1.1,0,0,1-.06-.18l4.78-4.18a.13.13,0,0,0,0-.12,30.19,30.19,0,0,0-3.65-6.07.09.09,0,0,0-.11,0l-5.91,2a.1.1,0,0,1-.12-.14L72.19,23a.11.11,0,0,0,0-.12,29.86,29.86,0,0,0-5.84-4.13.09.09,0,0,0-.11,0l-4.47,4.13a.1.1,0,0,1-.17-.07l.09-6a.1.1,0,0,0-.07-.1,30.54,30.54,0,0,0-7-1.47.1.1,0,0,0-.1.07l-2.38,5.54a.1.1,0,0,1-.18,0l-2.37-5.54a.11.11,0,0,0-.11-.06,30,30,0,0,0-7,1.48.12.12,0,0,0-.07.1l.08,6.05a.09.09,0,0,1-.16.07L37.8,18.76a.11.11,0,0,0-.12,0,29.75,29.75,0,0,0-5.83,4.13.11.11,0,0,0,0,.12l2.59,5.6a.11.11,0,0,1-.13.14l-5.9-2a.11.11,0,0,0-.12,0,30.23,30.23,0,0,0-3.62,6.08.11.11,0,0,0,0,.12l4.79,4.19a.1.1,0,0,1-.06.17L23,37.91a.1.1,0,0,0-.09.07A29.9,29.9,0,0,0,22,44.92a.1.1,0,0,0,.07.1L28.4,47a.1.1,0,0,1,0,.18l-5.84,3.26a.16.16,0,0,0,0,.11,30.17,30.17,0,0,0,2.1,6.76c.32.71.67,1.4,1,2.08a.1.1,0,0,0,.06,0L52,68.16H52l26.34-8.78a.1.1,0,0,0,.06-.05,30.48,30.48,0,0,0,3.11-8.88.1.1,0,0,0-.05-.11l-5.83-3.26A.1.1,0,0,1,75.68,46.9Z"/> |
||||||
|
</svg> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default BasicLogo |
@ -0,0 +1,18 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
import React, { MutableRefObject } from 'react' |
||||||
|
|
||||||
|
export interface ChevronProps { |
||||||
|
divElementRef: MutableRefObject<any> |
||||||
|
cssRule: string |
||||||
|
} |
||||||
|
|
||||||
|
function Chevron (props: ChevronProps) { |
||||||
|
return ( |
||||||
|
<> |
||||||
|
{ props.divElementRef.current && props.divElementRef.current.scrollHeight > props.divElementRef.current.clientHeight |
||||||
|
? <i className={props.cssRule}></i> : null } |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export { Chevron } |
@ -0,0 +1,62 @@ |
|||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, useEffect, useReducer } from 'react' |
||||||
|
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer' |
||||||
|
import Badge from './Badge' |
||||||
|
import Icon, { IconStatus } from './Icon' |
||||||
|
|
||||||
|
interface DebuggerProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
text: '', |
||||||
|
key: '', |
||||||
|
title: '', |
||||||
|
type: '' |
||||||
|
} |
||||||
|
|
||||||
|
function Debugger ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: DebuggerProps) { |
||||||
|
const [badgeStatus, dispatchStatusUpdate] = useReducer(iconBadgeReducer, initialState) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
verticalIconsPlugin.on('debugger', 'statusChanged', (iconStatus: IconStatus) => { |
||||||
|
const action: IconBadgeReducerAction = { type: 'debugger', payload: { status: iconStatus, verticalIconPlugin: verticalIconsPlugin } } |
||||||
|
dispatchStatusUpdate(action) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{verticalIconsPlugin.targetProfileForChange && |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange).length |
||||||
|
? Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'debugger') |
||||||
|
.map(p => ( |
||||||
|
<div id="debuggingIcons" data-id="verticalIconsDebuggingIcons" key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
}> |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} |
||||||
|
/> |
||||||
|
<Badge |
||||||
|
badgeStatus={badgeStatus} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
)) |
||||||
|
: null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Debugger |
@ -0,0 +1,59 @@ |
|||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, useEffect, useRef } from 'react' |
||||||
|
import Icon from './Icon' |
||||||
|
|
||||||
|
interface FilePanelProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
|
||||||
|
function FilePanel ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: FilePanelProps) { |
||||||
|
const filePanelRef = useRef(null) |
||||||
|
function onThemeChanged (themeType: any) { |
||||||
|
const invert = themeType === 'dark' ? 1 : 0 |
||||||
|
// @ts-ignore
|
||||||
|
const active = filePanelRef.current && filePanelRef.current.querySelector('.active') |
||||||
|
if (active) { |
||||||
|
// @ts-ignore
|
||||||
|
const image = filePanelRef.current.querySelector('.remixui_image') |
||||||
|
image.style.setProperty('filter', `invert(${invert})`) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const themeModule = verticalIconsPlugin.registry.get('themeModule').api |
||||||
|
themeModule.events.on('themeChanged', (theme: any) => { |
||||||
|
onThemeChanged(theme.quality) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{verticalIconsPlugin.targetProfileForChange && |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange).length |
||||||
|
? Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'filePanel') |
||||||
|
.map(p => ( |
||||||
|
<div id="fileExplorerIcons" key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} data-id="verticalIconsFileExplorerIcons" |
||||||
|
ref={filePanelRef} |
||||||
|
> |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
)) |
||||||
|
: null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default FilePanel |
@ -0,0 +1,26 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
import React, { ReactNode } from 'react' |
||||||
|
import BasicLogo from './BasicLogo' |
||||||
|
interface HomeProps { |
||||||
|
verticalIconPlugin: VerticalIcons |
||||||
|
} |
||||||
|
|
||||||
|
function Home ({ verticalIconPlugin }: HomeProps) { |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className="pl-1 mt-2 remixui_homeIcon" |
||||||
|
onClick={async () => verticalIconPlugin.activateHome()} |
||||||
|
// @ts-ignore
|
||||||
|
plugin="home" |
||||||
|
title="Home" |
||||||
|
data-id="verticalIconsHomeIcon" |
||||||
|
id="verticalIconsHomeIcon" |
||||||
|
> |
||||||
|
<BasicLogo /> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Home |
@ -0,0 +1,134 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */ |
||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
import VerticalIconsContextMenu from '../vertical-icons-context-menu' |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
import React, { Fragment, SyntheticEvent, useEffect, useReducer, useRef, useState } from 'react' |
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
import Badge from './Badge' |
||||||
|
|
||||||
|
interface IconProps { |
||||||
|
verticalIconPlugin: VerticalIcons |
||||||
|
profile: IconProfile |
||||||
|
contextMenuAction: (evt: any, profileName: string, documentation: string) => void |
||||||
|
addActive: (profileName: string) => void |
||||||
|
removeActive: () => void |
||||||
|
badgeStatus?: BadgeStatus |
||||||
|
} |
||||||
|
|
||||||
|
export interface IconStatus { |
||||||
|
key: string |
||||||
|
title: string |
||||||
|
type: string |
||||||
|
} |
||||||
|
|
||||||
|
export interface BadgeStatus extends IconStatus { |
||||||
|
text: string |
||||||
|
} |
||||||
|
|
||||||
|
export interface IconProfile { |
||||||
|
description: string |
||||||
|
displayName: string |
||||||
|
documentation: string |
||||||
|
events: any[] |
||||||
|
icon: string |
||||||
|
kind: string |
||||||
|
location: string |
||||||
|
methods: string[] |
||||||
|
name: string |
||||||
|
version: string |
||||||
|
tooltip?: string |
||||||
|
} |
||||||
|
|
||||||
|
function Icon ({ |
||||||
|
profile, |
||||||
|
verticalIconPlugin, |
||||||
|
contextMenuAction, |
||||||
|
addActive, |
||||||
|
removeActive, |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
badgeStatus |
||||||
|
}: IconProps) { |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { tooltip, displayName, name, kind, icon, documentation } = profile |
||||||
|
const [title] = useState(() => { |
||||||
|
const temp = tooltip || displayName || name |
||||||
|
return temp.replace(/^\w/, (word: string) => word.toUpperCase()) |
||||||
|
}) |
||||||
|
const [links, setLinks] = useState<{ Documentation: string, CanDeactivate: boolean }>( |
||||||
|
{} as { Documentation: string, CanDeactivate: boolean } |
||||||
|
) |
||||||
|
// @ts-ignore
|
||||||
|
const [pageX, setPageX] = useState<number>(null) |
||||||
|
// @ts-ignore
|
||||||
|
const [pageY, setPageY] = useState<number>(null) |
||||||
|
const [showContext, setShowContext] = useState(false) |
||||||
|
const [canDeactivate] = useState(false) |
||||||
|
const iconRef = useRef<any>(null) |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
|
||||||
|
const handleContextMenu = (e: SyntheticEvent & PointerEvent) => { |
||||||
|
const deactivationState = verticalIconPlugin.appManager |
||||||
|
.canDeactivatePlugin(verticalIconPlugin.defaultProfile, { name }) |
||||||
|
if (documentation && documentation.length > 0 && deactivationState) { |
||||||
|
setLinks({ Documentation: documentation, CanDeactivate: deactivationState }) |
||||||
|
} else { |
||||||
|
setLinks({ Documentation: documentation, CanDeactivate: deactivationState }) |
||||||
|
} |
||||||
|
setShowContext(false) |
||||||
|
setPageX(e.pageX) |
||||||
|
setPageY(e.pageY) |
||||||
|
setShowContext(true) |
||||||
|
} |
||||||
|
function closeContextMenu () { |
||||||
|
setShowContext(false) |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<div |
||||||
|
className={name === 'pluginManager' ? 'remixui_icon ml-2 mt-2 mr-2 mb-0 pl-1' : 'remixui_icon m-2 pl-1'} |
||||||
|
onLoad={() => { |
||||||
|
if (name === 'filePanel') { |
||||||
|
addActive(name) |
||||||
|
} |
||||||
|
}} |
||||||
|
onClick={() => { |
||||||
|
removeActive() |
||||||
|
addActive(name) |
||||||
|
verticalIconPlugin.toggle(name) |
||||||
|
}} |
||||||
|
// @ts-ignore
|
||||||
|
plugin={name} |
||||||
|
title={title} |
||||||
|
onContextMenu={(e: any) => { |
||||||
|
e.preventDefault() |
||||||
|
e.stopPropagation() |
||||||
|
handleContextMenu(e) |
||||||
|
}} |
||||||
|
data-id={`verticalIconsKind${name}`} |
||||||
|
id={`verticalIconsKind${name}`} |
||||||
|
ref={iconRef} |
||||||
|
> |
||||||
|
<img className="remixui_image" src={icon} alt={name} /> |
||||||
|
<Badge |
||||||
|
badgeStatus={badgeStatus!} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
{showContext ? ( |
||||||
|
<VerticalIconsContextMenu |
||||||
|
pageX={pageX} |
||||||
|
pageY={pageY} |
||||||
|
links={links} |
||||||
|
profileName={name} |
||||||
|
hideContextMenu={closeContextMenu} |
||||||
|
canBeDeactivated={canDeactivate} |
||||||
|
verticalIconPlugin={verticalIconPlugin} |
||||||
|
contextMenuAction={contextMenuAction} |
||||||
|
/> |
||||||
|
) : null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Icon |
@ -0,0 +1,66 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
import React, { useEffect, useReducer } from 'react' |
||||||
|
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer' |
||||||
|
import Icon, { IconStatus } from './Icon' |
||||||
|
|
||||||
|
function customFilter (p: string) { |
||||||
|
if (p !== 'settings' && p !== 'pluginManager' && |
||||||
|
p !== 'filePanel' && p !== 'debugger' && |
||||||
|
p !== 'compiler' && p !== 'solidity' && |
||||||
|
p !== 'udapp' && p !== 'testing' && p !== 'solidityStaticAnalysis') return true |
||||||
|
return false |
||||||
|
} |
||||||
|
interface OtherIconsProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
text: '', |
||||||
|
key: '', |
||||||
|
title: '', |
||||||
|
type: '' |
||||||
|
} |
||||||
|
|
||||||
|
function OtherIcons ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: OtherIconsProps) { |
||||||
|
const [badgeStatus, dispatchStatusUpdate] = useReducer(iconBadgeReducer, initialState) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(customFilter) |
||||||
|
.forEach(p => |
||||||
|
verticalIconsPlugin.on(verticalIconsPlugin.targetProfileForChange[p].name, 'statusChanged', (iconStatus: IconStatus) => { |
||||||
|
const action: IconBadgeReducerAction = { |
||||||
|
type: verticalIconsPlugin.targetProfileForChange[p].name, |
||||||
|
payload: { status: iconStatus, verticalIconPlugin: verticalIconsPlugin } |
||||||
|
} |
||||||
|
dispatchStatusUpdate(action) |
||||||
|
})) |
||||||
|
}, []) |
||||||
|
return ( |
||||||
|
<div id="otherIcons"> |
||||||
|
{ |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(customFilter) |
||||||
|
.map(p => ( |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} |
||||||
|
badgeStatus={badgeStatus} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default OtherIcons |
@ -0,0 +1,36 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
import React, { Fragment } from 'react' |
||||||
|
import Icon from './Icon' |
||||||
|
|
||||||
|
interface PluginManagerProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
|
||||||
|
function PluginManager ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: PluginManagerProps) { |
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'pluginManager') |
||||||
|
.map(p => ( |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p] |
||||||
|
.displayName |
||||||
|
} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default PluginManager |
@ -0,0 +1,67 @@ |
|||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, MutableRefObject } from 'react' |
||||||
|
import { Chevron } from './Chevron' |
||||||
|
import Debugger from './Debugger' |
||||||
|
import FilePanel from './FilePanel' |
||||||
|
import PluginManager from './PluginManager' |
||||||
|
import Solidity from './Solidity' |
||||||
|
import SolidityStaticAnalysis from './SolidityStaticAnalysis' |
||||||
|
import Udapp from './Udapp' |
||||||
|
|
||||||
|
interface RequiredSectionProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
scrollableRef: MutableRefObject<any> |
||||||
|
} |
||||||
|
|
||||||
|
function RequiredSection ({ verticalIconsPlugin, itemContextAction, addActive, removeActive, scrollableRef }: RequiredSectionProps) { |
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
<FilePanel |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
<PluginManager |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
<Solidity |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
<Udapp |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
<SolidityStaticAnalysis |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
<Debugger |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
<Chevron |
||||||
|
divElementRef={scrollableRef} |
||||||
|
cssRule={'fa fa-chevron-up remixui_icon-chevron mt-0 mb-0 ml-1 pl-3'} |
||||||
|
/> |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export { RequiredSection } |
@ -0,0 +1,60 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
import React, { useEffect, useRef } from 'react' |
||||||
|
import { Chevron } from './Chevron' |
||||||
|
import Icon from './Icon' |
||||||
|
|
||||||
|
interface SettingsProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
scrollableRef: React.MutableRefObject<any> |
||||||
|
} |
||||||
|
|
||||||
|
function Settings ({ scrollableRef, verticalIconsPlugin, itemContextAction, addActive, removeActive }: SettingsProps) { |
||||||
|
const settingsRef = useRef(null) |
||||||
|
function onThemeChanged (themeType: any) { |
||||||
|
const invert = themeType === 'dark' ? 1 : 0 |
||||||
|
// @ts-ignore
|
||||||
|
const active = settingsRef.current.querySelector('.active') |
||||||
|
if (active) { |
||||||
|
// @ts-ignore
|
||||||
|
const image = settingsRef.current.querySelector('.remixui_image') |
||||||
|
image.style.setProperty('filter', `invert(${invert})`) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const themeModule = verticalIconsPlugin.registry.get('themeModule').api |
||||||
|
themeModule.events.on('themeChanged', (theme: any) => { |
||||||
|
onThemeChanged(theme.quality) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
return ( |
||||||
|
<div id="settingsIcons" className="remixui_settings mb-0 flex-grow-0" data-id="vertialIconsSettingsIcons" ref={settingsRef}> |
||||||
|
<Chevron |
||||||
|
divElementRef={scrollableRef} |
||||||
|
cssRule={'fa fa-chevron-down remixui_icon-chevron mt-0 mb-0 ml-1 pl-3'} |
||||||
|
/> |
||||||
|
{Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'settings') |
||||||
|
.map(p => ( |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p] |
||||||
|
.displayName |
||||||
|
} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Settings |
@ -0,0 +1,58 @@ |
|||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, useEffect, useReducer } from 'react' |
||||||
|
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer' |
||||||
|
// import Badge from './Badge'
|
||||||
|
import Icon, { IconStatus } from './Icon' |
||||||
|
|
||||||
|
interface SolidityProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
const initialState = { |
||||||
|
text: '', |
||||||
|
key: '', |
||||||
|
title: '', |
||||||
|
type: '' |
||||||
|
} |
||||||
|
|
||||||
|
function Solidity ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: SolidityProps) { |
||||||
|
const [badgeStatus, dispatchStatusUpdate] = useReducer(iconBadgeReducer, initialState) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
verticalIconsPlugin.on('solidity', 'statusChanged', (iconStatus: IconStatus) => { |
||||||
|
const action: IconBadgeReducerAction = { type: 'solidity', payload: { status: iconStatus, verticalIconPlugin: verticalIconsPlugin } } |
||||||
|
dispatchStatusUpdate(action) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{verticalIconsPlugin.targetProfileForChange && |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange).length |
||||||
|
? Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'solidity') |
||||||
|
.map(p => ( |
||||||
|
<div id="compileIcons" key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
}> |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} |
||||||
|
badgeStatus={badgeStatus} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
)) |
||||||
|
: null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Solidity |
@ -0,0 +1,58 @@ |
|||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, useEffect, useReducer } from 'react' |
||||||
|
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer' |
||||||
|
// import Badge from './Badge'
|
||||||
|
import Icon, { IconStatus } from './Icon' |
||||||
|
|
||||||
|
interface SolidityStaticAnalysisProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
text: '', |
||||||
|
key: '', |
||||||
|
title: '', |
||||||
|
type: '' |
||||||
|
} |
||||||
|
|
||||||
|
function SolidityStaticAnalysis ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: SolidityStaticAnalysisProps) { |
||||||
|
const [badgeStatus, dispatchStatusUpdate] = useReducer(iconBadgeReducer, initialState) |
||||||
|
useEffect(() => { |
||||||
|
verticalIconsPlugin.on('solidityStaticAnalysis', 'statusChanged', (iconStatus: IconStatus) => { |
||||||
|
const action: IconBadgeReducerAction = { type: 'solidityStaticAnalysis', payload: { status: iconStatus, verticalIconPlugin: verticalIconsPlugin } } |
||||||
|
dispatchStatusUpdate(action) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{verticalIconsPlugin.targetProfileForChange && |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange).length |
||||||
|
? Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'solidityStaticAnalysis') |
||||||
|
.map(p => ( |
||||||
|
<div id="analysisIcons" className="remixui_iconContainer" key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
}> |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} |
||||||
|
badgeStatus={badgeStatus} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
)) |
||||||
|
: null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default SolidityStaticAnalysis |
@ -0,0 +1,60 @@ |
|||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
import React, { Fragment, useEffect, useReducer } from 'react' |
||||||
|
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer' |
||||||
|
import Icon, { IconStatus } from './Icon' |
||||||
|
|
||||||
|
interface UdappProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
itemContextAction: (e: any, name: string, documentation: string) => Promise<void> |
||||||
|
addActive: (name: string) => void |
||||||
|
removeActive: () => void |
||||||
|
} |
||||||
|
|
||||||
|
const initialState = { |
||||||
|
text: '', |
||||||
|
key: '', |
||||||
|
title: '', |
||||||
|
type: '' |
||||||
|
} |
||||||
|
|
||||||
|
function Udapp ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: UdappProps) { |
||||||
|
const [badgeStatus, dispatchStatusUpdate] = useReducer(iconBadgeReducer, initialState) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
verticalIconsPlugin.on('udapp', 'statusChanged', (iconStatus: IconStatus) => { |
||||||
|
const action: IconBadgeReducerAction = { type: 'udapp', payload: { status: iconStatus, verticalIconPlugin: verticalIconsPlugin } } |
||||||
|
dispatchStatusUpdate(action) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{verticalIconsPlugin.targetProfileForChange && |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange).length |
||||||
|
? Object.keys(verticalIconsPlugin.targetProfileForChange) |
||||||
|
.filter(p => p === 'udapp') |
||||||
|
.map(p => ( |
||||||
|
<div id="runIcons" data-id="verticalIconsKindUdapp" key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} |
||||||
|
> |
||||||
|
<Icon |
||||||
|
profile={verticalIconsPlugin.targetProfileForChange[p]} |
||||||
|
verticalIconPlugin={verticalIconsPlugin} |
||||||
|
contextMenuAction={itemContextAction} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
key={ |
||||||
|
verticalIconsPlugin.targetProfileForChange[p].displayName |
||||||
|
} |
||||||
|
badgeStatus={badgeStatus} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
)) |
||||||
|
: null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Udapp |
@ -0,0 +1,44 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import helper from 'apps/remix-ide/src/lib/helper' |
||||||
|
import { BadgeStatus, IconStatus } from '../components/Icon' |
||||||
|
import React, { MutableRefObject } from 'react' |
||||||
|
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel' |
||||||
|
|
||||||
|
export type IconBadgeReducerAction = { |
||||||
|
readonly type: string |
||||||
|
readonly payload: any |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set a new status for the @arg name |
||||||
|
* @param {String} name |
||||||
|
* @param {Object} status |
||||||
|
*/ |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
function setIconStatus (name: string, status: IconStatus) { |
||||||
|
if (status.key === 'none') return { ...status, text: '' } // remove status
|
||||||
|
|
||||||
|
let text = '' |
||||||
|
let key = '' |
||||||
|
if (typeof status.key === 'number') { |
||||||
|
key = status.key |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
text = key |
||||||
|
} else key = helper.checkSpecialChars(status.key) ? '' : status.key |
||||||
|
|
||||||
|
let thisType = '' |
||||||
|
if (status.type === 'error') { |
||||||
|
thisType = 'danger' // to use with bootstrap
|
||||||
|
} else thisType = helper.checkSpecialChars(status.type) ? '' : status.type! |
||||||
|
const title = helper.checkSpecialChars(status.title) ? '' : status.title |
||||||
|
return { title, type: thisType, key, text } |
||||||
|
} |
||||||
|
|
||||||
|
export function iconBadgeReducer (state: BadgeStatus, action: IconBadgeReducerAction) { |
||||||
|
const { status, ref, verticalIconPlugin } = action.payload |
||||||
|
if (Object.keys(verticalIconPlugin.targetProfileForChange).includes(action.type)) { |
||||||
|
const setStatus = setIconStatus(action.type, status) |
||||||
|
return setStatus |
||||||
|
} |
||||||
|
return state |
||||||
|
} |
@ -0,0 +1,124 @@ |
|||||||
|
.remixui_homeIcon { |
||||||
|
/* display: block; */ |
||||||
|
width: 42px; |
||||||
|
height: 42px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
.remixui_homeIcon svg path { |
||||||
|
fill: var(--primary); |
||||||
|
} |
||||||
|
.remixui_homeIcon svg polygon { |
||||||
|
fill: var(--primary); |
||||||
|
} |
||||||
|
.remixui_icons { |
||||||
|
display: flex; |
||||||
|
flex-flow: column nowrap; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.remixui_icon { |
||||||
|
cursor: pointer; |
||||||
|
margin-bottom: 3px; |
||||||
|
position: 12px; |
||||||
|
width: 36px; |
||||||
|
height: 36px; |
||||||
|
padding: relative; |
||||||
|
border-radius: 8px; |
||||||
|
} |
||||||
|
.remixui_icon img { |
||||||
|
width: 28px; |
||||||
|
height: 28px; |
||||||
|
padding: 4px; |
||||||
|
filter: invert(0.5); |
||||||
|
} |
||||||
|
.remixui_image { |
||||||
|
} |
||||||
|
.remixui_icon svg { |
||||||
|
width: 28px; |
||||||
|
height: 28px; |
||||||
|
padding: 4px; |
||||||
|
} |
||||||
|
.remixui_icon[title='Settings'] { |
||||||
|
order: 5; |
||||||
|
align-self: center; |
||||||
|
bottom: 0; |
||||||
|
} |
||||||
|
.remixui_status { |
||||||
|
position: relative; |
||||||
|
bottom: 0; |
||||||
|
right: 0; |
||||||
|
left: 12px; |
||||||
|
top: -13px; |
||||||
|
} |
||||||
|
.remixui_statusCheck { |
||||||
|
font-size: 1.2em; |
||||||
|
} |
||||||
|
.remixui_statusWithBG { |
||||||
|
border-radius: 8px; |
||||||
|
background-color: var(--danger); |
||||||
|
color: var(--light); |
||||||
|
font-size: 12px; |
||||||
|
height: 15px; |
||||||
|
text-align: center; |
||||||
|
font-weight: bold; |
||||||
|
padding-left: 5px; |
||||||
|
padding-right: 5px; |
||||||
|
} |
||||||
|
|
||||||
|
.remixui_verticalIconContextcontainer { |
||||||
|
display: block; |
||||||
|
position: fixed; |
||||||
|
border-radius: 2px; |
||||||
|
z-index: 1000; |
||||||
|
box-shadow: 0 0 4px var(--dark); |
||||||
|
} |
||||||
|
.remixui_verticalIconContextcontainer:focus { |
||||||
|
outline: 0; |
||||||
|
} |
||||||
|
.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_scrollbar { |
||||||
|
overflow-y: scroll; |
||||||
|
scrollbar-width: none; /* Firefox hide scrollbar */ |
||||||
|
-ms-overflow-style: none; |
||||||
|
} |
||||||
|
.remixui_scrollable-container { |
||||||
|
flex-basis: 510px; |
||||||
|
flex-grow: 2; |
||||||
|
/* border-bottom: 3px solid #3f4455; */ |
||||||
|
} |
||||||
|
.remixui_scrollbar::-webkit-scrollbar { /* Chrome, Safari and other Webkit browsers*/ |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.remixui_hide-scroll { |
||||||
|
overflow-x: 'hidden'; |
||||||
|
} |
||||||
|
.remixui_default-icons-container { |
||||||
|
border-bottom: 2px solid #3f4455; |
||||||
|
} |
||||||
|
.remixui_icon-chevron { |
||||||
|
z-index: 1000; |
||||||
|
} |
||||||
|
|
||||||
|
.remixui_settings { |
||||||
|
flex-basis: 50px; |
||||||
|
} |
||||||
|
|
||||||
|
.remixui_requiredSection { |
||||||
|
flex-basis: 180px; |
||||||
|
flex-grow: 1; |
||||||
|
} |
||||||
|
|
||||||
|
#menuitems { |
||||||
|
list-style: none; |
||||||
|
margin: 0px; |
||||||
|
} |
@ -0,0 +1,139 @@ |
|||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
import React, { |
||||||
|
Fragment, |
||||||
|
useEffect, |
||||||
|
useRef |
||||||
|
} from 'react' |
||||||
|
|
||||||
|
import './remix-ui-vertical-icons-panel.css' |
||||||
|
import OtherIcons from './components/OtherIcons' |
||||||
|
import { VerticalIcons } from '../../types/vertical-icons-panel' |
||||||
|
import Home from './components/Home' |
||||||
|
import Settings from './components/Settings' |
||||||
|
import { RequiredSection } from './components/RequiredSection' |
||||||
|
export interface RemixUiVerticalIconsPanelProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
} |
||||||
|
|
||||||
|
let scrollHeight: any |
||||||
|
|
||||||
|
export function RemixUiVerticalIconsPanel ({ |
||||||
|
verticalIconsPlugin |
||||||
|
}: RemixUiVerticalIconsPanelProps) { |
||||||
|
const scrollableRef = useRef<any>() |
||||||
|
const iconPanelRef = useRef<any>() |
||||||
|
|
||||||
|
function onThemeChanged (themeType: any) { |
||||||
|
const invert = themeType === 'dark' ? 1 : 0 |
||||||
|
// @ts-ignore
|
||||||
|
const active = iconPanelRef.current.querySelector('.active') |
||||||
|
if (active) { |
||||||
|
// @ts-ignore
|
||||||
|
const image = iconPanelRef.current.querySelector('.remixui_image') |
||||||
|
image.style.setProperty('filter', `invert(${invert})`) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function removeActive () { |
||||||
|
// @ts-ignore
|
||||||
|
const images = iconPanelRef.current.querySelectorAll('.remixui_image') |
||||||
|
images.forEach(function (im: any) { |
||||||
|
im.style.setProperty('filter', 'invert(0.5)') |
||||||
|
}) |
||||||
|
|
||||||
|
// remove active
|
||||||
|
// @ts-ignore
|
||||||
|
const currentActive = iconPanelRef.current.querySelector('.active') |
||||||
|
if (currentActive) { |
||||||
|
currentActive.classList.remove('active') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function addActive (name: string) { |
||||||
|
if (name === 'home') return |
||||||
|
const themeType = verticalIconsPlugin.registry.get('themeModule').api.currentTheme().quality |
||||||
|
const invert = themeType === 'dark' ? 1 : 0 |
||||||
|
const brightness = themeType === 'dark' ? '150' : '0' // should be >100 for icons with color
|
||||||
|
// @ts-ignore
|
||||||
|
const nextActive = iconPanelRef.current.querySelector(`[plugin="${name}"]`) |
||||||
|
if (nextActive) { |
||||||
|
const image = nextActive.querySelector('.remixui_image') |
||||||
|
nextActive.classList.add('active') |
||||||
|
image.style.setProperty('filter', `invert(${invert}) grayscale(1) brightness(${brightness}%)`) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
async function itemContextAction (e: any, name: string, documentation: string) { |
||||||
|
verticalIconsPlugin.appManager.deactivatePlugin(name) |
||||||
|
if (e.target.parentElement.classList.contains('active')) { |
||||||
|
verticalIconsPlugin.select('filePanel') |
||||||
|
} |
||||||
|
verticalIconsPlugin.renderComponent() |
||||||
|
} |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const themeModule = verticalIconsPlugin.registry.get('themeModule').api |
||||||
|
themeModule.events.on('themeChanged', (theme: any) => { |
||||||
|
onThemeChanged(theme.quality) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const themeModule = verticalIconsPlugin.registry.get('themeModule').api |
||||||
|
themeModule.events.on('themeChanged', (theme: any) => { |
||||||
|
onThemeChanged(theme.quality) |
||||||
|
}) |
||||||
|
}, []) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (verticalIconsPlugin.targetProfileForChange && verticalIconsPlugin.targetProfileForChange.udapp) { |
||||||
|
const doWalkThroughEvent = new Event('doWalkThrough') |
||||||
|
document.dispatchEvent(doWalkThroughEvent) |
||||||
|
} |
||||||
|
}, [Object.keys(verticalIconsPlugin.targetProfileForChange).length]) |
||||||
|
|
||||||
|
return ( |
||||||
|
<div id="iconsP" className="h-100"> |
||||||
|
<div className="remixui_icons d-flex flex-column vh-100" ref={iconPanelRef}> |
||||||
|
<Home verticalIconPlugin={verticalIconsPlugin} /> |
||||||
|
<div className={scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight |
||||||
|
? 'remixui_default-icons-container remixui_requiredSection' : 'remixui_requiredSection'}> |
||||||
|
<RequiredSection |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
scrollableRef={scrollableRef} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
<div |
||||||
|
id="remixuiScrollable" |
||||||
|
className={scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight |
||||||
|
? 'remixui_default-icons-container remixui_scrollable-container remixui_scrollbar remixui_hide-scroll' |
||||||
|
: 'remixui_scrollable-container remixui_scrollbar remixui_hide-scroll'} |
||||||
|
ref={scrollableRef} |
||||||
|
> |
||||||
|
<OtherIcons |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
{verticalIconsPlugin.targetProfileForChange && |
||||||
|
Object.keys(verticalIconsPlugin.targetProfileForChange).length ? ( |
||||||
|
<Fragment> |
||||||
|
<Settings |
||||||
|
verticalIconsPlugin={verticalIconsPlugin} |
||||||
|
addActive={addActive} |
||||||
|
removeActive={removeActive} |
||||||
|
itemContextAction={itemContextAction} |
||||||
|
scrollableRef={scrollableRef} |
||||||
|
/> |
||||||
|
</Fragment> |
||||||
|
) : null} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,121 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/ban-ts-comment */ |
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
import React, { Fragment, useEffect, useRef } from 'react' |
||||||
|
import { VerticalIcons } from '../../types/vertical-icons-panel' |
||||||
|
|
||||||
|
export interface VerticalIconsContextMenuProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> { |
||||||
|
pageX: number |
||||||
|
pageY: number |
||||||
|
profileName: string |
||||||
|
links: { Documentation: string, CanDeactivate: boolean } |
||||||
|
canBeDeactivated: boolean |
||||||
|
verticalIconPlugin: VerticalIcons |
||||||
|
hideContextMenu: () => void |
||||||
|
contextMenuAction: (evt: any, profileName: string, documentation: string) => void |
||||||
|
} |
||||||
|
|
||||||
|
interface MenuLinksProps { |
||||||
|
listItems: { Documentation: string, CanDeactivate: boolean } |
||||||
|
hide: () => void |
||||||
|
profileName: string |
||||||
|
canBeDeactivated: boolean |
||||||
|
verticalIconPlugin: VerticalIcons |
||||||
|
ref?: React.MutableRefObject<any> |
||||||
|
toggle: (name: string) => void |
||||||
|
contextMenuAction: (evt: any, profileName: string, documentation: string) => void |
||||||
|
} |
||||||
|
|
||||||
|
interface MenuProps { |
||||||
|
verticalIconsPlugin: VerticalIcons |
||||||
|
profileName: string |
||||||
|
listItems: { Documentation: string, CanDeactivate: boolean } |
||||||
|
hide: () => void |
||||||
|
} |
||||||
|
|
||||||
|
const requiredModules = [ |
||||||
|
'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme', |
||||||
|
'fileManager', 'contentImport', 'blockchain', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons', |
||||||
|
'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider', 'solidity-logic'] |
||||||
|
const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'hardhat-provider'] |
||||||
|
|
||||||
|
function VerticalIconsContextMenu (props: VerticalIconsContextMenuProps) { |
||||||
|
const menuRef = useRef(null) |
||||||
|
useEffect(() => { |
||||||
|
document.addEventListener('click', props.hideContextMenu) |
||||||
|
return () => document.removeEventListener('click', props.hideContextMenu) |
||||||
|
}, []) |
||||||
|
useEffect(() => { |
||||||
|
// @ts-ignore
|
||||||
|
menuRef.current.focus() |
||||||
|
}, []) |
||||||
|
return ( |
||||||
|
<div |
||||||
|
id="menuItemsContainer" |
||||||
|
className="p-1 remixui_verticalIconContextcontainer bg-light shadow border" |
||||||
|
onBlur={props.hideContextMenu} |
||||||
|
style={{ |
||||||
|
left: props.pageX, |
||||||
|
top: props.pageY, |
||||||
|
display: 'block' |
||||||
|
|
||||||
|
}} |
||||||
|
ref={menuRef} |
||||||
|
tabIndex={1} |
||||||
|
> |
||||||
|
<ul id="menuitems"> |
||||||
|
<MenuForLinks |
||||||
|
hide={props.hideContextMenu} |
||||||
|
listItems={props.links} |
||||||
|
profileName={props.profileName} |
||||||
|
canBeDeactivated={props.canBeDeactivated} |
||||||
|
verticalIconPlugin={props.verticalIconPlugin} |
||||||
|
toggle={props.verticalIconPlugin.toggle} |
||||||
|
contextMenuAction={props.contextMenuAction} |
||||||
|
/> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
function MenuForLinks ({ |
||||||
|
listItems, |
||||||
|
hide, |
||||||
|
profileName, |
||||||
|
contextMenuAction |
||||||
|
}: MenuLinksProps) { |
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{listItems.CanDeactivate && !requiredModules.includes(profileName) |
||||||
|
? <li |
||||||
|
id="menuitemdeactivate" |
||||||
|
onClick={(evt) => { |
||||||
|
contextMenuAction(evt, profileName, listItems.Documentation) |
||||||
|
hide() |
||||||
|
}} |
||||||
|
className="remixui_liitem" |
||||||
|
> |
||||||
|
Deactivate |
||||||
|
</li> |
||||||
|
: null |
||||||
|
} |
||||||
|
{(listItems.Documentation && listItems.Documentation.length > 0) && |
||||||
|
<li |
||||||
|
id="menuitemdocumentation" |
||||||
|
className="remixui_liitem" |
||||||
|
> |
||||||
|
<a |
||||||
|
onClick={hide} |
||||||
|
href={listItems.Documentation} |
||||||
|
target="_blank" |
||||||
|
> |
||||||
|
Documentation |
||||||
|
</a> |
||||||
|
</li>} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default VerticalIconsContextMenu |
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"extends": "../../../tsconfig.base.json", |
||||||
|
"compilerOptions": { |
||||||
|
"jsx": "react-jsx", |
||||||
|
"allowJs": true, |
||||||
|
"esModuleInterop": true, |
||||||
|
"allowSyntheticDefaultImports": true, |
||||||
|
"forceConsistentCasingInFileNames": true, |
||||||
|
"strict": true, |
||||||
|
"noImplicitReturns": true, |
||||||
|
"noFallthroughCasesInSwitch": true, |
||||||
|
"resolveJsonModule": true |
||||||
|
}, |
||||||
|
"files": [], |
||||||
|
"include": [], |
||||||
|
"references": [ |
||||||
|
{ |
||||||
|
"path": "./tsconfig.lib.json" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
{ |
||||||
|
"extends": "./tsconfig.json", |
||||||
|
"compilerOptions": { |
||||||
|
"outDir": "../../../dist/out-tsc", |
||||||
|
"types": ["node"], |
||||||
|
"resolveJsonModule": true |
||||||
|
}, |
||||||
|
"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"] |
||||||
|
} |
@ -0,0 +1,110 @@ |
|||||||
|
/* eslint-disable @typescript-eslint/ban-types */ |
||||||
|
/* eslint-disable no-use-before-define */ |
||||||
|
import { Plugin } from '@remixproject/engine/lib/abstract' |
||||||
|
import * as packageJson from '../../../../package.json' |
||||||
|
import * as registry from 'apps/remix-ide/src/global/registry' |
||||||
|
import { RemixAppManager } from '@remix-ui/plugin-manager' |
||||||
|
|
||||||
|
export type Kind = |
||||||
|
| 'fileexplorer' |
||||||
|
| 'compiler' |
||||||
|
| 'udapp' |
||||||
|
| 'testing' |
||||||
|
| 'analysis' |
||||||
|
| 'debugging' |
||||||
|
| 'settings' |
||||||
|
| 'none' |
||||||
|
|
||||||
|
type IconKindType = { |
||||||
|
kind: {} |
||||||
|
} |
||||||
|
|
||||||
|
interface defaultModuleProfile { |
||||||
|
name: string |
||||||
|
displayName: string |
||||||
|
description: string |
||||||
|
version: packageJson.version |
||||||
|
methods: string[] |
||||||
|
} |
||||||
|
|
||||||
|
interface PassedProfile { |
||||||
|
name: string |
||||||
|
displayName: string |
||||||
|
description: string |
||||||
|
version: packageJson.version |
||||||
|
methods: string[] |
||||||
|
icon?: string |
||||||
|
tooltip?: string |
||||||
|
kind?: string |
||||||
|
documentation?: string |
||||||
|
} |
||||||
|
|
||||||
|
interface targetProfileIcons { |
||||||
|
profile: PassedProfile |
||||||
|
} |
||||||
|
export class VerticalIcons extends Plugin<any, any> { |
||||||
|
events: EventEmitter |
||||||
|
appManager: RemixAppManager |
||||||
|
htmlElement: HTMLDivElement |
||||||
|
icons: any |
||||||
|
iconKind: {} |
||||||
|
iconStatus: {} |
||||||
|
defaultProfile: defaultModuleProfile |
||||||
|
targetProfileForChange: any |
||||||
|
targetProfileForRemoval: any |
||||||
|
registry: registry |
||||||
|
keys: string[] |
||||||
|
types: string[] |
||||||
|
renderComponent(): void |
||||||
|
linkContent(profile: any): void |
||||||
|
unlinkContent(profile: any): void |
||||||
|
listenOnStatus(profile: any): void |
||||||
|
activateHome(): void |
||||||
|
/** |
||||||
|
* Add an icon to the map |
||||||
|
* @param {ModuleProfile} profile The profile of the module |
||||||
|
*/ |
||||||
|
addIcon({ kind, name, icon, displayName, tooltip, documentation }: any): void |
||||||
|
/** |
||||||
|
* resolve a classes list for @arg key |
||||||
|
* @param {Object} key |
||||||
|
* @param {Object} type |
||||||
|
*/ |
||||||
|
resolveClasses(key: any, type: any): any |
||||||
|
/** |
||||||
|
* Set a new status for the @arg name |
||||||
|
* @param {String} name |
||||||
|
* @param {Object} status |
||||||
|
*/ |
||||||
|
setIconStatus(name: string, status: any): void |
||||||
|
/** |
||||||
|
* Remove an icon from the map |
||||||
|
* @param {ModuleProfile} profile The profile of the module |
||||||
|
*/ |
||||||
|
removeIcon({ name }: any): void |
||||||
|
/** |
||||||
|
* Remove active for the current activated icons |
||||||
|
*/ |
||||||
|
removeActive(): void |
||||||
|
/** |
||||||
|
* Add active for the new activated icon |
||||||
|
* @param {string} name Name of profile of the module to activate |
||||||
|
*/ |
||||||
|
addActive(name: string): void |
||||||
|
/** |
||||||
|
* Set an icon as active |
||||||
|
* @param {string} name Name of profile of the module to activate |
||||||
|
*/ |
||||||
|
select(name: string): void |
||||||
|
/** |
||||||
|
* Toggles the side panel for plugin |
||||||
|
* @param {string} name Name of profile of the module to activate |
||||||
|
*/ |
||||||
|
toggle(name: string): void |
||||||
|
updateActivations(name: any): void |
||||||
|
onThemeChanged(themeType: any): void |
||||||
|
itemContextMenu(e: any, name: any, documentation: any): Promise<void> |
||||||
|
render(): any |
||||||
|
view: any |
||||||
|
} |
||||||
|
import EventEmitter = require('events') |
Loading…
Reference in new issue