After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 639 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 552 KiB |
After Width: | Height: | Size: 972 KiB |
After Width: | Height: | Size: 6.8 KiB |
@ -0,0 +1,14 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React from 'react' |
||||
|
||||
function CustomButtonGroupAsArrows ({ next, previous }) { |
||||
return ( |
||||
<div style={{ textAlign: "center" }}> |
||||
<h4>These buttons can be positioned anywhere you want on the screen</h4> |
||||
<button onClick={previous}>Prev</button> |
||||
<button onClick={next}>Next</button> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default CustomButtonGroupAsArrows |
@ -0,0 +1,20 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React from 'react' |
||||
|
||||
const CustomNavButtons = ({ next, previous, goToSlide, ...rest }) => { |
||||
const { carouselState: { currentSlide, totalItems } } = rest |
||||
return ( |
||||
<div className="mt-1 d-flex justify-content-end carousel-button-group"> |
||||
<button className={currentSlide === 0 ? 'disable py-1 border btn' : 'py-1 border btn'} onClick={() => previous()}> |
||||
<i className="fas fa-angle-left"></i> |
||||
</button> |
||||
<button className={currentSlide + 1 === totalItems ? 'disable py-1 border btn' : 'py-1 border btn'} onClick={() => { |
||||
if (currentSlide + 1 < totalItems) goToSlide(currentSlide + 1) |
||||
}} > |
||||
<i className="fas fa-angle-right"></i> |
||||
</button> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default CustomNavButtons |
@ -0,0 +1,73 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useEffect, useState, useRef, useContext } from 'react' |
||||
import { ThemeContext, themes } from '../themeContext' |
||||
import Carousel from 'react-multi-carousel' |
||||
import 'react-multi-carousel/lib/styles.css' |
||||
import CustomNavButtons from './customNavButtons' |
||||
|
||||
function HomeTabFeatured() { |
||||
const themeFilter = useContext(ThemeContext) |
||||
|
||||
useEffect(() => { |
||||
return () => { |
||||
} |
||||
}, []) |
||||
|
||||
return ( |
||||
<div className="pt-3 pl-2" id="hTFeaturedeSection"> |
||||
<label style={{ fontSize: "1.2rem" }}>Featured</label> |
||||
<div className="mb-2"> |
||||
<div className="w-100 d-flex flex-column" style={{ height: "200px" }}> |
||||
<ThemeContext.Provider value={ themeFilter }> |
||||
<Carousel |
||||
customButtonGroup={<CustomNavButtons next={undefined} previous={undefined} goToSlide={undefined} />} |
||||
arrows={false} |
||||
swipeable={false} |
||||
draggable={true} |
||||
showDots={true} |
||||
responsive={{ desktop: { breakpoint: { max: 2000, min: 1024 }, items: 1 } }} |
||||
renderDotsOutside={true} |
||||
ssr={true} // means to render carousel on server-side.
|
||||
infinite={true} |
||||
centerMode={false} |
||||
autoPlay={true} |
||||
keyBoardControl={true} |
||||
containerClass="border carousel-container" |
||||
sliderClass="px-2 h-100 justify-content-between" |
||||
deviceType={"desktop"} |
||||
itemClass="px-2 carousel-item-padding-10-px" |
||||
autoPlaySpeed={15000} |
||||
dotListClass="position-relative mt-2" |
||||
> |
||||
<div className="d-flex"> |
||||
<img src={"assets/img/bgRemi.webp"} style={{ flex: "1", height: "170px", maxWidth: "170px"}} alt="" ></img> |
||||
<div className="h6 w-50 p-4" style={{ flex: "1"}}> |
||||
<h5>JUMP INTO WEB3</h5> |
||||
<span>The Remix Project is a rich toolset which can be used for the entire journey of contract development by users of any knowledge level, and as a learning lab for teaching and experimenting with Ethereum.</span> |
||||
</div> |
||||
</div> |
||||
<div className="d-flex"> |
||||
<img src={"/assets/img/remixRewardUser.webp"} style={{ flex: "1", height: "170px", maxWidth: "170px" }} alt="" ></img> |
||||
<div className="h6 p-4" style={{ flex: "1"}}> |
||||
<h5>REMIX REWARDS</h5> |
||||
<p style={{fontStyle: 'italic'}}>NFTs for our users!</p> |
||||
<span>Remix Project rewards contributors, beta testers, and UX research participants with NFTs deployed on Optimism. Remix Reward holders are able to mint a second “Remixer” user NFT badge to give to any other user of their choice</span> |
||||
</div> |
||||
</div> |
||||
<div className="d-flex"> |
||||
<img src={"/assets/img/remixRewardBetaTester.webp"} style={{ flex: "1", height: "170px", maxWidth: "170px" }} alt="" ></img> |
||||
<div className="h6 p-4" style={{ flex: "1"}}> |
||||
<h5>BETA TESTING</h5> |
||||
<p style={{fontStyle: 'italic'}}>Our community supports us.</p> |
||||
<span>You can join Beta Testing before each release of Remix IDE. Help us test now and get a handle on new features!</span> |
||||
</div> |
||||
</div> |
||||
</Carousel> |
||||
</ThemeContext.Provider> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabFeatured |
@ -0,0 +1,125 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useEffect, useState, useRef, useContext } from 'react' |
||||
import PluginButton from './pluginButton' |
||||
import { ThemeContext, themes } from '../themeContext' |
||||
import Carousel from 'react-multi-carousel' |
||||
import 'react-multi-carousel/lib/styles.css' |
||||
import CustomNavButtons from './customNavButtons' |
||||
declare global { |
||||
interface Window { |
||||
_paq: any |
||||
} |
||||
} |
||||
const _paq = window._paq = window._paq || [] //eslint-disable-line
|
||||
|
||||
interface HomeTabFeaturedPluginsProps { |
||||
plugin: any |
||||
} |
||||
|
||||
function HomeTabFeaturedPlugins ({plugin}: HomeTabFeaturedPluginsProps) { |
||||
|
||||
const themeFilter = useContext(ThemeContext) |
||||
const carouselRef = useRef(null) |
||||
|
||||
// Todo doesn't work
|
||||
useEffect(() => { |
||||
window.addEventListener("scroll", handleScroll) |
||||
return () => { |
||||
window.removeEventListener("scroll", handleScroll) |
||||
} |
||||
}, []) |
||||
|
||||
const handleScroll = (e) => { |
||||
} |
||||
|
||||
const startSolidity = async () => { |
||||
await plugin.appManager.activatePlugin(['solidity', 'udapp', 'solidityStaticAnalysis', 'solidityUnitTesting']) |
||||
plugin.verticalIcons.select('solidity') |
||||
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'solidity']) |
||||
} |
||||
const startStarkNet = async () => { |
||||
await plugin.appManager.activatePlugin('starkNet_compiler') |
||||
plugin.verticalIcons.select('starkNet_compiler') |
||||
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'starkNet_compiler']) |
||||
} |
||||
const startSolhint = async () => { |
||||
await plugin.appManager.activatePlugin(['solidity', 'solhint']) |
||||
plugin.verticalIcons.select('solhint') |
||||
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'solhint']) |
||||
} |
||||
const startSourceVerify = async () => { |
||||
await plugin.appManager.activatePlugin(['solidity', 'sourcify']) |
||||
plugin.verticalIcons.select('sourcify') |
||||
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'sourcify']) |
||||
}
|
||||
const startSolidityUnitTesting = async () => { |
||||
await plugin.appManager.activatePlugin(['solidity', 'solidityUnitTesting']) |
||||
plugin.verticalIcons.select('solidityUnitTesting') |
||||
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'solidityUnitTesting']) |
||||
} |
||||
|
||||
return ( |
||||
<div className="pl-2 w-100" id="hTFeaturedPlugins"> |
||||
<label className="" style={{fontSize: "1.2rem"}}>Featured Plugins</label> |
||||
<div className="w-100 d-flex flex-column"> |
||||
<ThemeContext.Provider value={ themeFilter }> |
||||
<Carousel
|
||||
ref={carouselRef} |
||||
focusOnSelect |
||||
customButtonGroup={<CustomNavButtons next={undefined} previous={undefined} goToSlide={undefined} />} |
||||
arrows={false} |
||||
swipeable={false} |
||||
draggable={true} |
||||
showDots={false} |
||||
responsive={{ desktop: { breakpoint: { max: 3000, min: 1024 }, items: 5} }} |
||||
renderButtonGroupOutside={true} |
||||
ssr={true} // means to render carousel on server-side.
|
||||
keyBoardControl={true} |
||||
containerClass="carousel-container" |
||||
deviceType={"desktop"} |
||||
itemClass="w-100" |
||||
> |
||||
<PluginButton |
||||
imgPath="assets/img/solidityLogo.webp" |
||||
envID="solidityLogo" |
||||
envText="Solidity" |
||||
description="Compile, test and analyse smart contract." |
||||
remixMaintained={true} |
||||
callback={() => startSolidity()} |
||||
/> |
||||
<PluginButton |
||||
imgPath="assets/img/starkNetLogo.webp" |
||||
envID="starkNetLogo" |
||||
envText="StarkNet" |
||||
description="Compile and deploy contracts with Cairo, a native language for StarkNet." |
||||
l2={true} |
||||
callback={() => startStarkNet()} |
||||
/> |
||||
<PluginButton |
||||
imgPath="assets/img/solhintLogo.webp" |
||||
envID="solhintLogo" envText="Solhint linter" |
||||
description="Solhint is an open source project for linting Solidity code." |
||||
callback={() => startSolhint()} |
||||
/> |
||||
<PluginButton |
||||
imgPath="assets/img/sourcifyNewLogo.webp" |
||||
envID="sourcifyLogo" |
||||
envText="Sourcify" |
||||
description="Solidity contract and metadata verification service." |
||||
callback={() => startSourceVerify()} |
||||
/> |
||||
<PluginButton |
||||
imgPath="assets/img/unitTesting.webp" |
||||
envID="sUTLogo" |
||||
envText="Solidity unit testing" |
||||
description="Write and run unit tests for your contracts in Solidity." |
||||
callback={() => startSolidityUnitTesting()} |
||||
/> |
||||
</Carousel> |
||||
</ThemeContext.Provider> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabFeaturedPlugins |
@ -0,0 +1,161 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useState, useRef, useReducer } from 'react' |
||||
import { ModalDialog } from '@remix-ui/modal-dialog' // eslint-disable-line
|
||||
import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
|
||||
|
||||
interface HomeTabFileProps { |
||||
plugin: any |
||||
} |
||||
|
||||
const loadingInitialState = { |
||||
tooltip: '', |
||||
showModalDialog: false, |
||||
importSource: '' |
||||
} |
||||
|
||||
const loadingReducer = (state = loadingInitialState, action) => { |
||||
return { ...state, tooltip: action.tooltip, showModalDialog: false, importSource: '' } |
||||
} |
||||
|
||||
function HomeTabFile ({plugin}: HomeTabFileProps) { |
||||
const [state, setState] = useState<{ |
||||
searchInput: string, |
||||
showModalDialog: boolean, |
||||
modalInfo: { title: string, loadItem: string, examples: Array<string> }, |
||||
importSource: string, |
||||
toasterMsg: string |
||||
}>({ |
||||
searchInput: '', |
||||
showModalDialog: false, |
||||
modalInfo: { title: '', loadItem: '', examples: [] }, |
||||
importSource: '', |
||||
toasterMsg: '' |
||||
}) |
||||
|
||||
const [, dispatch] = useReducer(loadingReducer, loadingInitialState) |
||||
|
||||
const inputValue = useRef(null) |
||||
|
||||
const processLoading = () => { |
||||
const contentImport = plugin.contentImport |
||||
const workspace = plugin.fileManager.getProvider('workspace') |
||||
contentImport.import( |
||||
state.importSource, |
||||
(loadingMsg) => dispatch({ tooltip: loadingMsg }), |
||||
async (error, content, cleanUrl, type, url) => { |
||||
if (error) { |
||||
toast(error.message || error) |
||||
} else { |
||||
try { |
||||
if (await workspace.exists(type + '/' + cleanUrl)) toast('File already exists in workspace') |
||||
else { |
||||
workspace.addExternal(type + '/' + cleanUrl, content, url) |
||||
plugin.call('menuicons', 'select', 'filePanel') |
||||
}
|
||||
} catch (e) { |
||||
toast(e.message) |
||||
} |
||||
} |
||||
} |
||||
) |
||||
setState(prevState => { |
||||
return { ...prevState, showModalDialog: false, importSource: '' } |
||||
}) |
||||
} |
||||
|
||||
const toast = (message: string) => { |
||||
setState(prevState => { |
||||
return { ...prevState, toasterMsg: message } |
||||
}) |
||||
} |
||||
|
||||
const createNewFile = async () => { |
||||
plugin.verticalIcons.select('filePanel') |
||||
await plugin.call('filePanel', 'createNewFile') |
||||
} |
||||
|
||||
const uploadFile = async (target) => { |
||||
await plugin.call('filePanel', 'uploadFile', target) |
||||
} |
||||
|
||||
const connectToLocalhost = () => { |
||||
plugin.appManager.activatePlugin('remixd') |
||||
} |
||||
const importFromGist = () => { |
||||
plugin.call('gistHandler', 'load', '') |
||||
plugin.verticalIcons.select('filePanel') |
||||
} |
||||
|
||||
const showFullMessage = (title: string, loadItem: string, examples: Array<string>) => { |
||||
setState(prevState => { |
||||
return { ...prevState, showModalDialog: true, modalInfo: { title: title, loadItem: loadItem, examples: examples } } |
||||
}) |
||||
} |
||||
|
||||
const hideFullMessage = () => { //eslint-disable-line
|
||||
setState(prevState => { |
||||
return { ...prevState, showModalDialog: false, importSource: '' } |
||||
}) |
||||
} |
||||
|
||||
const examples = state.modalInfo.examples.map((urlEl, key) => (<div key={key} className="p-1 user-select-auto"><a>{urlEl}</a></div>)) |
||||
|
||||
return ( |
||||
<> |
||||
<ModalDialog |
||||
id='homeTab' |
||||
title={ 'Import from ' + state.modalInfo.title } |
||||
okLabel='Import' |
||||
hide={ !state.showModalDialog } |
||||
handleHide={ () => hideFullMessage() } |
||||
okFn={ () => processLoading() } |
||||
> |
||||
<div className="p-2 user-select-auto"> |
||||
{ state.modalInfo.loadItem !== '' && <span>Enter the { state.modalInfo.loadItem } you would like to load.</span> } |
||||
{ state.modalInfo.examples.length !== 0 && |
||||
<> |
||||
<div>e.g</div> |
||||
<div> |
||||
{ examples } |
||||
</div> |
||||
</> } |
||||
<input |
||||
ref={inputValue} |
||||
type='text' |
||||
name='prompt_text' |
||||
id='inputPrompt_text' |
||||
className="w-100 mt-1 form-control" |
||||
data-id="homeTabModalDialogCustomPromptText" |
||||
value={state.importSource} |
||||
onInput={(e) => { |
||||
setState(prevState => { |
||||
return { ...prevState, importSource: inputValue.current.value } |
||||
}) |
||||
}} |
||||
/> |
||||
</div> |
||||
</ModalDialog> |
||||
<Toaster message={state.toasterMsg} /> |
||||
<div className="justify-content-start mt-1 p-2 border-bottom d-flex flex-column" id="hTFileSection"> |
||||
<label style={{fontSize: "1rem"}}>Files</label> |
||||
<button className="btn btn-primary p-2 border my-1" data-id="homeTabNewFile" style={{width: 'fit-content'}} onClick={() => createNewFile()}>New File</button> |
||||
<label className="btn p-2 border my-1" style={{width: 'fit-content'}} htmlFor="openFileInput">Open File</label> |
||||
<input title="open file" type="file" id="openFileInput" onChange={(event) => { |
||||
event.stopPropagation() |
||||
plugin.verticalIcons.select('filePanel') |
||||
uploadFile(event.target) |
||||
}} multiple /> |
||||
<button className="btn p-2 border my-1" style={{width: 'fit-content'}} onClick={() => connectToLocalhost()}>Connect to Localhost</button> |
||||
<label className="pt-2">Load From</label> |
||||
<div className="d-flex"> |
||||
<button className="btn p-2 border mr-2" data-id="landingPageImportFromGitHubButton" onClick={() => showFullMessage('GitHub', 'github URL', ['https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/nf-token-metadata.sol', 'https://github.com/OpenZeppelin/openzeppelin-solidity/blob/67bca857eedf99bf44a4b6a0fc5b5ed553135316/contracts/access/Roles.sol'])}>GitHub</button> |
||||
<button className="btn p-2 border mr-2" data-id="landingPageImportFromGistButton" onClick={() => importFromGist()}>Gist</button> |
||||
<button className="btn p-2 border mr-2" onClick={() => showFullMessage('Ipfs', 'ipfs URL', ['ipfs://<ipfs-hash>'])}>IPFS</button>
|
||||
<button className="btn p-2 border" onClick={() => showFullMessage('Https', 'http/https raw content', ['https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/master/contracts/token/ERC20/ERC20.sol'])}>HTTPS</button> |
||||
</div> |
||||
</div> |
||||
</> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabFile |
@ -0,0 +1,88 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useEffect, useState, useRef, useContext } from 'react' |
||||
import { ThemeContext, themes } from '../themeContext' |
||||
import Carousel from 'react-multi-carousel' |
||||
import WorkspaceTemplate from './workspaceTemplate' |
||||
import 'react-multi-carousel/lib/styles.css' |
||||
import CustomNavButtons from './customNavButtons' |
||||
declare global { |
||||
interface Window { |
||||
_paq: any |
||||
} |
||||
} |
||||
const _paq = window._paq = window._paq || [] //eslint-disable-line
|
||||
|
||||
interface HomeTabGetStartedProps { |
||||
plugin: any |
||||
} |
||||
|
||||
function HomeTabGetStarted ({plugin}: HomeTabGetStartedProps) { |
||||
const themeFilter = useContext(ThemeContext) |
||||
|
||||
const createWorkspace = async (templateName) => { |
||||
await plugin.appManager.activatePlugin('filePanel') |
||||
const timeStamp = Date.now() |
||||
await plugin.call('filePanel', 'createWorkspace', templateName + "_" + timeStamp, templateName) |
||||
await plugin.call('filePanel', 'setWorkspace', templateName + "_" + timeStamp) |
||||
plugin.verticalIcons.select('filePanel') |
||||
_paq.push(['trackEvent', 'homeGetStarted', templateName]) |
||||
} |
||||
|
||||
return ( |
||||
<div className="pl-2" id="hTGetStartedSection"> |
||||
<label style={{fontSize: "1.2rem"}}> |
||||
<span className="mr-2" style={{fontWeight: "bold"}}> |
||||
Get Started |
||||
</span> |
||||
- Project Templates |
||||
</label> |
||||
<div className="w-100 d-flex flex-column"> |
||||
<ThemeContext.Provider value={ themeFilter }> |
||||
<Carousel
|
||||
focusOnSelect |
||||
customButtonGroup={<CustomNavButtons next={undefined} previous={undefined} goToSlide={undefined} />} |
||||
arrows={false} |
||||
swipeable={false} |
||||
draggable={true} |
||||
showDots={false} |
||||
responsive={{ desktop: { breakpoint: { max: 3000, min: 1024 }, items: 5} }} |
||||
renderButtonGroupOutside={true} |
||||
ssr={true} // means to render carousel on server-side.
|
||||
keyBoardControl={true} |
||||
containerClass="carousel-container" |
||||
deviceType={"desktop"} |
||||
itemClass="w-100" |
||||
> |
||||
<WorkspaceTemplate |
||||
gsID="starkNetLogo" |
||||
workspaceTitle="Blank" |
||||
description="Create an empty workspace." |
||||
callback={() => createWorkspace("blank")} /> |
||||
<WorkspaceTemplate |
||||
gsID="solhintLogo" |
||||
workspaceTitle="Remix Default" |
||||
description="Create a workspace with sample files." |
||||
callback={() => createWorkspace("remixDefault")} /> |
||||
<WorkspaceTemplate |
||||
gsID="sourcifyLogo" |
||||
workspaceTitle="OpenZeppelin ERC20" |
||||
description="Create an ERC20 token by importing OpenZeppelin library." |
||||
callback={() => createWorkspace("ozerc20")} /> |
||||
<WorkspaceTemplate |
||||
gsID="sUTLogo" |
||||
workspaceTitle="OpenZeppelin ERC721" |
||||
description="Create an NFT token by importing OpenZeppelin library." |
||||
callback={() => createWorkspace("ozerc721")} /> |
||||
<WorkspaceTemplate |
||||
gsID="sUTLogo" |
||||
workspaceTitle="0xProject ERC20" |
||||
description="Create an ERC20 token by importing 0xProject contract." |
||||
callback={() => createWorkspace("zeroxErc20")} /> |
||||
</Carousel> |
||||
</ThemeContext.Provider> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabGetStarted |
@ -0,0 +1,76 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useEffect, useState, useContext } from 'react' |
||||
import { ThemeContext } from '../themeContext' |
||||
declare global { |
||||
interface Window { |
||||
_paq: any |
||||
} |
||||
} |
||||
const _paq = window._paq = window._paq || [] //eslint-disable-line
|
||||
|
||||
enum VisibleTutorial { |
||||
Basics, |
||||
Intermediate, |
||||
Advanced |
||||
} |
||||
interface HomeTabLearnProps { |
||||
plugin: any |
||||
} |
||||
|
||||
function HomeTabLearn ({plugin}: HomeTabLearnProps) { |
||||
const [state, setState] = useState<{ |
||||
visibleTutorial: VisibleTutorial |
||||
}>({ |
||||
visibleTutorial: VisibleTutorial.Basics |
||||
}) |
||||
|
||||
const themeFilter = useContext(ThemeContext) |
||||
|
||||
const openLink = () => { |
||||
window.open("https://remix-ide.readthedocs.io/en/latest/remix_tutorials_learneth.html?highlight=learneth#learneth-tutorial-repos", '_blank') |
||||
} |
||||
|
||||
const startLearnEthTutorial = async (tutorial) => { |
||||
await plugin.appManager.activatePlugin(['solidity', 'LearnEth', 'solidityUnitTesting']) |
||||
plugin.call('LearnEth', 'startTutorial', 'ethereum/remix-workshops', 'master', tutorial) |
||||
plugin.verticalIcons.select('LearnEth') |
||||
_paq.push(['trackEvent', 'homeTab', 'startLearnEthTutorial', tutorial]) |
||||
} |
||||
|
||||
return ( |
||||
<div className="d-flex px-2 pb-2 pt-2 d-flex flex-column" id="hTLearnSection"> |
||||
<div className="d-flex justify-content-between"> |
||||
<label className="py-2 align-self-center m-0" style={{fontSize: "1.2rem"}}>Learn</label> |
||||
<button |
||||
onClick={ ()=> openLink()} |
||||
className="h-100 px-2 pt-0 btn" |
||||
> |
||||
<img className="align-self-center" src="assets/img/learnEthLogo.webp" alt="" style={ { filter: themeFilter.filter, width: "1rem", height: "1ren" } } /> |
||||
</button> |
||||
</div> |
||||
<div className="d-flex flex-column"> |
||||
<button className="d-flex flex-column btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Basics }})}> |
||||
<label className="float-left" style={{fontSize: "1rem"}}>Remix Basics</label> |
||||
{(state.visibleTutorial === VisibleTutorial.Basics) && <div className="pt-2 d-flex flex-column text-left"> |
||||
<span>Introduction to Remix's interface and concepts used in Ethereum, as well as the basics of Solidity.</span> |
||||
<button className="btn btn-sm btn-secondary mt-2" style={{width: 'fit-content'}} onClick={() => startLearnEthTutorial('basics')}>Get Started</button> |
||||
</div>} |
||||
</button> |
||||
<button className="d-flex flex-column btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Intermediate }})}> |
||||
<label className="float-left" style={{fontSize: "1rem"}}>Remix Intermediate</label> |
||||
{(state.visibleTutorial === VisibleTutorial.Intermediate) && <div className="pt-2 d-flex flex-column text-left">Using the web3.js to interact with a contract. Using Recorder tool. |
||||
<button className="btn btn-sm btn-secondary mt-2" style={{width: 'fit-content'}} onClick={() => startLearnEthTutorial('useofweb3js')}>Get Started</button> |
||||
</div>} |
||||
</button> |
||||
<button className="d-flex flex-column btn border" onClick={() => setState((prevState) => {return { ...prevState, visibleTutorial: VisibleTutorial.Advanced }})}> |
||||
<label className="float-left" style={{fontSize: "1rem"}}>Remix Advanced</label> |
||||
{(state.visibleTutorial === VisibleTutorial.Advanced) && <div className="pt-2 d-flex flex-column text-left">Learn the Proxy Pattern and working with Libraries in Remix. Learn to use the Debugger. |
||||
<button className="btn btn-sm btn-secondary mt-2" style={{width: 'fit-content'}} onClick={() => startLearnEthTutorial('deploylibraries')}>Get Started</button> |
||||
</div>} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabLearn |
@ -0,0 +1,28 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React from 'react' |
||||
|
||||
function HomeTabScamAlert () { |
||||
return ( |
||||
<div className="" id="hTScamAlertSection"> |
||||
<label className="pl-2 text-danger" style={{fontSize: "1.2rem"}}>Scam Alert</label> |
||||
<div className="py-2 ml-2 mb-1 align-self-end mb-2 d-flex flex-column border border-danger"> |
||||
<span className="pl-4 mt-2"> |
||||
<i className="pr-2 text-danger fas fa-exclamation-triangle"></i> |
||||
<b>Scam Alerts:</b> |
||||
</span> |
||||
<span className="pl-4 mt-1"> |
||||
The only URL Remix uses is remix.ethereum.org
|
||||
</span> |
||||
<span className="pl-4 mt-1">
|
||||
Beware of online videos promoting "liquidity front runner bots":
|
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://medium.com/remix-ide/remix-in-youtube-crypto-scams-71c338da32d">Learn more</a> |
||||
</span> |
||||
<span className="pl-4 mt-1"> |
||||
Additional safety tips: <a className="remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest/security.html">here</a> |
||||
</span> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabScamAlert |
@ -0,0 +1,148 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
|
||||
import BasicLogo from 'libs/remix-ui/vertical-icons-panel/src/lib/components/BasicLogo' |
||||
import { ThemeContext } from '../themeContext' |
||||
import React, { useEffect, useState, useRef, useContext } from 'react' |
||||
import { OverlayTrigger, Tooltip } from 'react-bootstrap'// eslint-disable-line
|
||||
|
||||
function HomeTabTitle() { |
||||
useEffect(() => { |
||||
document.addEventListener("keyup", (e) => handleSearchKeyDown(e)) |
||||
return () => { |
||||
document.removeEventListener("keyup", handleSearchKeyDown) |
||||
} |
||||
}, []) |
||||
const [state, setState] = useState<{ |
||||
searchDisable: boolean |
||||
}>({ |
||||
searchDisable: true |
||||
}) |
||||
|
||||
const themeFilter = useContext(ThemeContext) |
||||
const searchInputRef = useRef(null) |
||||
const remiAudioEl = useRef(null) |
||||
|
||||
const playRemi = async () => { |
||||
remiAudioEl.current.play() |
||||
} |
||||
const handleSearchKeyDown = (e: KeyboardEvent) => { |
||||
if (e.target !== searchInputRef.current) return |
||||
if (e.key === "Enter") { |
||||
openLink() |
||||
searchInputRef.current.value = "" |
||||
} else { |
||||
setState(prevState => { |
||||
return { ...prevState, searchDisable: searchInputRef.current.value === "" } |
||||
}) |
||||
} |
||||
} |
||||
|
||||
const openLink = (url = "") => { |
||||
if (url === "") { |
||||
window.open("https://remix-ide.readthedocs.io/en/latest/search.html?q=" + searchInputRef.current.value + "&check_keywords=yes&area=default", '_blank') |
||||
} else { |
||||
window.open(url, '_blank') |
||||
} |
||||
} |
||||
|
||||
return ( |
||||
<div className="px-2 pb-2 pt-2 d-flex flex-column border-bottom" id="hTTitleSection"> |
||||
<div className="mr-4 d-flex"> |
||||
<div onClick={() => playRemi()} style={{ filter: themeFilter.filter}} > |
||||
<BasicLogo classList="align-self-end remixui_home_logoImg" solid={false} /> |
||||
</div> |
||||
<audio |
||||
id="remiAudio" |
||||
muted={false} |
||||
src="assets/audio/remiGuitar-single-power-chord-A-minor.wav" |
||||
ref={remiAudioEl} |
||||
></audio> |
||||
</div> |
||||
<div className="d-flex justify-content-between"> |
||||
<span className="h-80 text-uppercase" style={{ fontSize: 'xx-large', fontFamily: "Noah, sans-serif" }}>Remix</span> |
||||
<span> |
||||
<OverlayTrigger placement={'top'} overlay={ |
||||
<Tooltip className="text-nowrap" id="overlay-tooltip"> |
||||
<span className="border bg-light text-dark p-1 pr-3">Remix Youtube Playlist</span> |
||||
</Tooltip> |
||||
}> |
||||
<button |
||||
onClick={() => openLink("https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA")} |
||||
className="border-0 h-100 btn fab fa-youtube"> |
||||
</button> |
||||
</OverlayTrigger> |
||||
|
||||
<OverlayTrigger placement={'top'} overlay={ |
||||
<Tooltip className="text-nowrap" id="overlay-tooltip"> |
||||
<span className="border bg-light text-dark p-1 pr-3">Remix Twitter Profile</span> |
||||
</Tooltip> |
||||
}> |
||||
<button |
||||
onClick={() => openLink("https://twitter.com/EthereumRemix")} |
||||
className="border-0 h-100 pl-2 btn fab fa-twitter"> |
||||
</button> |
||||
</OverlayTrigger> |
||||
|
||||
<OverlayTrigger placement={'top'} overlay={ |
||||
<Tooltip className="text-nowrap" id="overlay-tooltip"> |
||||
<span className="border bg-light text-dark p-1 pr-3">Remix Linkedin Profile</span> |
||||
</Tooltip> |
||||
}> |
||||
<button |
||||
onClick={() => openLink("https://www.linkedin.com/company/ethereum-remix/")} |
||||
className="border-0 h-100 pl-2 btn fa fa-linkedin"> |
||||
</button> |
||||
</OverlayTrigger> |
||||
|
||||
<OverlayTrigger placement={'top'} overlay={ |
||||
<Tooltip className="text-nowrap" id="overlay-tooltip"> |
||||
<span className="border bg-light text-dark p-1 pr-3">Remix Medium Posts</span> |
||||
</Tooltip> |
||||
}> |
||||
<button |
||||
onClick={() => openLink("https://medium.com/remix-ide")} |
||||
className="border-0 h-100 pl-2 btn fab fa-medium"> |
||||
</button> |
||||
</OverlayTrigger> |
||||
|
||||
<OverlayTrigger placement={'top'} overlay={ |
||||
<Tooltip className="text-nowrap" id="overlay-tooltip"> |
||||
<span className="border bg-light text-dark p-1 pr-3">Remix Gitter channel</span> |
||||
</Tooltip> |
||||
}> |
||||
<button |
||||
onClick={() => openLink("https://gitter.im/ethereum/remix")} |
||||
className="border-0 h-100 pl-2 btn fab fa-gitter"> |
||||
</button> |
||||
</OverlayTrigger> |
||||
</span> |
||||
</div> |
||||
<b className="pb-1 text-dark" style={{ fontStyle: 'italic' }}>The Native IDE for Web3 Development.</b> |
||||
<div className="pb-1" id="hTGeneralLinks"> |
||||
<a className="remixui_home_text" target="__blank" href="https://remix-project.org">Website</a> |
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-ide.readthedocs.io/en/latest">Documentation</a> |
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://remix-plugin-docs.readthedocs.io/en/latest/">Remix Plugin</a> |
||||
<a className="pl-2 remixui_home_text" target="__blank" href="https://github.com/ethereum/remix-desktop/releases">Remix Desktop</a> |
||||
</div> |
||||
<div className="d-flex pb-1 align-items-center"> |
||||
<input |
||||
ref={searchInputRef} |
||||
type="text" |
||||
className="border form-control border-right-0" |
||||
id="searchInput" |
||||
placeholder="Search Documentation" |
||||
data-id="terminalInputSearch" |
||||
/> |
||||
<button |
||||
className="form-control border d-flex align-items-center p-2 justify-content-center fas fa-search bg-light" |
||||
onClick={(e) => openLink()} |
||||
disabled={state.searchDisable} |
||||
style={{ width: "3rem" }} |
||||
> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default HomeTabTitle |
@ -1,12 +0,0 @@ |
||||
.RSSFeed-item img { |
||||
width: 100%; |
||||
} |
||||
|
||||
.RSSFeed-item .truncate { |
||||
max-height: 500px; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.RSSFeed-item .more-button { |
||||
|
||||
} |
@ -1,42 +0,0 @@ |
||||
import React, { useState, useEffect } from "react"; |
||||
import Parser from "rss-parser"; |
||||
import './rssFeed.css'; |
||||
|
||||
interface RSSFeedProps { |
||||
feedUrl: string, |
||||
maxItems: number, |
||||
} |
||||
|
||||
export function RSSFeed({ feedUrl, maxItems }: RSSFeedProps) { |
||||
const [feed, setFeed] = useState(null); |
||||
|
||||
useEffect(() => { |
||||
const fetchData = async () => { |
||||
const parser = new Parser() |
||||
const feed = await parser.parseURL(feedUrl); |
||||
for (const item of feed.items) { |
||||
item.content = item['content:encoded'] |
||||
item.date = new Date(item.pubDate).toLocaleDateString('en-US', { |
||||
month: 'short', |
||||
day: 'numeric' |
||||
}) |
||||
} |
||||
setFeed(feed); |
||||
}; |
||||
fetchData(); |
||||
}, [feedUrl]); |
||||
|
||||
|
||||
return (<> |
||||
{feed && feed.items.slice(0, maxItems).map((item: any, index: any) => ( |
||||
<div className='RSSFeed-item' key={index}> |
||||
<a target="_blank" href={item.link}><h3>{item.title}</h3></a> |
||||
<p>Author: {item.creator}</p> |
||||
<h4>{item.date}</h4> |
||||
<div className="truncate" dangerouslySetInnerHTML={{ __html: item.content }} /> |
||||
<a className="more-button btn mb-3" target="_blank" href={item.link}>READ MORE</a> |
||||
<hr></hr> |
||||
</div> |
||||
))} |
||||
</>) |
||||
} |
@ -0,0 +1,116 @@ |
||||
import * as React from "react"; |
||||
export interface ResponsiveType { |
||||
[key: string]: { |
||||
breakpoint: { max: number; min: number }; |
||||
items: number; |
||||
partialVisibilityGutter?: number; // back-ward compatible, because previously there has been a typo
|
||||
paritialVisibilityGutter?: number; |
||||
slidesToSlide?: number; |
||||
}; |
||||
} |
||||
export function isMouseMoveEvent( |
||||
e: React.MouseEvent | React.TouchEvent |
||||
): e is React.MouseEvent { |
||||
return "clientX" && "clientY" in e; |
||||
} |
||||
export interface CarouselProps { |
||||
responsive: ResponsiveType; |
||||
deviceType?: string; |
||||
ssr?: boolean; |
||||
slidesToSlide?: number; |
||||
draggable?: boolean; |
||||
arrows?: boolean; // show or hide arrows.
|
||||
renderArrowsWhenDisabled?: boolean; // Allow for the arrows to have a disabled attribute instead of not showing them
|
||||
swipeable?: boolean; |
||||
removeArrowOnDeviceType?: string | Array<string>; |
||||
children: any; |
||||
customLeftArrow?: React.ReactElement<any> | null; |
||||
customRightArrow?: React.ReactElement<any> | null; |
||||
customDot?: React.ReactElement<any> | null; |
||||
customButtonGroup?: React.ReactElement<any> | null; |
||||
infinite?: boolean; |
||||
minimumTouchDrag?: number; // default 50px. The amount of distance to drag / swipe in order to move to the next slide.
|
||||
afterChange?: (previousSlide: number, state: StateCallBack) => void; // Change callback after sliding everytime. `(previousSlide, currentState) => ...`
|
||||
beforeChange?: (nextSlide: number, state: StateCallBack) => void; // Change callback before sliding everytime. `(previousSlide, currentState) => ...`
|
||||
sliderClass?: string; // Use this to style your own track list.
|
||||
itemClass?: string; // Use this to style your own Carousel item. For example add padding-left and padding-right
|
||||
itemAriaLabel?: string; // Use this to add your own Carousel item aria-label.if it is not defined the child aria label will be applied if the child dont have one than a default empty string will be applied
|
||||
containerClass?: string; // Use this to style the whole container. For example add padding to allow the "dots" or "arrows" to go to other places without being overflown.
|
||||
className?: string; // Use this to style the whole container with styled-components
|
||||
dotListClass?: string; // Use this to style the dot list.
|
||||
keyBoardControl?: boolean; |
||||
centerMode?: boolean; // show previous and next set of items partially
|
||||
autoPlay?: boolean; |
||||
autoPlaySpeed?: number; // default 3000ms
|
||||
showDots?: boolean; |
||||
renderDotsOutside?: boolean; // show dots outside of the container for custom styling.
|
||||
renderButtonGroupOutside?: boolean; // show buttonGroup outside of the container for custom styling.
|
||||
// Show next/previous item partially
|
||||
// partialVisible has to be used in conjunction with the responsive props, details are in documentation.
|
||||
// it shows the next set of items partially, different from centerMode as it shows both.
|
||||
partialVisible?: boolean; |
||||
partialVisbile?: boolean; // old typo - deprecated (will be remove in 3.0)
|
||||
customTransition?: string; |
||||
transitionDuration?: number; |
||||
// if you are using customTransition, make sure to put the duration here.
|
||||
// for example, customTransition="all .5" then put transitionDuration as 500.
|
||||
// this is needed for the resizing to work.
|
||||
focusOnSelect?: boolean; |
||||
additionalTransfrom?: number; // this is only used if you want to add additional transfrom to the current transform
|
||||
pauseOnHover?: boolean; |
||||
shouldResetAutoplay?: boolean; |
||||
rewind?: boolean; |
||||
rewindWithAnimation?: boolean; |
||||
rtl?: boolean; |
||||
} |
||||
|
||||
export type StateCallBack = CarouselInternalState; |
||||
|
||||
export type Direction = "left" | "right" | "" | undefined; |
||||
export type SkipCallbackOptions = |
||||
| boolean |
||||
| { skipBeforeChange?: boolean; skipAfterChange?: boolean }; |
||||
export interface ButtonGroupProps { |
||||
previous?: () => void; |
||||
next?: () => void; |
||||
goToSlide?: (index: number, skipCallbacks?: SkipCallbackOptions) => void; |
||||
carouselState?: StateCallBack; |
||||
} |
||||
export interface ArrowProps { |
||||
onClick?: () => void; |
||||
carouselState?: StateCallBack; |
||||
} |
||||
export interface DotProps { |
||||
index?: number; |
||||
active?: boolean; |
||||
onClick?: () => void; |
||||
carouselState?: StateCallBack; |
||||
} |
||||
|
||||
export interface CarouselInternalState { |
||||
itemWidth: number; |
||||
containerWidth: number; |
||||
slidesToShow: number; |
||||
currentSlide: number; |
||||
totalItems: number; |
||||
domLoaded: boolean; |
||||
deviceType?: string; |
||||
transform: number; |
||||
} |
||||
|
||||
export default class Carousel extends React.Component<CarouselProps> { |
||||
previous: (slidesHavePassed: number) => void; |
||||
next: (slidesHavePassed: number) => void; |
||||
goToSlide: (slide: number, skipCallbacks?: SkipCallbackOptions) => void; |
||||
state: CarouselInternalState; |
||||
setClones: ( |
||||
slidesToShow: number, |
||||
itemWidth?: number, |
||||
forResizing?: boolean |
||||
) => void; // reset carousel in infinite mode.
|
||||
setItemsToShow: (shouldCorrectItemPosition?: boolean) => void; // reset carousel in non-infinite mode.
|
||||
correctClonesPosition: ({ domLoaded }: { domLoaded: boolean }) => void; |
||||
onMove: boolean; |
||||
direction: Direction; |
||||
containerRef: React.RefObject<HTMLDivElement>; |
||||
} |
@ -0,0 +1,28 @@ |
||||
/* eslint-disable @typescript-eslint/no-unused-vars */ |
||||
import React, { useContext } from 'react' |
||||
interface WorkspaceTemplateProps { |
||||
gsID: string, |
||||
workspaceTitle: string, |
||||
callback: any, |
||||
description: string, |
||||
} |
||||
|
||||
function WorkspaceTemplate ({ gsID, workspaceTitle, description, callback }: WorkspaceTemplateProps) { |
||||
|
||||
return ( |
||||
<div className="d-flex remixui_home_workspaceTemplate"> |
||||
<button |
||||
className="btn border-secondary p-1 d-flex flex-column text-nowrap justify-content-center align-items-center mr-2 remixui_home_workspaceTemplate" |
||||
data-id={'landingPageStart' + gsID} |
||||
onClick={() => callback()} |
||||
> |
||||
<div className="w-100 p-2 h-100 align-items-start d-flex flex-column"> |
||||
<label className="h6 pb-1 text-uppercase text-dark remixui_home_cursorStyle">{workspaceTitle}</label> |
||||
<div className="remixui_home_gtDescription">{description}</div> |
||||
</div> |
||||
</button> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export default WorkspaceTemplate |
@ -1,12 +1,20 @@ |
||||
import React from 'react' |
||||
interface BasicLogoProps { |
||||
classList?: string, |
||||
solid?: boolean |
||||
} |
||||
|
||||
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> |
||||
) |
||||
function BasicLogo ({classList = "", solid = true}: BasicLogoProps) { |
||||
if (solid) { |
||||
return (<svg id="Ebene_2" className={classList} 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> |
||||
) |
||||
} else { |
||||
return (<img className="" src="assets/img/remix_logo_light.webp" style={{height: "3rem"}} alt=""></img>) |
||||
} |
||||
} |
||||
|
||||
export default BasicLogo |
||||
export default BasicLogo |