Initial commit
This commit is contained in:
commit
56d40196d6
15 changed files with 490 additions and 0 deletions
8
src/actions.js
Normal file
8
src/actions.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export const themeActions = {
|
||||
THEME_CHANGE: 'THEME_CHANGE'
|
||||
}
|
||||
|
||||
export const changeTheme = (new_theme) => ({
|
||||
type: themeActions.THEME_CHANGE,
|
||||
theme: new_theme
|
||||
})
|
||||
35
src/index.jsx
Normal file
35
src/index.jsx
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
`use strict`
|
||||
import { render } from 'inferno'
|
||||
import { Provider } from 'inferno-redux';
|
||||
import { applyMiddleware, createStore, combineReducers } from 'redux';
|
||||
|
||||
import { themeReducer } from './reducers';
|
||||
|
||||
import Main from './main.jsx'
|
||||
|
||||
const logger = process.env.DEBUG ? store => next => action => {
|
||||
console.group(action.type)
|
||||
console.info('dispatching', action)
|
||||
let result = next(action)
|
||||
console.log('next state', store.getState())
|
||||
console.groupEnd()
|
||||
return result
|
||||
} : null
|
||||
|
||||
const persistedState = localStorage.getItem('reduxState')
|
||||
const initState = persistedState ? JSON.parse(persistedState) : {}
|
||||
|
||||
const reducers = combineReducers(
|
||||
{theme: themeReducer})
|
||||
const store = process.env.DEBUG ?
|
||||
createStore(reducers, initState, applyMiddleware(logger)) : createStore(reducers, initState)
|
||||
|
||||
store.subscribe(() => {
|
||||
localStorage.setItem('reduxState', JSON.stringify(store.getState()))
|
||||
})
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<Main />
|
||||
</Provider>,
|
||||
document.getElementById("root"))
|
||||
77
src/main.css
Normal file
77
src/main.css
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
*, ::after, ::before
|
||||
{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
background-color: var(--main-bg-color);
|
||||
color: var(--main-fg-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* START switch */
|
||||
input:checked + .slider::before {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slider.round
|
||||
{
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.slider
|
||||
{
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--light-primary-color);
|
||||
border: 1px solid var(--light-primary-color);
|
||||
}
|
||||
|
||||
.slider.round::before
|
||||
{
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.slider::before
|
||||
{
|
||||
background-color: var(--main-primary-color);
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
left: 2px;
|
||||
bottom: 1px;
|
||||
transition: background-color 1s, transform .4s;
|
||||
}
|
||||
|
||||
.switch
|
||||
{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 19px;
|
||||
}
|
||||
/* END switch */
|
||||
|
||||
#ayo_logo
|
||||
{
|
||||
width: 200px;
|
||||
fill: var(--main-fg-color);
|
||||
}
|
||||
60
src/main.jsx
Normal file
60
src/main.jsx
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
`use strict`
|
||||
import { Component } from 'inferno'
|
||||
import { connect } from 'inferno-redux';
|
||||
|
||||
import { changeTheme } from './actions';
|
||||
import { Svg } from './svg.jsx'
|
||||
|
||||
import './main.css'
|
||||
import Logo from '../assets/logo.svg'
|
||||
|
||||
class MainComponent extends Component
|
||||
{
|
||||
componentDidMount()
|
||||
{
|
||||
// Smooth color transitions (after rendering to avoid flash on reload)
|
||||
setTimeout(() => {
|
||||
const styleEl = document.head.getElementsByTagName('style')[0]
|
||||
document.head.appendChild(styleEl)
|
||||
const styleSheet = styleEl.sheet
|
||||
styleSheet.insertRule(
|
||||
'*, ::after, ::before { transition-property: background-color, color, fill; transition-duration: 1s;}')
|
||||
},
|
||||
500)
|
||||
}
|
||||
|
||||
toggleTheme(event)
|
||||
{
|
||||
this.props.changeTheme(event.target.checked ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
return (
|
||||
<div>
|
||||
<link rel="stylesheet" type="text/css" href={'/assets/theme/' + this.props.theme + '.css'} />
|
||||
<nav>
|
||||
<Svg url={Logo}/>
|
||||
<label className="switch" htmlFor="switch-theme">
|
||||
<input type="checkbox" id="switch-theme"
|
||||
defaultChecked={this.props.theme == 'dark'}
|
||||
onChange={(event) => this.toggleTheme(event)}/>
|
||||
<div className="slider round"></div>
|
||||
</label>
|
||||
</nav>
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
theme: state.theme
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
changeTheme: theme => dispatch(changeTheme(theme))
|
||||
})
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(MainComponent)
|
||||
11
src/reducers.js
Normal file
11
src/reducers.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { themeActions } from './actions.js'
|
||||
|
||||
export const themeReducer = (state = 'light', action) => {
|
||||
switch (action.type)
|
||||
{
|
||||
case themeActions.THEME_CHANGE:
|
||||
return action.theme
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
35
src/svg.jsx
Normal file
35
src/svg.jsx
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
`use strict`
|
||||
import { Component } from 'inferno'
|
||||
|
||||
export class Svg extends Component
|
||||
{
|
||||
constructor(props)
|
||||
{
|
||||
super(props)
|
||||
this.state = {
|
||||
svg: null,
|
||||
loading: false
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount()
|
||||
{
|
||||
fetch(this.props.url)
|
||||
.then(res => res.text())
|
||||
.then(text => this.setState({ svg: text }))
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const { loading, svg } = this.state;
|
||||
if (loading)
|
||||
{
|
||||
return <span className="spinner"/>
|
||||
}
|
||||
else if(!svg)
|
||||
{
|
||||
return <span className="error"/>
|
||||
}
|
||||
return <span dangerouslySetInnerHTML={{ __html: this.state.svg}}/>
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue