update components and setttings

pull/1671/head
Joseph Izang 3 years ago
parent 1e2dbea7cc
commit 851e0dd59d
  1. 204
      apps/remix-ide/src/app/components/vertical-icons.js
  2. 12
      libs/remix-ui/vertical-icons-panel/.babelrc
  3. 35
      libs/remix-ui/vertical-icons-panel/.eslintrc.json
  4. 5
      libs/remix-ui/vertical-icons-panel/.prettierrc
  5. 14
      libs/remix-ui/vertical-icons-panel/src/lib/components/BasicLogo.tsx
  6. 26
      libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx
  7. 114
      libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx
  8. 15
      libs/remix-ui/vertical-icons-panel/src/lib/components/OtherIcons.tsx
  9. 15
      libs/remix-ui/vertical-icons-panel/src/lib/components/Settings.tsx
  10. 109
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css
  11. 0
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.module.css
  12. 422
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx
  13. 113
      libs/remix-ui/vertical-icons-panel/src/lib/vertical-icons-context-menu.tsx
  14. 3
      libs/remix-ui/vertical-icons-panel/tsconfig.json
  15. 3
      libs/remix-ui/vertical-icons-panel/tsconfig.lib.json
  16. 112
      libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel.d.ts
  17. 57
      package-lock.json

@ -1,13 +1,18 @@
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
// eslint-disable-next-line no-unused-vars
import { basicLogo } from '../ui/svgLogo' import { basicLogo } from '../ui/svgLogo'
import ReactDOM from 'react-dom'
import React from 'react' // eslint-disable-line
// eslint-disable-next-line no-unused-vars
import { RemixUiVerticalIconsPanel } from '@remix-ui/vertical-icons-panel'
var yo = require('yo-yo') var yo = require('yo-yo')
var csjs = require('csjs-inject') var csjs = require('csjs-inject')
var helper = require('../../lib/helper') var helper = require('../../lib/helper')
const globalRegistry = require('../../global/registry') const globalRegistry = require('../../global/registry')
const contextMenu = require('../ui/contextMenu') // const contextMenu = require('../ui/contextMenu')
const { Plugin } = require('@remixproject/engine') const { Plugin } = require('@remixproject/engine')
const EventEmitter = require('events') const EventEmitter = require('events')
let VERTICALMENU_HANDLE // let VERTICALMENU_HANDLE
const profile = { const profile = {
name: 'menuicons', name: 'menuicons',
@ -23,23 +28,39 @@ export class VerticalIcons extends Plugin {
super(profile) super(profile)
this.events = new EventEmitter() this.events = new EventEmitter()
this.appManager = appManager this.appManager = appManager
this.htmlElement = document.createElement('div')
this.htmlElement.setAttribute('id', 'icon-panel')
this.icons = {} this.icons = {}
this.iconKind = {} this.iconKind = {}
this.iconStatus = {} this.iconStatus = {}
this.defaultProfile = profile
this.targetProfileForChange = {}
this.targetProfileForRemoval = {}
this.registry = globalRegistry
}
renderComponent () {
ReactDOM.render(
<RemixUiVerticalIconsPanel
verticalIconsPlugin={this}
/>,
this.htmlElement)
}
const themeModule = globalRegistry.get('themeModule').api onActivation () {
themeModule.events.on('themeChanged', (theme) => { this.renderComponent()
this.onThemeChanged(theme.quality)
})
} }
linkContent (profile) { linkContent (profile) {
if (!profile.icon) return if (!profile.icon) return
this.addIcon(profile) if (!profile.kind) profile.kind = 'none'
this.targetProfileForChange[profile.name] = profile
this.listenOnStatus(profile) this.listenOnStatus(profile)
this.renderComponent()
} }
unlinkContent (profile) { unlinkContent (profile) {
this.targetProfileForRemoval = profile
this.removeIcon(profile) this.removeIcon(profile)
} }
@ -60,55 +81,6 @@ export class VerticalIcons extends Plugin {
this.on(profile.name, 'statusChanged', this.iconStatus[profile.name]) this.on(profile.name, 'statusChanged', this.iconStatus[profile.name])
} }
/**
* Add an icon to the map
* @param {ModuleProfile} profile The profile of the module
*/
addIcon ({ kind, name, icon, displayName, tooltip, documentation }) {
let title = (tooltip || displayName || name)
title = title.replace(/^\w/, c => c.toUpperCase())
this.icons[name] = yo`
<div
class="${css.icon} m-2"
onclick="${() => { this.toggle(name) }}"
plugin="${name}"
title="${title}"
oncontextmenu="${(e) => this.itemContextMenu(e, name, documentation)}"
data-id="verticalIconsKind${name}"
id="verticalIconsKind${name}"
>
<img class="image" src="${icon}" alt="${name}" />
</div>`
this.iconKind[kind || 'none'].appendChild(this.icons[name])
}
/**
* resolve a classes list for @arg key
* @param {Object} key
* @param {Object} type
*/
resolveClasses (key, type) {
let classes = css.status
switch (key) {
case 'succeed':
classes += ' fas fa-check-circle text-' + type + ' ' + css.statusCheck
break
case 'edited':
classes += ' fas fa-sync text-' + type + ' ' + css.statusCheck
break
case 'loading':
classes += ' fas fa-spinner text-' + type + ' ' + css.statusCheck
break
case 'failed':
classes += ' fas fa-exclamation-triangle text-' + type + ' ' + css.statusCheck
break
default: {
classes += ' badge badge-pill badge-' + type
}
}
return classes
}
/** /**
* Set a new status for the @arg name * Set a new status for the @arg name
* @param {String} name * @param {String} name
@ -137,7 +109,7 @@ export class VerticalIcons extends Plugin {
const title = helper.checkSpecialChars(status.title) ? '' : status.title const title = helper.checkSpecialChars(status.title) ? '' : status.title
el.appendChild(yo`<i el.appendChild(yo`<i
title="${title}" title="${title}"
class="${this.resolveClasses(key, type)}" class="${this.resolveClasses(key, type)}"
aria-hidden="true" aria-hidden="true"
> >
@ -152,41 +124,8 @@ export class VerticalIcons extends Plugin {
* @param {ModuleProfile} profile The profile of the module * @param {ModuleProfile} profile The profile of the module
*/ */
removeIcon ({ kind, name }) { removeIcon ({ kind, name }) {
if (this.icons[name]) this.iconKind[kind || 'none'].removeChild(this.icons[name]) if (this.targetProfileForChange[name]) delete this.targetProfileForChange[name]
} this.renderComponent()
/**
* Remove active for the current activated icons
*/
removeActive () {
// reset filters
const images = this.view.querySelectorAll('.image')
images.forEach(function (im) {
im.style.setProperty('filter', 'invert(0.5)')
})
// remove active
const currentActive = this.view.querySelector('.active')
if (currentActive) {
currentActive.classList.remove('active')
}
}
/**
* Add active for the new activated icon
* @param {string} name Name of profile of the module to activate
*/
addActive (name) {
if (name === 'home') return
const themeType = globalRegistry.get('themeModule').api.currentTheme().quality
const invert = themeType === 'dark' ? 1 : 0
const brightness = themeType === 'dark' ? '150' : '0' // should be >100 for icons with color
const nextActive = this.view.querySelector(`[plugin="${name}"]`)
if (nextActive) {
const image = nextActive.querySelector('.image')
nextActive.classList.add('active')
image.style.setProperty('filter', `invert(${invert}) grayscale(1) brightness(${brightness}%)`)
}
} }
/** /**
@ -194,7 +133,6 @@ export class VerticalIcons extends Plugin {
* @param {string} name Name of profile of the module to activate * @param {string} name Name of profile of the module to activate
*/ */
select (name) { select (name) {
this.updateActivations(name)
// TODO: Only keep `this.emit` (issue#2210) // TODO: Only keep `this.emit` (issue#2210)
this.emit('showContent', name) this.emit('showContent', name)
this.events.emit('showContent', name) this.events.emit('showContent', name)
@ -205,89 +143,13 @@ export class VerticalIcons extends Plugin {
* @param {string} name Name of profile of the module to activate * @param {string} name Name of profile of the module to activate
*/ */
toggle (name) { toggle (name) {
this.updateActivations(name) // // TODO: Only keep `this.emit` (issue#2210)
// TODO: Only keep `this.emit` (issue#2210)
this.emit('toggleContent', name) this.emit('toggleContent', name)
this.events.emit('toggleContent', name) this.events.emit('toggleContent', name)
} }
updateActivations (name) {
this.removeActive()
this.addActive(name)
}
onThemeChanged (themeType) {
const invert = themeType === 'dark' ? 1 : 0
const active = this.view.querySelector('.active')
if (active) {
const image = active.querySelector('.image')
image.style.setProperty('filter', `invert(${invert})`)
}
}
async itemContextMenu (e, name, documentation) {
const actions = {}
if (await this.appManager.canDeactivatePlugin(profile, { name })) {
actions.Deactivate = () => {
// this.call('manager', 'deactivatePlugin', name)
this.appManager.deactivatePlugin(name)
if (e.target.parentElement.classList.contains('active')) {
this.select('filePanel')
}
}
}
const links = {}
if (documentation) {
links.Documentation = documentation
}
if (Object.keys(actions).length || Object.keys(links).length) {
VERTICALMENU_HANDLE && VERTICALMENU_HANDLE.hide(null, true)
VERTICALMENU_HANDLE = contextMenu(e, actions, links)
}
e.preventDefault()
e.stopPropagation()
}
render () { render () {
const home = yo` return this.htmlElement
<div
class="m-1 mt-2 ${css.homeIcon}"
onclick="${async () => {
await this.appManager.activatePlugin('home')
this.call('tabs', 'focus', 'home')
}}"
plugin="home" title="Home"
data-id="verticalIconsHomeIcon"
id="verticalIconsHomeIcon"
>
${basicLogo()}
</div>
`
this.iconKind.fileexplorer = yo`<div id='fileExplorerIcons' data-id="verticalIconsFileExplorerIcons"></div>`
this.iconKind.compiler = yo`<div id='compileIcons'></div>`
this.iconKind.udapp = yo`<div id='runIcons'></div>`
this.iconKind.testing = yo`<div id='testingIcons'></div>`
this.iconKind.analysis = yo`<div id='analysisIcons'></div>`
this.iconKind.debugging = yo`<div id='debuggingIcons' data-id="verticalIconsDebuggingIcons"></div>`
this.iconKind.none = yo`<div id='otherIcons'></div>`
this.iconKind.settings = yo`<div id='settingsIcons' data-id="verticalIconsSettingsIcons"></div>`
this.view = yo`
<div class="h-100">
<div class=${css.icons}>
${home}
${this.iconKind.fileexplorer}
${this.iconKind.compiler}
${this.iconKind.udapp}
${this.iconKind.testing}
${this.iconKind.analysis}
${this.iconKind.debugging}
${this.iconKind.none}
${this.iconKind.settings}
</div>
</div>
`
return this.view
} }
} }

@ -1,12 +1,4 @@
{ {
"presets": [ "presets": ["@nrwl/react/babel"],
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": [] "plugins": []
} }

@ -1,18 +1,19 @@
{ {
"extends": ["plugin:@nrwl/nx/react", "../../../.eslintrc.json"], "env": {
"ignorePatterns": ["!**/*"], "browser": true,
"overrides": [ "es6": true
{ },
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "extends": ["../../../.eslintrc"],
"rules": {} "globals": {
}, "Atomics": "readonly",
{ "SharedArrayBuffer": "readonly"
"files": ["*.ts", "*.tsx"], },
"rules": {} "parserOptions": {
}, "ecmaVersion": 11,
{ "sourceType": "module"
"files": ["*.js", "*.jsx"], },
"rules": {} "rules": {
} "no-unused-vars": "off",
] "@typescript-eslint/no-unused-vars": "error"
} }
}

@ -0,0 +1,5 @@
{
"tabWidth": 2,
"singleQuote": true,
"semi": false
}

@ -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,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="m-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,114 @@
/* 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, useRef, useState } from 'react'
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// import helper from 'apps/remix-ide/src/lib/helper'
interface IconProps {
verticalIconPlugin: VerticalIcons
kind: string
name: string
icon: string
displayName: string
tooltip: string
documentation: string
contextMenuAction: (evt: any, profileName: string, documentation: string) => void
addActive: (profileName: string) => void
removeActive: () => void
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function Icon ({
// eslint-disable-next-line @typescript-eslint/no-unused-vars
kind,
name,
icon,
displayName,
tooltip,
documentation,
verticalIconPlugin,
contextMenuAction,
addActive,
removeActive
}: IconProps) {
const [title] = useState(() => {
const temp = tooltip || displayName || name
return temp.replace(/^\w/, word => 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(null)
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="remixui_icon m-2"
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)
}}
onBlur={closeContextMenu}
data-id={`verticalIconsKind${name}`}
id={`verticalIconsKind${name}`}
ref={iconRef}
>
<img className="remixui_image" src={icon} alt={name} />
</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,15 @@
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { ReactNode } from 'react'
interface OtherIconsProps {
children: ReactNode
}
function OtherIcons ({ children }: OtherIconsProps) {
return (
<div id="otherIcons">{ children }</div>
)
}
export default OtherIcons

@ -0,0 +1,15 @@
/* eslint-disable no-use-before-define */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React, { ReactNode } from 'react'
interface SettingsProps {
children: ReactNode
}
function Settings ({ children }: SettingsProps) {
return (
<div id="settingsIcons" data-id="vertialIconsSettingsIcons">{ children }</div>
)
}
export default Settings

@ -0,0 +1,109 @@
.remixui_homeIcon {
display: block;
width: 42px;
height: 42px;
margin-bottom: 20px;
cursor: pointer;
}
.remixui_homeIcon svg path {
fill: var(--primary);
}
.remixui_homeIcon svg polygon {
fill: var(--primary);
}
.remixui_icons {
}
.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'] {
position: absolute;
bottom: 0;
}
.remixui_status {
position: absolute;
bottom: 0;
right: 0;
}
.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_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 {
max-height: 500px;
}
.remixui_scrollbar::-webkit-scrollbar { /* Chrome, Safari and other Webkit browsers*/
display: none;
}
.remixui_hide-scroll {
overflow-x: 'hidden';
}
.remixui_default-icons-container {
border-bottom: 1px solid #3f4455;
}
.remixui_icon-chevron {
z-index: 1000;
}
.remixui_icon-chevron {
z-index: 1000;
}
.remixui_icon-chevron {
z-index: 1000;
}
#menuitems {
list-style: none;
margin: 0px;
}

@ -1,16 +1,416 @@
import './remix-ui-vertical-icons-panel.module.css'; /* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, {
Fragment,
useEffect,
useRef
} from 'react'
/* eslint-disable-next-line */ import './remix-ui-vertical-icons-panel.css'
export interface RemixUiVerticalIconsPanelProps {} import OtherIcons from './components/OtherIcons'
import { VerticalIcons } from '../../types/vertical-icons-panel'
import Home from './components/Home'
import Icon from './components/Icon'
import Settings from './components/Settings'
export interface RemixUiVerticalIconsPanelProps {
verticalIconsPlugin: VerticalIcons
}
let scrollHeight: any
let clientHeight: any
export function RemixUiVerticalIconsPanel ({
verticalIconsPlugin
}: RemixUiVerticalIconsPanelProps) {
const scrollableRef = useRef<any>()
const iconPanelRef = useRef<any>()
// @ts-ignore
// scrollHeight = scrollableRef.current!.scrollHeight
// // @ts-ignore
// clientHeight = scrollableRef.current!.clientHeight
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(() => {
console.log('usefRef for scrolling', scrollableRef)
})
useEffect(() => {
const themeModule = verticalIconsPlugin.registry.get('themeModule').api
themeModule.events.on('themeChanged', (theme: any) => {
onThemeChanged(theme.quality)
})
}, [])
useEffect(() => {
// @ts-ignore
scrollHeight = scrollableRef.current.scrollHeight
// @ts-ignore
clientHeight = scrollableRef.current.clientHeight
console.log('scrollHeight ', scrollHeight)
}, [])
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)
})
}, [])
export function RemixUiVerticalIconsPanel(
props: RemixUiVerticalIconsPanelProps
) {
return ( return (
<div> <div id="iconsP" className="h-100">
<h1>Welcome to remix-ui-vertical-icons-panel!</h1> <div className="remixui_icons" ref={iconPanelRef}>
<div className="remixui_default-icons-container">
<Home verticalIconPlugin={verticalIconsPlugin} />
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p !== 'settings')
.filter(p => p !== 'pluginManager')
.filter(p => p === 'filePanel')
.map(p => (
<div id="fileExplorerIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
} data-id="verticalIconsFileExplorerIcons">
<Icon
kind={verticalIconsPlugin.targetProfileForChange[p].kind}
displayName={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={verticalIconsPlugin.targetProfileForChange[p].icon}
name={verticalIconsPlugin.targetProfileForChange[p].name}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
/>
</div>
))
: null}
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p !== 'settings')
.filter(p => p !== 'pluginManager')
.filter(p => p === 'solidity')
.map(p => (
<div id="compileIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
kind={verticalIconsPlugin.targetProfileForChange[p].kind}
displayName={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={verticalIconsPlugin.targetProfileForChange[p].icon}
name={verticalIconsPlugin.targetProfileForChange[p].name}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p !== 'settings')
.filter(p => p !== 'pluginManager')
.filter(p => p === 'udapp')
.map(p => (
<div id="compileIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
kind={verticalIconsPlugin.targetProfileForChange[p].kind}
displayName={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={verticalIconsPlugin.targetProfileForChange[p].icon}
name={verticalIconsPlugin.targetProfileForChange[p].name}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p !== 'settings')
.filter(p => p !== 'pluginManager')
.filter(p => p === 'solidityStaticAnalysis')
.map(p => (
<div id="analysisIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
kind={verticalIconsPlugin.targetProfileForChange[p].kind}
displayName={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={verticalIconsPlugin.targetProfileForChange[p].icon}
name={verticalIconsPlugin.targetProfileForChange[p].name}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p !== 'settings')
.filter(p => p !== 'pluginManager')
.filter(p => p === 'debugger')
.map(p => (
<div id="debuggingIcons" data-id="verticalIconsDebuggingIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
kind={verticalIconsPlugin.targetProfileForChange[p].kind}
displayName={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={verticalIconsPlugin.targetProfileForChange[p].icon}
name={verticalIconsPlugin.targetProfileForChange[p].name}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
</div>
<div
id="remixuiScrollable"
className="remixui_scrollable-container remixui_scrollbar remixui_hide-scroll"
ref={scrollableRef}
>
<OtherIcons>
{Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p !== 'settings')
.filter(p => p !== 'pluginManager')
.filter(p => p !== 'filePanel')
.filter(p => p !== 'debugger')
.filter(p => p !== 'compiler')
.filter(p => p !== 'solidity')
.filter(p => p !== 'udapp')
.filter(p => p !== 'testing')
.filter(p => p !== 'solidityStaticAnalysis')
.map(p => (
<Icon
kind={verticalIconsPlugin.targetProfileForChange[p].kind}
displayName={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p].documentation
}
icon={verticalIconsPlugin.targetProfileForChange[p].icon}
name={verticalIconsPlugin.targetProfileForChange[p].name}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
))}
</OtherIcons>
</div>
{scrollableRef.current && scrollableRef.current!.scrollHeight > clientHeight
? <i className="fa fa-chevron-double-down remixui_icon-chevron m-3"></i>
: null
}
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length ? (
<Fragment>
<Settings>
<>
{Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'pluginManager')
.map(p => (
<Icon
kind={
verticalIconsPlugin.targetProfileForChange[p].kind
}
displayName={
verticalIconsPlugin.targetProfileForChange[p]
.displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={
verticalIconsPlugin.targetProfileForChange[p].icon
}
name={
verticalIconsPlugin.targetProfileForChange[p].name
}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p]
.displayName
}
/>
))}
{Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'settings')
.map(p => (
<Icon
kind={
verticalIconsPlugin.targetProfileForChange[p].kind
}
displayName={
verticalIconsPlugin.targetProfileForChange[p]
.displayName
}
documentation={
verticalIconsPlugin.targetProfileForChange[p]
.documentation
}
icon={
verticalIconsPlugin.targetProfileForChange[p].icon
}
name={
verticalIconsPlugin.targetProfileForChange[p].name
}
tooltip={
verticalIconsPlugin.targetProfileForChange[p].tooltip
}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p]
.displayName
}
/>
))}
</>
</Settings>
</Fragment>
) : null}
</div>
</div> </div>
); )
} }
export default RemixUiVerticalIconsPanel;

@ -0,0 +1,113 @@
/* 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> {
// actions: action[]
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
}
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}
>
<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 &&
<li
id="menuitemdeactivate"
onClick={(evt) => {
contextMenuAction(evt, profileName, listItems.Documentation)
hide()
}}
className="remixui_liitem"
>
Deactivate
</li>}
{(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

@ -8,7 +8,8 @@
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"strict": true, "strict": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true,
"resolveJsonModule": true
}, },
"files": [], "files": [],
"include": [], "include": [],

@ -2,7 +2,8 @@
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../../../dist/out-tsc", "outDir": "../../../dist/out-tsc",
"types": ["node"] "types": ["node"],
"resolveJsonModule": true
}, },
"files": [ "files": [
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts", "../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",

@ -0,0 +1,112 @@
/* 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> {
// constructor(appManager: RemixAppManager)
events: EventEmitter
appManager: RemixAppManager
htmlElement: HTMLDivElement
icons: {
name: any
}
iconKind: {}
iconStatus: {}
defaultProfile: defaultModuleProfile
targetProfileForChange: any
targetProfileForRemoval: any
registry: registry
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({ kind, 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')

57
package-lock.json generated

@ -1517,6 +1517,14 @@
"requires": { "requires": {
"core-js": "^2.6.5", "core-js": "^2.6.5",
"regenerator-runtime": "^0.13.4" "regenerator-runtime": "^0.13.4"
},
"dependencies": {
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"dev": true
}
} }
}, },
"@babel/preset-env": { "@babel/preset-env": {
@ -12685,6 +12693,12 @@
"regenerator-runtime": "^0.11.0" "regenerator-runtime": "^0.11.0"
}, },
"dependencies": { "dependencies": {
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"dev": true
},
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.11.1", "version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
@ -15409,10 +15423,9 @@
} }
}, },
"core-js": { "core-js": {
"version": "2.6.12", "version": "3.18.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.2.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "integrity": "sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ=="
"dev": true
}, },
"core-js-compat": { "core-js-compat": {
"version": "3.19.1", "version": "3.19.1",
@ -38943,9 +38956,9 @@
} }
}, },
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.13.9", "version": "0.13.7",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
}, },
"regenerator-transform": { "regenerator-transform": {
"version": "0.14.5", "version": "0.14.5",
@ -41476,6 +41489,36 @@
"internal-slot": "^1.0.3", "internal-slot": "^1.0.3",
"regexp.prototype.flags": "^1.3.1", "regexp.prototype.flags": "^1.3.1",
"side-channel": "^1.0.4" "side-channel": "^1.0.4"
},
"dependencies": {
"es-abstract": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
"integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
"dev": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"get-intrinsic": "^1.1.1",
"get-symbol-description": "^1.0.0",
"has": "^1.0.3",
"has-symbols": "^1.0.2",
"internal-slot": "^1.0.3",
"is-callable": "^1.2.4",
"is-negative-zero": "^2.0.1",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.1",
"is-string": "^1.0.7",
"is-weakref": "^1.0.1",
"object-inspect": "^1.11.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"string.prototype.trimend": "^1.0.4",
"string.prototype.trimstart": "^1.0.4",
"unbox-primitive": "^1.0.1"
}
}
} }
}, },
"string.prototype.padend": { "string.prototype.padend": {

Loading…
Cancel
Save