diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cd54cb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/.bin/acorn +node_modules/ \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..7cfdc70 --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "uva-preact", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "eslint src && preact test", + "start": "if-env NODE_ENV=production && npm run -s serve || npm run -s dev", + "build": "preact build", + "serve": "preact build && preact serve", + "dev": "preact watch" + }, + "keywords": [], + "author": "", + "license": "ISC", + "eslintConfig": { + "extends": "eslint-config-synacor" + }, + "devDependencies": { + "eslint": "^4.15.0", + "eslint-config-synacor": "^2.0.4", + "if-env": "^1.0.0", + "node-sass": "^4.7.2", + "preact-cli": "^2.1.0", + "sass-loader": "^6.0.6" + }, + "dependencies": { + "preact": "^8.2.7", + "preact-compat": "^3.17.0", + "preact-router": "^2.6.0" + } +} diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico new file mode 100644 index 0000000..0741914 Binary files /dev/null and b/src/assets/favicon.ico differ diff --git a/src/assets/icons/android-chrome-192x192.png b/src/assets/icons/android-chrome-192x192.png new file mode 100644 index 0000000..93ebe2e Binary files /dev/null and b/src/assets/icons/android-chrome-192x192.png differ diff --git a/src/assets/icons/android-chrome-512x512.png b/src/assets/icons/android-chrome-512x512.png new file mode 100644 index 0000000..52d1623 Binary files /dev/null and b/src/assets/icons/android-chrome-512x512.png differ diff --git a/src/assets/icons/apple-touch-icon.png b/src/assets/icons/apple-touch-icon.png new file mode 100644 index 0000000..254e4bb Binary files /dev/null and b/src/assets/icons/apple-touch-icon.png differ diff --git a/src/assets/icons/favicon-16x16.png b/src/assets/icons/favicon-16x16.png new file mode 100644 index 0000000..e81177d Binary files /dev/null and b/src/assets/icons/favicon-16x16.png differ diff --git a/src/assets/icons/favicon-32x32.png b/src/assets/icons/favicon-32x32.png new file mode 100644 index 0000000..40e9b5b Binary files /dev/null and b/src/assets/icons/favicon-32x32.png differ diff --git a/src/assets/icons/mstile-150x150.png b/src/assets/icons/mstile-150x150.png new file mode 100644 index 0000000..9cfb889 Binary files /dev/null and b/src/assets/icons/mstile-150x150.png differ diff --git a/src/components/app.js b/src/components/app.js new file mode 100644 index 0000000..f3c4a84 --- /dev/null +++ b/src/components/app.js @@ -0,0 +1,31 @@ +import { h, Component } from 'preact'; +import { Router } from 'preact-router'; + +import Header from './header'; +import Home from '../routes/home'; +import Profile from '../routes/profile'; +// import Home from 'async!./home'; +// import Profile from 'async!./profile'; + +export default class App extends Component { + /** Gets fired when the route changes. + * @param {Object} event "change" event from [preact-router](http://git.io/preact-router) + * @param {string} event.url The newly routed URL + */ + handleRoute = e => { + this.currentUrl = e.url; + }; + + render() { + return ( +
+
+ + + + + +
+ ); + } +} diff --git a/src/components/header/index.js b/src/components/header/index.js new file mode 100644 index 0000000..c79e433 --- /dev/null +++ b/src/components/header/index.js @@ -0,0 +1,18 @@ +import { h, Component } from 'preact'; +import { Link } from 'preact-router/match'; +import style from './style'; + +export default class Header extends Component { + render() { + return ( +
+

Preact App

+ +
+ ); + } +} diff --git a/src/components/header/style.scss b/src/components/header/style.scss new file mode 100644 index 0000000..f08fda7 --- /dev/null +++ b/src/components/header/style.scss @@ -0,0 +1,48 @@ +.header { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 56px; + padding: 0; + background: #673AB7; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.5); + z-index: 50; +} + +.header h1 { + float: left; + margin: 0; + padding: 0 15px; + font-size: 24px; + line-height: 56px; + font-weight: 400; + color: #FFF; +} + +.header nav { + float: right; + font-size: 100%; +} + +.header nav a { + display: inline-block; + height: 56px; + line-height: 56px; + padding: 0 15px; + min-width: 50px; + text-align: center; + background: rgba(255,255,255,0); + text-decoration: none; + color: #FFF; + will-change: background-color; +} + +.header nav a:hover, +.header nav a:active { + background: rgba(0,0,0,0.2); +} + +.header nav a.active { + background: rgba(0,0,0,0.4); +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..009d937 --- /dev/null +++ b/src/index.js @@ -0,0 +1,4 @@ +import './style'; +import App from './components/app'; + +export default App; diff --git a/src/manifest.json b/src/manifest.json new file mode 100644 index 0000000..55ca625 --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,19 @@ +{ + "name": "Preact PWA", + "short_name": "Preact PWA", + "start_url": "/", + "display": "standalone", + "orientation": "portrait", + "background_color": "#fff", + "theme_color": "#673ab8", + "icons": [{ + "src": "/assets/icons/android-chrome-192x192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "/assets/icons/android-chrome-512x512.png", + "type": "image/png", + "sizes": "512x512" + }] +} diff --git a/src/routes/home/index.js b/src/routes/home/index.js new file mode 100644 index 0000000..009daaf --- /dev/null +++ b/src/routes/home/index.js @@ -0,0 +1,13 @@ +import { h, Component } from 'preact'; +import style from './style'; + +export default class Home extends Component { + render() { + return ( +
+

Home

+

This is the Home component.

+
+ ); + } +} diff --git a/src/routes/home/style.scss b/src/routes/home/style.scss new file mode 100644 index 0000000..f052d25 --- /dev/null +++ b/src/routes/home/style.scss @@ -0,0 +1,5 @@ +.home { + padding: 56px 20px; + min-height: 100%; + width: 100%; +} diff --git a/src/routes/profile/index.js b/src/routes/profile/index.js new file mode 100644 index 0000000..164b259 --- /dev/null +++ b/src/routes/profile/index.js @@ -0,0 +1,47 @@ +import { h, Component } from 'preact'; +import style from './style'; + +export default class Profile extends Component { + state = { + time: Date.now(), + count: 10 + }; + + // gets called when this route is navigated to + componentDidMount() { + // start a timer for the clock: + this.timer = setInterval(this.updateTime, 1000); + } + + // gets called just before navigating away from the route + componentWillUnmount() { + clearInterval(this.timer); + } + + // update the current time + updateTime = () => { + this.setState({ time: Date.now() }); + }; + + increment = () => { + this.setState({ count: this.state.count+1 }); + }; + + // Note: `user` comes from the URL, courtesy of our router + render({ user }, { time, count }) { + return ( +
+

Profile: {user}

+

This is the user profile for a user named { user }.

+ +
Current time: {new Date(time).toLocaleString()}
+ +

+ + {' '} + Clicked {count} times. +

+
+ ); + } +} diff --git a/src/routes/profile/style.scss b/src/routes/profile/style.scss new file mode 100644 index 0000000..fcb1296 --- /dev/null +++ b/src/routes/profile/style.scss @@ -0,0 +1,5 @@ +.profile { + padding: 56px 20px; + min-height: 100%; + width: 100%; +} diff --git a/src/style/index.scss b/src/style/index.scss new file mode 100644 index 0000000..5fe95de --- /dev/null +++ b/src/style/index.scss @@ -0,0 +1,20 @@ +html, body { + height: 100%; + width: 100%; + padding: 0; + margin: 0; + background: #FAFAFA; + font-family: 'Helvetica Neue', arial, sans-serif; + font-weight: 400; + color: #444; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + box-sizing: border-box; +} + +#app { + height: 100%; +}