forked from external-repos/squoosh
Adds an app skeleton. Still needs some work.
This commit is contained in:
33
.babelrc
Normal file
33
.babelrc
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"env",
|
||||||
|
{
|
||||||
|
"loose": true,
|
||||||
|
"uglify": true,
|
||||||
|
"modules": "commonjs",
|
||||||
|
"targets": {
|
||||||
|
"browsers": "last 2 versions"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"transform-regenerator",
|
||||||
|
"transform-es2015-typeof-symbol"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"syntax-dynamic-import",
|
||||||
|
"transform-decorators-legacy",
|
||||||
|
"transform-class-properties",
|
||||||
|
"transform-object-rest-spread",
|
||||||
|
"transform-react-constant-elements",
|
||||||
|
"transform-react-remove-prop-types",
|
||||||
|
[
|
||||||
|
"transform-react-jsx",
|
||||||
|
{
|
||||||
|
"pragma": "h"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
29
config/async-component-loader.js
Normal file
29
config/async-component-loader.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
let loaderUtils = require('loader-utils');
|
||||||
|
let componentPath = require.resolve('./async-component');
|
||||||
|
|
||||||
|
module.exports = function () { };
|
||||||
|
module.exports.pitch = function (remainingRequest) {
|
||||||
|
this.cacheable && this.cacheable();
|
||||||
|
let query = loaderUtils.getOptions(this) || {};
|
||||||
|
let routeName = typeof query.name === 'function' ? query.name(this.resourcePath) : null;
|
||||||
|
let name;
|
||||||
|
if (routeName !== null) {
|
||||||
|
name = routeName;
|
||||||
|
}
|
||||||
|
else if ('name' in query) {
|
||||||
|
name = query.name;
|
||||||
|
}
|
||||||
|
else if ('formatName' in query) {
|
||||||
|
name = query.formatName(this.resourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
import async from ${JSON.stringify(componentPath)};
|
||||||
|
function load(cb) {
|
||||||
|
require.ensure([], function (require) {
|
||||||
|
cb( require(${loaderUtils.stringifyRequest(this, '!!' + remainingRequest)}) );
|
||||||
|
}${name ? (', ' + JSON.stringify(name)) : ''});
|
||||||
|
}
|
||||||
|
export default async(load);
|
||||||
|
`;
|
||||||
|
};
|
||||||
30
config/async-component.js
Normal file
30
config/async-component.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
|
||||||
|
export default function (req) {
|
||||||
|
function Async() {
|
||||||
|
Component.call(this);
|
||||||
|
|
||||||
|
let b, old;
|
||||||
|
this.componentWillMount = () => {
|
||||||
|
b = this.base = this.nextBase || this.__b; // short circuits 1st render
|
||||||
|
req(m => {
|
||||||
|
this.setState({ child: m.default || m });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.shouldComponentUpdate = (_, nxt) => {
|
||||||
|
nxt = nxt.child === void 0;
|
||||||
|
if (nxt && old === void 0 && !!b) {
|
||||||
|
old = h(b.nodeName, { dangerouslySetInnerHTML: { __html: b.innerHTML } });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
old = ''; // dump it
|
||||||
|
}
|
||||||
|
return !nxt;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.render = (p, s) => s.child ? h(s.child, p) : old;
|
||||||
|
}
|
||||||
|
(Async.prototype = new Component()).constructor = Async;
|
||||||
|
return Async;
|
||||||
|
}
|
||||||
27
config/client-boot.js
Normal file
27
config/client-boot.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { h, render } from 'preact';
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
// enable preact devtools
|
||||||
|
require('preact/debug');
|
||||||
|
}
|
||||||
|
else if (process.env.ADD_SW && 'serviceWorker' in navigator && location.protocol === 'https:') {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
navigator.serviceWorker.register(__webpack_public_path__ + 'sw.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
const interopDefault = m => m && m.default ? m.default : m;
|
||||||
|
|
||||||
|
let app = interopDefault(require('app-entry-point'));
|
||||||
|
|
||||||
|
if (typeof app === 'function') {
|
||||||
|
let root = document.getElementById('app') || document.body.firstElementChild;
|
||||||
|
|
||||||
|
let init = () => {
|
||||||
|
let app = interopDefault(require('app-entry-point'));
|
||||||
|
root = render(h(app), document.body, root);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (module.hot) module.hot.accept('app-entry-point', init);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
20
config/prerender.js
Normal file
20
config/prerender.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
let path = require('path');
|
||||||
|
let preact = require('preact');
|
||||||
|
let renderToString = require('preact-render-to-string');
|
||||||
|
|
||||||
|
let appPath = path.join(__dirname, '../src/index');
|
||||||
|
|
||||||
|
module.exports = function(options) {
|
||||||
|
options = options || {};
|
||||||
|
let url = typeof options==='string' ? options : options.url;
|
||||||
|
global.history = {};
|
||||||
|
global.location = { href: url, pathname: url };
|
||||||
|
|
||||||
|
// let app = require('app-entry-point');
|
||||||
|
let app = require(appPath);
|
||||||
|
|
||||||
|
let html = renderToString(preact.h(app, { url }));
|
||||||
|
console.log(html);
|
||||||
|
|
||||||
|
return html;
|
||||||
|
};
|
||||||
23
config/watch-timestamps-plugin.js
Normal file
23
config/watch-timestamps-plugin.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
let fs = require('fs');
|
||||||
|
|
||||||
|
module.exports = WatchTimestampsPlugin;
|
||||||
|
|
||||||
|
function WatchTimestampsPlugin(patterns) {
|
||||||
|
this.patterns = patterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchTimestampsPlugin.prototype.apply = function (compiler) {
|
||||||
|
compiler.plugin('watch-run', (watch, callback) => {
|
||||||
|
let patterns = this.patterns;
|
||||||
|
let timestamps = watch.fileTimestamps || watch.compiler.fileTimestamps;
|
||||||
|
|
||||||
|
Object.keys(timestamps).forEach( filepath => {
|
||||||
|
if (patterns.some( pat => pat instanceof RegExp ? pat.test(filepath) : filepath.indexOf(pat)===0 )) {
|
||||||
|
let time = fs.statSync(filepath).mtime;
|
||||||
|
if (timestamps instanceof Map) timestamps.set(filepath, time);
|
||||||
|
else timestamps[filepath] = time;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
0
global.d.ts
vendored
Normal file
0
global.d.ts
vendored
Normal file
1970
package-lock.json
generated
1970
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"license": "apache-2.0",
|
"license": "apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack-dev-server --hot",
|
"start": "webpack serve --hot --inline",
|
||||||
"build": "webpack -p",
|
"build": "webpack -p",
|
||||||
"lint": "eslint src"
|
"lint": "eslint src"
|
||||||
},
|
},
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
"build/*"
|
"build/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/node": "^9.4.7",
|
||||||
"awesome-typescript-loader": "^4.0.1",
|
"awesome-typescript-loader": "^4.0.1",
|
||||||
"babel-loader": "^7.1.4",
|
"babel-loader": "^7.1.4",
|
||||||
"babel-plugin-jsx-pragmatic": "^1.0.2",
|
"babel-plugin-jsx-pragmatic": "^1.0.2",
|
||||||
@@ -29,25 +30,39 @@
|
|||||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.13",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.13",
|
||||||
"babel-preset-env": "^1.6.1",
|
"babel-preset-env": "^1.6.1",
|
||||||
|
"babel-register": "^6.26.0",
|
||||||
|
"copy-webpack-plugin": "^4.5.1",
|
||||||
"css-loader": "^0.28.10",
|
"css-loader": "^0.28.10",
|
||||||
|
"ejs-loader": "^0.3.1",
|
||||||
"eslint": "^4.18.2",
|
"eslint": "^4.18.2",
|
||||||
"eslint-config-developit": "^1.1.1",
|
"eslint-config-developit": "^1.1.1",
|
||||||
|
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||||
"html-webpack-plugin": "^3.0.6",
|
"html-webpack-plugin": "^3.0.6",
|
||||||
"if-env": "^1.0.4",
|
"if-env": "^1.0.4",
|
||||||
"mini-css-extract-plugin": "^0.2.0",
|
"mini-css-extract-plugin": "^0.2.0",
|
||||||
"node-sass": "^4.7.2",
|
"node-sass": "^4.7.2",
|
||||||
|
"preact-render-to-string": "^3.7.0",
|
||||||
|
"preload-webpack-plugin": "github:GoogleChromeLabs/preload-webpack-plugin",
|
||||||
"sass-loader": "^6.0.7",
|
"sass-loader": "^6.0.7",
|
||||||
|
"script-ext-html-webpack-plugin": "^2.0.0",
|
||||||
|
"style-loader": "^0.20.3",
|
||||||
|
"typescript": "^2.7.2",
|
||||||
"typescript-loader": "^1.1.3",
|
"typescript-loader": "^1.1.3",
|
||||||
|
"typings-for-css-modules-loader": "^1.7.0",
|
||||||
"webpack": "^4.1.1",
|
"webpack": "^4.1.1",
|
||||||
"webpack-cli": "^2.0.10",
|
"webpack-cli": "^2.0.11",
|
||||||
"webpack-dev-server": "^3.1.0"
|
"webpack-dev-server": "^3.1.1",
|
||||||
|
"webpack-plugin-replace": "^1.1.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"material-components-web": "^0.31.0",
|
"classnames": "^2.2.5",
|
||||||
|
"material-components-web": "^0.32.0",
|
||||||
"material-radial-progress": "git+https://gist.github.com/02134901c77c5309924bfcf8b4435ebe.git",
|
"material-radial-progress": "git+https://gist.github.com/02134901c77c5309924bfcf8b4435ebe.git",
|
||||||
"preact": "^8.2.7",
|
"preact": "^8.2.7",
|
||||||
"preact-i18n": "^1.2.0",
|
"preact-i18n": "^1.2.0",
|
||||||
"preact-material-components": "^1.3.7",
|
"preact-material-components": "^1.3.7",
|
||||||
"preact-router": "^2.6.0"
|
"preact-material-components-drawer": "git+https://gist.github.com/a78fceed440b98e62582e4440b86bfab.git",
|
||||||
|
"preact-router": "^2.6.0",
|
||||||
|
"ts-loader": "^4.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import { Component } from 'preact';
|
|
||||||
import { updater, toggle } from '../../lib/util';
|
|
||||||
import Fab from '../fab';
|
|
||||||
import Header from '../header';
|
|
||||||
import Drawer from '../drawer';
|
|
||||||
import Home from '../home';
|
|
||||||
import style from './style';
|
|
||||||
|
|
||||||
export default class App extends Component {
|
|
||||||
state = {
|
|
||||||
showDrawer: false,
|
|
||||||
showFab: true
|
|
||||||
};
|
|
||||||
|
|
||||||
openDrawer = updater(this, 'showDrawer', true);
|
|
||||||
closeDrawer = updater(this, 'showDrawer', false);
|
|
||||||
toggleDrawer = updater(this, 'showDrawer', toggle);
|
|
||||||
|
|
||||||
openFab = updater(this, 'showFab', true);
|
|
||||||
closeFab = updater(this, 'showFab', false);
|
|
||||||
toggleFab = updater(this, 'showFab', toggle);
|
|
||||||
|
|
||||||
render({ url }, { showDrawer, showFab }) {
|
|
||||||
return (
|
|
||||||
<div id="app" class={style.app}>
|
|
||||||
<Fab showing={showFab} />
|
|
||||||
<Header toggleDrawer={this.toggleDrawer} />
|
|
||||||
<Drawer showing={showDrawer} openDrawer={this.openDrawer} closeDrawer={this.closeDrawer} />
|
|
||||||
<div class={style.content} paint-outside>
|
|
||||||
<Home />
|
|
||||||
</div>
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
110
src/components/app/index.tsx
Normal file
110
src/components/app/index.tsx
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
import { updater, toggle, When } from '../../lib/util';
|
||||||
|
import Fab from '../fab';
|
||||||
|
import Header from '../header';
|
||||||
|
// import Drawer from 'async!../drawer';
|
||||||
|
import Home from '../home';
|
||||||
|
import * as style from './style.scss';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
url?: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileObj = {
|
||||||
|
id: any,
|
||||||
|
data: any,
|
||||||
|
error: Error | DOMError | String,
|
||||||
|
file: File,
|
||||||
|
loading: Boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
showDrawer: Boolean,
|
||||||
|
showFab: Boolean,
|
||||||
|
files: FileObj[]
|
||||||
|
};
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
export default class App extends Component<Props, State> {
|
||||||
|
state: State = {
|
||||||
|
showDrawer: false,
|
||||||
|
showFab: true,
|
||||||
|
files: []
|
||||||
|
};
|
||||||
|
|
||||||
|
loadFile = (file: File) => {
|
||||||
|
let fileObj = {
|
||||||
|
id: ++counter,
|
||||||
|
file,
|
||||||
|
error: null,
|
||||||
|
loading: true,
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
files: [fileObj]
|
||||||
|
});
|
||||||
|
|
||||||
|
let fr = new FileReader();
|
||||||
|
// fr.readAsArrayBuffer();
|
||||||
|
fr.onerror = () => {
|
||||||
|
let files = this.state.files.slice();
|
||||||
|
files.splice(0, files.indexOf(fileObj), {
|
||||||
|
...fileObj,
|
||||||
|
error: fr.error,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
this.setState({ files });
|
||||||
|
};
|
||||||
|
fr.onloadend = () => {
|
||||||
|
let files = this.state.files.slice();
|
||||||
|
files.splice(0, files.indexOf(fileObj), {
|
||||||
|
...fileObj,
|
||||||
|
data: fr.result,
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
this.setState({ files });
|
||||||
|
};
|
||||||
|
fr.readAsDataURL(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
enableDrawer = false;
|
||||||
|
|
||||||
|
openDrawer = updater(this, 'showDrawer', true);
|
||||||
|
closeDrawer = updater(this, 'showDrawer', false);
|
||||||
|
toggleDrawer = updater(this, 'showDrawer', toggle);
|
||||||
|
|
||||||
|
openFab = updater(this, 'showFab', true);
|
||||||
|
closeFab = updater(this, 'showFab', false);
|
||||||
|
toggleFab = updater(this, 'showFab', toggle);
|
||||||
|
|
||||||
|
render({ url }, { showDrawer, showFab, files }) {
|
||||||
|
if (showDrawer) this.enableDrawer = true;
|
||||||
|
return (
|
||||||
|
<div id="app" class={style.app}>
|
||||||
|
<Fab showing={showFab} />
|
||||||
|
|
||||||
|
<Header toggleDrawer={this.toggleDrawer} loadFile={this.loadFile} />
|
||||||
|
|
||||||
|
{/* Avoid loading & rendering the drawer until the first time it is shown. */}
|
||||||
|
{/*
|
||||||
|
<When value={showDrawer}>
|
||||||
|
<Drawer showing={showDrawer} openDrawer={this.openDrawer} closeDrawer={this.closeDrawer} />
|
||||||
|
</When>
|
||||||
|
*/}
|
||||||
|
|
||||||
|
{/*
|
||||||
|
Note: this is normally where a <Router> with auto code-splitting goes.
|
||||||
|
Since we don't seem to need one (yet?), it's omitted.
|
||||||
|
*/}
|
||||||
|
<div class={style.content}>
|
||||||
|
<Home files={files} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* This ends up in the body when prerendered, which makes it load async. */}
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/components/app/style.scss.d.ts
vendored
Normal file
2
src/components/app/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const app: string;
|
||||||
|
export const content: string;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import MdlDrawer from 'preact-material-components-drawer';
|
import MdlDrawer from 'preact-material-components-drawer';
|
||||||
import 'preact-material-components/Drawer/style.css';
|
import 'preact-material-components/Drawer/style.css';
|
||||||
import List from 'preact-material-components/List';
|
import List from 'preact-material-components/List';
|
||||||
@@ -7,14 +7,27 @@ import { Text } from 'preact-i18n';
|
|||||||
import style from './style';
|
import style from './style';
|
||||||
|
|
||||||
export default class Drawer extends Component {
|
export default class Drawer extends Component {
|
||||||
render({ showing, openDrawer, closeDrawer }) {
|
state = {
|
||||||
|
rendered: false
|
||||||
|
};
|
||||||
|
|
||||||
|
setRendered = () => {
|
||||||
|
this.setState({ rendered: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
render({ showing, openDrawer, closeDrawer }, { rendered }) {
|
||||||
|
if (showing && !rendered) {
|
||||||
|
setTimeout(this.setRendered, 20);
|
||||||
|
showing = false;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MdlDrawer open={showing} onOpen={openDrawer} onClose={closeDrawer}>
|
<MdlDrawer open={showing} onOpen={openDrawer} onClose={closeDrawer}>
|
||||||
<MdlDrawer.Header autosize class="mdc-theme--primary-bg">
|
<MdlDrawer.Header class="mdc-theme--primary-bg">
|
||||||
<img class={style.logo} alt="logo" src="/assets/icon.png" />
|
<img class={style.logo} alt="logo" src="/assets/icon.png" />
|
||||||
</MdlDrawer.Header>
|
</MdlDrawer.Header>
|
||||||
<MdlDrawer.Content autosize class={style.list}>
|
<MdlDrawer.Content class={style.list}>
|
||||||
<List autosize>
|
<List>
|
||||||
<List.LinkItem href="/">
|
<List.LinkItem href="/">
|
||||||
<List.ItemIcon>verified_user</List.ItemIcon>
|
<List.ItemIcon>verified_user</List.ItemIcon>
|
||||||
<Text id="SIGN_IN">Sign In</Text>
|
<Text id="SIGN_IN">Sign In</Text>
|
||||||
@@ -26,7 +39,7 @@ export default class Drawer extends Component {
|
|||||||
</List>
|
</List>
|
||||||
</MdlDrawer.Content>
|
</MdlDrawer.Content>
|
||||||
|
|
||||||
<div class={style.bottom} autosize>
|
<div class={style.bottom}>
|
||||||
<List.LinkItem href="/preferences">
|
<List.LinkItem href="/preferences">
|
||||||
<List.ItemIcon>settings</List.ItemIcon>
|
<List.ItemIcon>settings</List.ItemIcon>
|
||||||
<Text id="PREFERENCES">Preferences</Text>
|
<Text id="PREFERENCES">Preferences</Text>
|
||||||
|
|||||||
14
src/components/drawer/style.scss.d.ts
vendored
Normal file
14
src/components/drawer/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export const mdcListItemSecondaryText: string;
|
||||||
|
export const mdcListItemGraphic: string;
|
||||||
|
export const mdcListItemMeta: string;
|
||||||
|
export const mdcListItem: string;
|
||||||
|
export const mdcListDivider: string;
|
||||||
|
export const mdcListGroup: string;
|
||||||
|
export const mdcListGroupSubheader: string;
|
||||||
|
export const drawer: string;
|
||||||
|
export const logo: string;
|
||||||
|
export const category: string;
|
||||||
|
export const bottom: string;
|
||||||
|
export const mdcRippleFgRadiusIn: string;
|
||||||
|
export const mdcRippleFgOpacityIn: string;
|
||||||
|
export const mdcRippleFgOpacityOut: string;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import Icon from 'preact-material-components/Icon';
|
import Icon from 'preact-material-components/Icon';
|
||||||
import 'preact-material-components/Icon/style.css';
|
import 'preact-material-components/Icon/style.css';
|
||||||
import Fab from 'preact-material-components/Fab';
|
import Fab from 'preact-material-components/Fab';
|
||||||
@@ -20,7 +20,7 @@ export default class AppFab extends Component {
|
|||||||
{ loading ? (
|
{ loading ? (
|
||||||
<RadialProgress primary class={style.progress} />
|
<RadialProgress primary class={style.progress} />
|
||||||
) : (
|
) : (
|
||||||
<Icon autosize>file_download</Icon>
|
<Icon>file_download</Icon>
|
||||||
) }
|
) }
|
||||||
</Fab>
|
</Fab>
|
||||||
);
|
);
|
||||||
|
|||||||
5
src/components/fab/style.scss.d.ts
vendored
Normal file
5
src/components/fab/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const fab: string;
|
||||||
|
export const progress: string;
|
||||||
|
export const mdcRippleFgRadiusIn: string;
|
||||||
|
export const mdcRippleFgOpacityIn: string;
|
||||||
|
export const mdcRippleFgOpacityOut: string;
|
||||||
@@ -1,34 +1,45 @@
|
|||||||
import { Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import Toolbar from 'preact-material-components/Toolbar';
|
import Toolbar from 'preact-material-components/Toolbar';
|
||||||
// import 'preact-material-components/Toolbar/mdc-toolbar.scss';
|
import cx from 'classnames';
|
||||||
// import Icon from 'preact-material-components/Icon';
|
|
||||||
// import 'preact-material-components/Icon/style.css';
|
|
||||||
// import Fab from 'preact-material-components/Fab';
|
|
||||||
// import 'preact-material-components/Fab/mdc-fab.scss';
|
|
||||||
import style from './style';
|
import style from './style';
|
||||||
|
|
||||||
export default class Header extends Component {
|
export default class Header extends Component {
|
||||||
// fabClick = () => {
|
setInputRef = c => {
|
||||||
// alert("Hello");
|
this.input = c;
|
||||||
// };
|
};
|
||||||
|
|
||||||
|
handleFiles = () => {
|
||||||
|
let files = this.input.files;
|
||||||
|
if (files.length) {
|
||||||
|
this.props.loadFile(files[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
upload = () => {
|
||||||
|
// let input = document.createElement('input');
|
||||||
|
// input.type = 'file';
|
||||||
|
// // input.multiple = true;
|
||||||
|
// document.body.appendChild(input);
|
||||||
|
// input.addEventListener('change', e => {
|
||||||
|
|
||||||
|
// });
|
||||||
|
// input.click();
|
||||||
|
this.input.click();
|
||||||
|
};
|
||||||
|
|
||||||
render({ toggleDrawer, showHeader, showFab }) {
|
render({ toggleDrawer, showHeader, showFab }) {
|
||||||
return (
|
return (
|
||||||
<Toolbar class={`${style.toolbar} ${showHeader === false ? style.minimal : ''} inert`} fixed>
|
<Toolbar fixed class={cx(style.toolbar, 'inert', showHeader===false && style.minimal)}>
|
||||||
<Toolbar.Row>
|
<Toolbar.Row>
|
||||||
<Toolbar.Title autosize class={style.title}>
|
<Toolbar.Title class={style.title}>
|
||||||
<img class={style.logo} src="/assets/icon.png" />
|
<img class={style.logo} src="/assets/icon.png" />
|
||||||
|
<Toolbar.Icon ripple onClick={this.upload}>file_upload</Toolbar.Icon>
|
||||||
</Toolbar.Title>
|
</Toolbar.Title>
|
||||||
<Toolbar.Section autosize align-end>
|
<Toolbar.Section align-end>
|
||||||
<Toolbar.Icon autosize menu onClick={toggleDrawer}>menu</Toolbar.Icon>
|
<Toolbar.Icon ripple onClick={toggleDrawer}>menu</Toolbar.Icon>
|
||||||
</Toolbar.Section>
|
</Toolbar.Section>
|
||||||
</Toolbar.Row>
|
</Toolbar.Row>
|
||||||
|
<input class={style.fileInput} ref={this.setInputRef} type="file" onChange={this.handleFiles} />
|
||||||
{/*
|
|
||||||
<Fab class={style.fab} exited={showFab===false} ripple onClick={this.fabClick}>
|
|
||||||
<Icon>create</Icon>
|
|
||||||
</Fab>
|
|
||||||
*/}
|
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,12 @@
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fileInput {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: -999px;
|
||||||
|
}
|
||||||
|
|
||||||
.fab {
|
.fab {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
8
src/components/header/style.scss.d.ts
vendored
Normal file
8
src/components/header/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const toolbar: string;
|
||||||
|
export const minimal: string;
|
||||||
|
export const fileInput: string;
|
||||||
|
export const fab: string;
|
||||||
|
export const logo: string;
|
||||||
|
export const menu: string;
|
||||||
|
export const menuItem: string;
|
||||||
|
export const title: string;
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { Component } from 'preact';
|
|
||||||
// import Button from 'preact-material-components/Button';
|
|
||||||
// import Switch from 'preact-material-components/Switch';
|
|
||||||
// import 'preact-material-components/Switch/style.css';
|
|
||||||
import style from './style';
|
|
||||||
|
|
||||||
|
|
||||||
export default class Home extends Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div class={style.home}>
|
|
||||||
<h1>Home</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
src/components/home/index.tsx
Normal file
36
src/components/home/index.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { h, Component } from 'preact';
|
||||||
|
// import Button from 'preact-material-components/Button';
|
||||||
|
// import Switch from 'preact-material-components/Switch';
|
||||||
|
// import 'preact-material-components/Switch/style.css';
|
||||||
|
import * as style from './style.scss';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
files: {
|
||||||
|
data: any
|
||||||
|
}[]
|
||||||
|
};
|
||||||
|
type State = {
|
||||||
|
active: boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Home extends Component<Props, State> {
|
||||||
|
state: State = {
|
||||||
|
active: false
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
setTimeout( () => {
|
||||||
|
this.setState({ active: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render({ files }, { active }) {
|
||||||
|
return (
|
||||||
|
<div class={style.home+' '+(active ? style.active : '')}>
|
||||||
|
{ files && files[0] && (
|
||||||
|
<img src={files[0].data} />
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,4 +7,14 @@
|
|||||||
|
|
||||||
.home {
|
.home {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
animation: fadeIn 2s forwards ease 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
}
|
}
|
||||||
3
src/components/home/style.scss.d.ts
vendored
Normal file
3
src/components/home/style.scss.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const home: string;
|
||||||
|
export const active: string;
|
||||||
|
export const fadeIn: string;
|
||||||
28
src/index.html
Normal file
28
src/index.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Squoosh</title>
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<link rel="manifest" href="/manifest.json">
|
||||||
|
<!--
|
||||||
|
<% for (var chunk of webpack.chunks) { %>
|
||||||
|
<% for (var file of chunk.files) { %>
|
||||||
|
<% if (htmlWebpackPlugin.options.preload && file.match(/\.(js|css)$/)) { %>
|
||||||
|
<link rel="preload" href="<%= htmlWebpackPlugin.files.publicPath + file %>" as="<%= file.match(/\.css$/)?'style':'script' %>">
|
||||||
|
<% } else if (file.match(/manifest\.json$/)) { %>
|
||||||
|
<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath + file %>">
|
||||||
|
<% } %>
|
||||||
|
<% } %>
|
||||||
|
<% } %>
|
||||||
|
-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%=
|
||||||
|
/*require('../config/prerender')()*/
|
||||||
|
htmlWebpackPlugin.options.prerender()
|
||||||
|
%>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -13,6 +13,6 @@ if (typeof window!=='undefined') {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (target = target.parentNode);
|
} while ((target = target.parentNode));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Component } from 'preact';
|
||||||
|
|
||||||
export function updater(obj, property, value) {
|
export function updater(obj, property, value) {
|
||||||
return e => {
|
return e => {
|
||||||
let update = {};
|
let update = {};
|
||||||
@@ -8,3 +10,10 @@ export function updater(obj, property, value) {
|
|||||||
|
|
||||||
export const toggle = value => !value;
|
export const toggle = value => !value;
|
||||||
|
|
||||||
|
export class When extends Component {
|
||||||
|
state = { ready: !!this.props.value };
|
||||||
|
render({ value, children: [child] }, { ready }) {
|
||||||
|
if (value && !ready) this.setState({ ready: true });
|
||||||
|
return ready ? (typeof child === 'function' ? child() : child) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2017",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"jsxFactory": "h",
|
||||||
|
"allowJs": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,78 +1,191 @@
|
|||||||
let path = require('path');
|
let path = require('path');
|
||||||
let webpack = require('webpack');
|
let webpack = require('webpack');
|
||||||
|
// let ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
let MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
let MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
let HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
let PreloadWebpackPlugin = require('preload-webpack-plugin');
|
||||||
|
let ReplacePlugin = require('webpack-plugin-replace');
|
||||||
|
let CopyPlugin = require('copy-webpack-plugin');
|
||||||
|
let WatchTimestampsPlugin = require('./config/watch-timestamps-plugin');
|
||||||
|
|
||||||
module.exports = function(_, env) {
|
module.exports = function(_, env) {
|
||||||
|
let isProd = env.mode === 'production';
|
||||||
|
let nodeModules = path.join(__dirname, 'node_modules');
|
||||||
|
let componentStyleDirs = [
|
||||||
|
path.join(__dirname, 'src/components'),
|
||||||
|
path.join(__dirname, 'src/routes')
|
||||||
|
];
|
||||||
|
|
||||||
|
let babelRc = JSON.parse(require('fs').readFileSync('.babelrc'));
|
||||||
|
babelRc.babelrc = false;
|
||||||
|
babelRc.presets[0][1].modules = isProd ? false : 'commonjs';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mode: env.mode || 'development',
|
mode: env.mode || 'development',
|
||||||
entry: './src/index',
|
entry: path.join(__dirname, 'config/client-boot.js'),
|
||||||
|
// entry: './src/index',
|
||||||
|
output: {
|
||||||
|
filename: isProd ? '[name].[chunkhash:5].js' : '[name].js',
|
||||||
|
chunkFilename: '[name].chunk.[chunkhash:5].js',
|
||||||
|
path: path.join(__dirname, 'build'),
|
||||||
|
publicPath: '/'
|
||||||
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.ts', '.js', '.scss', '.css'],
|
extensions: ['.ts', '.tsx', '.js', '.jsx', '.scss', '.css'],
|
||||||
alias: {
|
alias: {
|
||||||
|
'app-entry-point': path.join(__dirname, 'src/index'),
|
||||||
style: path.join(__dirname, 'src/style')
|
style: path.join(__dirname, 'src/style')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resolveLoader: {
|
||||||
|
alias: {
|
||||||
|
async: path.join(__dirname, 'config/async-component-loader')
|
||||||
|
}
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.s?css$/,
|
test: /\.tsx?$/,
|
||||||
|
enforce: 'pre',
|
||||||
|
// loader: 'awesome-typescript-loader',
|
||||||
|
loader: 'ts-loader',
|
||||||
|
exclude: nodeModules
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(tsx?|jsx?)$/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: babelRc
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(scss|sass)$/,
|
||||||
|
loader: 'sass-loader',
|
||||||
|
enforce: 'pre',
|
||||||
|
options: {
|
||||||
|
sourceMap: true,
|
||||||
|
includePaths: [nodeModules]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(scss|sass|css)$/,
|
||||||
|
include: componentStyleDirs,
|
||||||
use: [
|
use: [
|
||||||
MiniCssExtractPlugin.loader,
|
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||||
{ loader: 'css-loader' },
|
|
||||||
// 'sass-loader?includePaths='+encodeURIComponent(path.join(__dirname, 'node_modules'))
|
|
||||||
{
|
{
|
||||||
loader: 'sass-loader',
|
// loader: 'typings-for-css-modules-loader?modules&localIdentName=[local]__[hash:base64:5]&importLoaders=1'+(isProd ? '&sourceMap' : '')
|
||||||
|
// loader: 'css-loader',
|
||||||
|
loader: 'typings-for-css-modules-loader',
|
||||||
options: {
|
options: {
|
||||||
includePaths: [path.join(__dirname, 'node_modules')]
|
modules: true,
|
||||||
|
localIdentName: '[local]__[hash:base64:5]',
|
||||||
|
namedExport: true,
|
||||||
|
camelCase: true,
|
||||||
|
importLoaders: 1,
|
||||||
|
sourceMap: isProd,
|
||||||
|
sass: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
// loader: ExtractTextPlugin.extract({
|
||||||
|
// fallback: 'style-loader',
|
||||||
|
// use: [{
|
||||||
|
// loader: 'css-loader',
|
||||||
|
// options: {
|
||||||
|
// modules: true,
|
||||||
|
// localIdentName: '[local]__[hash:base64:5]',
|
||||||
|
// importLoaders: 1,
|
||||||
|
// sourceMap: isProd
|
||||||
|
// }
|
||||||
|
// }]
|
||||||
|
// })
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.ts$/,
|
test: /\.(scss|sass|css)$/,
|
||||||
// loader: 'awesome-typescript-loader'
|
exclude: componentStyleDirs,
|
||||||
loader: 'typescript-loader'
|
use: [
|
||||||
},
|
isProd ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
loader: 'css-loader',
|
||||||
loader: 'babel-loader',
|
options: {
|
||||||
options: {
|
importLoaders: 1,
|
||||||
presets: [
|
sourceMap: isProd
|
||||||
['env', {
|
}
|
||||||
loose: true,
|
}
|
||||||
uglify: true,
|
]
|
||||||
modules: false,
|
// loader: ExtractTextPlugin.extract({
|
||||||
targets: {
|
// fallback: 'style-loader',
|
||||||
browsers: 'last 2 versions'
|
// use: [{
|
||||||
},
|
// loader: 'css-loader',
|
||||||
exclude: [
|
// options: {
|
||||||
'transform-regenerator',
|
// importLoaders: 1,
|
||||||
'transform-es2015-typeof-symbol'
|
// sourceMap: isProd
|
||||||
]
|
// }
|
||||||
}]
|
// }]
|
||||||
],
|
// })
|
||||||
plugins: [
|
|
||||||
'syntax-dynamic-import',
|
|
||||||
'transform-decorators-legacy',
|
|
||||||
'transform-class-properties',
|
|
||||||
'transform-object-rest-spread',
|
|
||||||
'transform-react-constant-elements',
|
|
||||||
'transform-react-remove-prop-types',
|
|
||||||
['transform-react-jsx', {
|
|
||||||
pragma: 'h'
|
|
||||||
}],
|
|
||||||
['jsx-pragmatic', {
|
|
||||||
module: 'preact',
|
|
||||||
export: 'h',
|
|
||||||
import: 'h'
|
|
||||||
}]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.optimize.SplitChunksPlugin({})
|
isProd && new webpack.optimize.SplitChunksPlugin({}),
|
||||||
]
|
isProd && new MiniCssExtractPlugin({}),
|
||||||
|
// new ExtractTextPlugin({
|
||||||
|
// filename: isProd ? 'style.[contenthash:5].css' : 'style.css',
|
||||||
|
// disable: !isProd,
|
||||||
|
// allChunks: true
|
||||||
|
// }),
|
||||||
|
|
||||||
|
// fixes infinite loop in typings-for-css-modules-loader:
|
||||||
|
new webpack.WatchIgnorePlugin([
|
||||||
|
/(c|sc|sa)ss\.d\.ts$/
|
||||||
|
]),
|
||||||
|
new WatchTimestampsPlugin([
|
||||||
|
/(c|sc|sa)ss\.d\.ts$/
|
||||||
|
]),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
filename: path.join(__dirname, 'build/index.html'),
|
||||||
|
template: '!!ejs-loader!src/index.html',
|
||||||
|
minify: isProd && {
|
||||||
|
collapseWhitespace: true,
|
||||||
|
removeScriptTypeAttributes: true,
|
||||||
|
removeRedundantAttributes: true,
|
||||||
|
removeStyleLinkTypeAttributes: true,
|
||||||
|
removeComments: true
|
||||||
|
},
|
||||||
|
manifest: require('./src/manifest.json'),
|
||||||
|
|
||||||
|
/** @todo Finish implementing prerendering similar to that of Preact CLI. */
|
||||||
|
prerender() {
|
||||||
|
return '<div id="app_root"></div>';
|
||||||
|
// require('babel-register')({ ignore: false });
|
||||||
|
// return require('./config/prerender')();
|
||||||
|
},
|
||||||
|
inject: true,
|
||||||
|
compile: true
|
||||||
|
}),
|
||||||
|
isProd && new PreloadWebpackPlugin(),
|
||||||
|
isProd && new ReplacePlugin({
|
||||||
|
include: /babel-helper$/,
|
||||||
|
patterns: [{
|
||||||
|
regex: /throw\s+(new\s+)?(Type|Reference)?Error\s*\(/g,
|
||||||
|
value: s => `return;${Array(s.length - 7).join(' ')}(`
|
||||||
|
}]
|
||||||
|
}),
|
||||||
|
new CopyPlugin([
|
||||||
|
{ from: 'src/manifest.json', to: 'manifest.json' },
|
||||||
|
{ from: 'src/assets', to: 'assets' }
|
||||||
|
])
|
||||||
|
].filter(Boolean),
|
||||||
|
|
||||||
|
devServer: {
|
||||||
|
contentBase: path.join(__dirname, 'src'),
|
||||||
|
inline: true,
|
||||||
|
hot: true,
|
||||||
|
historyApiFallback: true,
|
||||||
|
noInfo: true,
|
||||||
|
progress: true,
|
||||||
|
// quiet: true,
|
||||||
|
clientLogLevel: 'none',
|
||||||
|
stats: 'minimal',
|
||||||
|
overlay: false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user