move compile tab styles to its own file refactor: simplify some methods; transform functions into blocks move events to its own method move compiler and compiler import out of _dependencies simplify passing registry to compile tab move queryParams & remove _dependencies var refactor optimize param move to compile tab logic extract code for compiler container into a separate module remove unused method move compiler imports logic out of the UIpull/1/head
parent
454778e474
commit
fc29644f50
@ -0,0 +1,98 @@ |
|||||||
|
const async = require('async') |
||||||
|
var remixTests = require('remix-tests') |
||||||
|
var Compiler = require('remix-solidity').Compiler |
||||||
|
var CompilerImport = require('../../compiler/compiler-imports') |
||||||
|
|
||||||
|
// TODO: move this to the UI
|
||||||
|
const addTooltip = require('../../ui/tooltip') |
||||||
|
|
||||||
|
class CompileTab { |
||||||
|
|
||||||
|
constructor (queryParams, fileManager, editor, config, fileProviders) { |
||||||
|
this.queryParams = queryParams |
||||||
|
this.compilerImport = new CompilerImport() |
||||||
|
this.compiler = new Compiler((url, cb) => this.importFileCb(url, cb)) |
||||||
|
this.fileManager = fileManager |
||||||
|
this.editor = editor |
||||||
|
this.config = config |
||||||
|
this.fileProviders = fileProviders |
||||||
|
} |
||||||
|
|
||||||
|
init () { |
||||||
|
this.optimize = this.queryParams.get().optimize |
||||||
|
this.optimize = this.optimize === 'true' |
||||||
|
this.queryParams.update({ optimize: this.optimize }) |
||||||
|
this.compiler.setOptimize(this.optimize) |
||||||
|
} |
||||||
|
|
||||||
|
setOptimize (newOptimizeValue) { |
||||||
|
this.optimize = newOptimizeValue |
||||||
|
this.queryParams.update({ optimize: this.optimize }) |
||||||
|
this.compiler.setOptimize(this.optimize) |
||||||
|
} |
||||||
|
|
||||||
|
runCompiler () { |
||||||
|
this.fileManager.saveCurrentFile() |
||||||
|
this.editor.clearAnnotations() |
||||||
|
var currentFile = this.config.get('currentFile') |
||||||
|
if (!currentFile && !/.(.sol)$/.exec(currentFile)) return |
||||||
|
// only compile *.sol file.
|
||||||
|
var target = currentFile |
||||||
|
var sources = {} |
||||||
|
var provider = this.fileManager.fileProviderOf(currentFile) |
||||||
|
if (!provider) return console.log('cannot compile ' + currentFile + '. Does not belong to any explorer') |
||||||
|
provider.get(target, (error, content) => { |
||||||
|
if (error) return console.log(error) |
||||||
|
sources[target] = { content } |
||||||
|
this.compiler.compile(sources, target) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
importExternal (url, cb) { |
||||||
|
this.compilerImport.import(url, |
||||||
|
|
||||||
|
// TODO: move to an event that is generated, the UI shouldn't be here
|
||||||
|
(loadingMsg) => { addTooltip(loadingMsg) }, |
||||||
|
(error, content, cleanUrl, type, url) => { |
||||||
|
if (error) return cb(error) |
||||||
|
|
||||||
|
if (this._deps.fileProviders[type]) { |
||||||
|
this._deps.fileProviders[type].addReadOnly(cleanUrl, content, url) |
||||||
|
} |
||||||
|
cb(null, content) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
importFileCb (url, filecb) { |
||||||
|
if (url.indexOf('/remix_tests.sol') !== -1) return filecb(null, remixTests.assertLibCode) |
||||||
|
|
||||||
|
var provider = this._deps.fileManager.fileProviderOf(url) |
||||||
|
if (provider) { |
||||||
|
if (provider.type === 'localhost' && !provider.isConnected()) { |
||||||
|
return filecb(`file provider ${provider.type} not available while trying to resolve ${url}`) |
||||||
|
} |
||||||
|
return provider.exists(url, (error, exist) => { |
||||||
|
if (error) return filecb(error) |
||||||
|
if (exist) { |
||||||
|
return provider.get(url, filecb) |
||||||
|
} |
||||||
|
this.importExternal(url, filecb) |
||||||
|
}) |
||||||
|
} |
||||||
|
if (this.compilerImport.isRelativeImport(url)) { |
||||||
|
// try to resolve localhost modules (aka truffle imports)
|
||||||
|
var splitted = /([^/]+)\/(.*)$/g.exec(url) |
||||||
|
return async.tryEach([ |
||||||
|
(cb) => { this.importFileCb('localhost/installed_contracts/' + url, cb) }, |
||||||
|
(cb) => { if (!splitted) { cb('URL not parseable: ' + url) } else { this.importFileCb('localhost/installed_contracts/' + splitted[1] + '/contracts/' + splitted[2], cb) } }, |
||||||
|
(cb) => { this.importFileCb('localhost/node_modules/' + url, cb) }, |
||||||
|
(cb) => { if (!splitted) { cb('URL not parseable: ' + url) } else { this.importFileCb('localhost/node_modules/' + splitted[1] + '/contracts/' + splitted[2], cb) } }], |
||||||
|
(error, result) => { filecb(error, result) } |
||||||
|
) |
||||||
|
} |
||||||
|
this.importExternal(url, filecb) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
module.exports = CompileTab |
@ -0,0 +1,227 @@ |
|||||||
|
/* global Worker */ |
||||||
|
const yo = require('yo-yo') |
||||||
|
var minixhr = require('minixhr') |
||||||
|
var helper = require('../../../lib/helper') |
||||||
|
const addTooltip = require('../../ui/tooltip') |
||||||
|
|
||||||
|
const styleGuide = require('../../ui/styles-guide/theme-chooser') |
||||||
|
const styles = styleGuide.chooser() |
||||||
|
var css = require('../styles/compile-tab-styles') |
||||||
|
|
||||||
|
class CompilerContainer { |
||||||
|
|
||||||
|
constructor (compileTabLogic, editor, config, queryParams) { |
||||||
|
this._view = {} |
||||||
|
this.compileTabLogic = compileTabLogic |
||||||
|
this.editor = editor |
||||||
|
this.config = config |
||||||
|
this.queryParams = queryParams |
||||||
|
|
||||||
|
this.data = { |
||||||
|
hideWarnings: config.get('hideWarnings') || false, |
||||||
|
autoCompile: config.get('autoCompile'), |
||||||
|
compileTimeout: null, |
||||||
|
timeout: 300, |
||||||
|
allversions: null, |
||||||
|
selectedVersion: null, |
||||||
|
defaultVersion: 'soljson-v0.5.1+commit.c8a2cb62.js', // this default version is defined: in makeMockCompiler (for browser test) and in package.json (downloadsolc_root) for the builtin compiler
|
||||||
|
baseurl: 'https://solc-bin.ethereum.org/bin' |
||||||
|
} |
||||||
|
|
||||||
|
this.listenToEvents() |
||||||
|
} |
||||||
|
|
||||||
|
listenToEvents () { |
||||||
|
this.editor.event.register('contentChanged', this.scheduleCompilation.bind(this)) |
||||||
|
this.editor.event.register('sessionSwitched', this.scheduleCompilation.bind(this)) |
||||||
|
|
||||||
|
this.compileTabLogic.compiler.event.register('compilationDuration', (speed) => { |
||||||
|
if (!this._view.warnCompilationSlow) return |
||||||
|
if (speed > 1000) { |
||||||
|
const msg = `Last compilation took ${speed}ms. We suggest to turn off autocompilation.` |
||||||
|
this._view.warnCompilationSlow.setAttribute('title', msg) |
||||||
|
this._view.warnCompilationSlow.style.visibility = 'visible' |
||||||
|
} else { |
||||||
|
this._view.warnCompilationSlow.style.visibility = 'hidden' |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
this.editor.event.register('contentChanged', () => { |
||||||
|
if (!this._view.compileIcon) return |
||||||
|
this._view.compileIcon.classList.add(`${css.bouncingIcon}`) // @TODO: compileView tab
|
||||||
|
}) |
||||||
|
|
||||||
|
this.compileTabLogic.compiler.event.register('loadingCompiler', () => { |
||||||
|
if (!this._view.compileIcon) return |
||||||
|
this._view.compileIcon.classList.add(`${css.spinningIcon}`) |
||||||
|
this._view.warnCompilationSlow.style.visibility = 'hidden' |
||||||
|
this._view.compileIcon.setAttribute('title', 'compiler is loading, please wait a few moments.') |
||||||
|
}) |
||||||
|
|
||||||
|
this.compileTabLogic.compiler.event.register('compilationStarted', () => { |
||||||
|
if (!this._view.compileIcon) return |
||||||
|
this._view.compileIcon.classList.remove(`${css.bouncingIcon}`) |
||||||
|
this._view.compileIcon.classList.add(`${css.spinningIcon}`) |
||||||
|
this._view.compileIcon.setAttribute('title', 'compiling...') |
||||||
|
}) |
||||||
|
|
||||||
|
this.compileTabLogic.compiler.event.register('compilerLoaded', () => { |
||||||
|
if (!this._view.compileIcon) return |
||||||
|
this._view.compileIcon.classList.remove(`${css.spinningIcon}`) |
||||||
|
this._view.compileIcon.setAttribute('title', '') |
||||||
|
}) |
||||||
|
|
||||||
|
this.compileTabLogic.compiler.event.register('compilationFinished', (success, data, source) => { |
||||||
|
if (!this._view.compileIcon) return |
||||||
|
this._view.compileIcon.style.color = styles.colors.black |
||||||
|
this._view.compileIcon.classList.remove(`${css.spinningIcon}`) |
||||||
|
this._view.compileIcon.classList.remove(`${css.bouncingIcon}`) |
||||||
|
this._view.compileIcon.setAttribute('title', 'idle') |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
this.compileTabLogic.compiler.event.register('compilerLoaded', (version) => this.setVersionText(version)) |
||||||
|
this.fetchAllVersion((allversions, selectedVersion) => { |
||||||
|
this.data.allversions = allversions |
||||||
|
this.data.selectedVersion = selectedVersion |
||||||
|
if (this._view.versionSelector) this._updateVersionSelector() |
||||||
|
}) |
||||||
|
|
||||||
|
this._view.warnCompilationSlow = yo`<i title="Compilation Slow" style="visibility:hidden" class="${css.warnCompilationSlow} fa fa-exclamation-triangle" aria-hidden="true"></i>` |
||||||
|
this._view.compileIcon = yo`<i class="fa fa-refresh ${css.icon}" aria-hidden="true"></i>` |
||||||
|
this._view.compileButton = yo`<div class="${css.compileButton}" onclick=${this.compile.bind(this)} id="compile" title="Compile source code">${this._view.compileIcon} Start to compile (Ctrl-S)</div>` |
||||||
|
this._view.autoCompile = yo`<input class="${css.autocompile}" onchange=${this.updateAutoCompile.bind(this)} id="autoCompile" type="checkbox" title="Auto compile">` |
||||||
|
this._view.hideWarningsBox = yo`<input class="${css.autocompile}" onchange=${this.hideWarnings.bind(this)} id="hideWarningsBox" type="checkbox" title="Hide warnings">` |
||||||
|
if (this.data.autoCompile) this._view.autoCompile.setAttribute('checked', '') |
||||||
|
if (this.data.hideWarnings) this._view.hideWarningsBox.setAttribute('checked', '') |
||||||
|
|
||||||
|
this._view.optimize = yo`<input onchange=${this.onchangeOptimize.bind(this)} id="optimize" type="checkbox">` |
||||||
|
if (this.compileTabLogic.optimize) this._view.optimize.setAttribute('checked', '') |
||||||
|
|
||||||
|
this._view.versionSelector = yo` |
||||||
|
<select onchange=${this.onchangeLoadVersion.bind(this)} class="${css.select}" id="versionSelector" disabled> |
||||||
|
<option disabled selected>Select new compiler version</option> |
||||||
|
</select>` |
||||||
|
this._view.version = yo`<span id="version"></span>` |
||||||
|
|
||||||
|
this._view.compileContainer = yo` |
||||||
|
<div class="${css.compileContainer}"> |
||||||
|
<div class="${css.info}"> |
||||||
|
<span>Current version:</span> ${this._view.version} |
||||||
|
<div class="${css.crow}"> |
||||||
|
${this._view.versionSelector} |
||||||
|
</div> |
||||||
|
<div class="${css.compileButtons}"> |
||||||
|
<div class=${css.checkboxes}> |
||||||
|
<div class="${css.autocompileContainer}"> |
||||||
|
${this._view.autoCompile} |
||||||
|
<label for="autoCompile" class="${css.autocompileText}">Auto compile</label> |
||||||
|
</div> |
||||||
|
<div class="${css.optimizeContainer}"> |
||||||
|
<div>${this._view.optimize}</div> |
||||||
|
<label for="optimize" class="${css.checkboxText}">Enable Optimization</label> |
||||||
|
</div> |
||||||
|
<div class=${css.hideWarningsContainer}> |
||||||
|
${this._view.hideWarningsBox} |
||||||
|
<label for="hideWarningsBox" class="${css.autocompileText}">Hide warnings</label> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
${this._view.compileButton} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div>` |
||||||
|
|
||||||
|
return this._view.compileContainer |
||||||
|
} |
||||||
|
|
||||||
|
updateAutoCompile (event) { |
||||||
|
this.config.set('autoCompile', this._view.autoCompile.checked) |
||||||
|
} |
||||||
|
|
||||||
|
compile (event) { |
||||||
|
this.compileTabLogic.runCompiler() |
||||||
|
} |
||||||
|
|
||||||
|
hideWarnings (event) { |
||||||
|
this.config.set('hideWarnings', this._view.hideWarningsBox.checked) |
||||||
|
this.compile() |
||||||
|
} |
||||||
|
|
||||||
|
onchangeOptimize () { |
||||||
|
this.compileTabLogic.setOptimize(!!this._view.optimize.checked) |
||||||
|
this.compileTabLogic.runCompiler() |
||||||
|
} |
||||||
|
|
||||||
|
onchangeLoadVersion (event) { |
||||||
|
this.data.selectedVersion = this._view.versionSelector.value |
||||||
|
this._updateVersionSelector() |
||||||
|
} |
||||||
|
|
||||||
|
_updateVersionSelector () { |
||||||
|
this._view.versionSelector.innerHTML = '' |
||||||
|
this._view.versionSelector.appendChild(yo`<option disabled selected>Select new compiler version</option>`) |
||||||
|
this.data.allversions.forEach(build => this._view.versionSelector.appendChild(yo`<option value=${build.path}>${build.longVersion}</option>`)) |
||||||
|
this._view.versionSelector.removeAttribute('disabled') |
||||||
|
this.queryParams.update({ version: this.data.selectedVersion }) |
||||||
|
var url |
||||||
|
if (this.data.selectedVersion === 'builtin') { |
||||||
|
var location = window.document.location |
||||||
|
location = location.protocol + '//' + location.host + '/' + location.pathname |
||||||
|
if (location.endsWith('index.html')) location = location.substring(0, location.length - 10) |
||||||
|
if (!location.endsWith('/')) location += '/' |
||||||
|
url = location + 'soljson.js' |
||||||
|
} else { |
||||||
|
if (this.data.selectedVersion.indexOf('soljson') !== 0 || helper.checkSpecialChars(this.data.selectedVersion)) { |
||||||
|
return console.log('loading ' + this.data.selectedVersion + ' not allowed') |
||||||
|
} |
||||||
|
url = `${this.data.baseurl}/${this.data.selectedVersion}` |
||||||
|
} |
||||||
|
var isFirefox = typeof InstallTrigger !== 'undefined' |
||||||
|
if (document.location.protocol !== 'file:' && Worker !== undefined && isFirefox) { |
||||||
|
// Workers cannot load js on "file:"-URLs and we get a
|
||||||
|
// "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium,
|
||||||
|
// resort to non-worker version in that case.
|
||||||
|
this.compileTabLogic.compiler.loadVersion(true, url) |
||||||
|
this.setVersionText('(loading using worker)') |
||||||
|
} else { |
||||||
|
this.compileTabLogic.compiler.loadVersion(false, url) |
||||||
|
this.setVersionText('(loading)') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setVersionText (text) { |
||||||
|
this.data.version = text |
||||||
|
if (this._view.version) this._view.version.innerText = text |
||||||
|
} |
||||||
|
|
||||||
|
fetchAllVersion (callback) { |
||||||
|
minixhr(`${this.data.baseurl}/list.json`, (json, event) => { |
||||||
|
// @TODO: optimise and cache results to improve app loading times
|
||||||
|
var allversions, selectedVersion |
||||||
|
if (event.type !== 'error') { |
||||||
|
try { |
||||||
|
const data = JSON.parse(json) |
||||||
|
allversions = data.builds.slice().reverse() |
||||||
|
selectedVersion = this.data.defaultVersion |
||||||
|
if (this.queryParams.get().version) selectedVersion = this.queryParams.get().version |
||||||
|
} catch (e) { |
||||||
|
addTooltip('Cannot load compiler version list. It might have been blocked by an advertisement blocker. Please try deactivating any of them from this page and reload.') |
||||||
|
} |
||||||
|
} else { |
||||||
|
allversions = [{ path: 'builtin', longVersion: 'latest local version' }] |
||||||
|
selectedVersion = 'builtin' |
||||||
|
} |
||||||
|
callback(allversions, selectedVersion) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
scheduleCompilation () { |
||||||
|
if (!this.config.get('autoCompile')) return |
||||||
|
if (this.data.compileTimeout) window.clearTimeout(this.data.compileTimeout) |
||||||
|
this.data.compileTimeout = window.setTimeout(() => this.compileTabLogic.runCompiler(), this.data.timeout) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
module.exports = CompilerContainer |
@ -0,0 +1,213 @@ |
|||||||
|
const csjs = require('csjs-inject') |
||||||
|
const styleGuide = require('../../ui/styles-guide/theme-chooser') |
||||||
|
const styles = styleGuide.chooser() |
||||||
|
|
||||||
|
const css = csjs` |
||||||
|
.title { |
||||||
|
font-size: 1.1em; |
||||||
|
font-weight: bold; |
||||||
|
margin-bottom: 1em; |
||||||
|
} |
||||||
|
.panicError { |
||||||
|
color: red; |
||||||
|
font-size: 20px; |
||||||
|
} |
||||||
|
.crow { |
||||||
|
display: flex; |
||||||
|
overflow: auto; |
||||||
|
clear: both; |
||||||
|
padding: .2em; |
||||||
|
} |
||||||
|
.checkboxText { |
||||||
|
font-weight: normal; |
||||||
|
} |
||||||
|
.crow label { |
||||||
|
cursor:pointer; |
||||||
|
} |
||||||
|
.crowNoFlex { |
||||||
|
overflow: auto; |
||||||
|
clear: both; |
||||||
|
} |
||||||
|
.select { |
||||||
|
font-weight: bold; |
||||||
|
margin: 10px 0px; |
||||||
|
${styles.rightPanel.settingsTab.dropdown_SelectCompiler}; |
||||||
|
} |
||||||
|
.info { |
||||||
|
${styles.rightPanel.settingsTab.box_SolidityVersionInfo} |
||||||
|
margin-bottom: 1em; |
||||||
|
word-break: break-word; |
||||||
|
} |
||||||
|
.compileTabView { |
||||||
|
padding: 2%; |
||||||
|
} |
||||||
|
.contract { |
||||||
|
display: block; |
||||||
|
margin: 3% 0; |
||||||
|
} |
||||||
|
.compileContainer { |
||||||
|
${styles.rightPanel.compileTab.box_CompileContainer}; |
||||||
|
margin-bottom: 2%; |
||||||
|
} |
||||||
|
.autocompileContainer { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.hideWarningsContainer { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.autocompile {} |
||||||
|
.autocompileTitle { |
||||||
|
font-weight: bold; |
||||||
|
margin: 1% 0; |
||||||
|
} |
||||||
|
.autocompileText { |
||||||
|
margin: 1% 0; |
||||||
|
font-size: 12px; |
||||||
|
overflow: hidden; |
||||||
|
word-break: normal; |
||||||
|
line-height: initial; |
||||||
|
} |
||||||
|
.warnCompilationSlow { |
||||||
|
color: ${styles.rightPanel.compileTab.icon_WarnCompilation_Color}; |
||||||
|
margin-left: 1%; |
||||||
|
} |
||||||
|
.compileButtons { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
flex-wrap: wrap; |
||||||
|
justify-content: flex-end; |
||||||
|
} |
||||||
|
.name { |
||||||
|
display: flex; |
||||||
|
} |
||||||
|
.size { |
||||||
|
display: flex; |
||||||
|
} |
||||||
|
.checkboxes { |
||||||
|
display: flex; |
||||||
|
width: 100%; |
||||||
|
justify-content: space-between; |
||||||
|
flex-wrap: wrap; |
||||||
|
} |
||||||
|
.compileButton { |
||||||
|
${styles.rightPanel.compileTab.button_Compile}; |
||||||
|
width: 100%; |
||||||
|
margin: 15px 0 10px 0; |
||||||
|
font-size: 12px; |
||||||
|
} |
||||||
|
.container { |
||||||
|
${styles.rightPanel.compileTab.box_CompileContainer}; |
||||||
|
margin: 0; |
||||||
|
margin-bottom: 2%; |
||||||
|
} |
||||||
|
.contractContainer { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 2%; |
||||||
|
} |
||||||
|
.optimizeContainer { |
||||||
|
display: flex; |
||||||
|
} |
||||||
|
.contractNames { |
||||||
|
${styles.rightPanel.compileTab.dropdown_CompileContract}; |
||||||
|
width:78%; |
||||||
|
} |
||||||
|
.contractHelperButtons { |
||||||
|
display: flex; |
||||||
|
cursor: pointer; |
||||||
|
text-align: center; |
||||||
|
justify-content: flex-end; |
||||||
|
margin: 15px 15px 10px 0; |
||||||
|
} |
||||||
|
.copyButton { |
||||||
|
${styles.rightPanel.compileTab.button_Publish}; |
||||||
|
padding: 0 7px; |
||||||
|
min-width: 50px; |
||||||
|
width: auto; |
||||||
|
margin-left: 5px; |
||||||
|
background-color: inherit; |
||||||
|
border: inherit; |
||||||
|
} |
||||||
|
.bytecodeButton { |
||||||
|
min-width: 80px; |
||||||
|
} |
||||||
|
.copyIcon { |
||||||
|
margin-right: 5px; |
||||||
|
} |
||||||
|
.details { |
||||||
|
${styles.rightPanel.compileTab.button_Details}; |
||||||
|
min-width: 70px; |
||||||
|
width: 80px; |
||||||
|
} |
||||||
|
.publish { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-left: 10px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
.log { |
||||||
|
${styles.rightPanel.compileTab.box_CompileContainer}; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
margin-bottom: 5%; |
||||||
|
overflow: visible; |
||||||
|
} |
||||||
|
.key { |
||||||
|
margin-right: 5px; |
||||||
|
color: ${styles.rightPanel.text_Primary}; |
||||||
|
text-transform: uppercase; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
.value { |
||||||
|
display: flex; |
||||||
|
width: 100%; |
||||||
|
margin-top: 1.5%; |
||||||
|
} |
||||||
|
.questionMark { |
||||||
|
margin-left: 2%; |
||||||
|
cursor: pointer; |
||||||
|
color: ${styles.rightPanel.icon_Color_TogglePanel}; |
||||||
|
} |
||||||
|
.questionMark:hover { |
||||||
|
color: ${styles.rightPanel.icon_HoverColor_TogglePanel}; |
||||||
|
} |
||||||
|
.detailsJSON { |
||||||
|
padding: 8px 0; |
||||||
|
background-color: ${styles.rightPanel.modalDialog_BackgroundColor_Primary}; |
||||||
|
border: none; |
||||||
|
color: ${styles.rightPanel.modalDialog_text_Secondary}; |
||||||
|
} |
||||||
|
.icon { |
||||||
|
margin-right: 0.3em; |
||||||
|
} |
||||||
|
.spinningIcon { |
||||||
|
margin-right: .3em; |
||||||
|
animation: spin 2s linear infinite; |
||||||
|
} |
||||||
|
.bouncingIcon { |
||||||
|
margin-right: .3em; |
||||||
|
animation: bounce 2s infinite; |
||||||
|
} |
||||||
|
@keyframes spin { |
||||||
|
0% { transform: rotate(0deg); } |
||||||
|
100% { transform: rotate(360deg); } |
||||||
|
} |
||||||
|
@-webkit-keyframes bounce { |
||||||
|
0% { |
||||||
|
margin-bottom: 0; |
||||||
|
color: ${styles.colors.transparent}; |
||||||
|
} |
||||||
|
70% { |
||||||
|
margin-bottom: 0; |
||||||
|
color: ${styles.rightPanel.text_Secondary}; |
||||||
|
} |
||||||
|
100% { |
||||||
|
margin-bottom: 0; |
||||||
|
color: ${styles.colors.transparent}; |
||||||
|
} |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
module.exports = css |
Loading…
Reference in new issue