├── .gitignore
├── .babelrc
├── .editorconfig
├── src
├── index.js
└── components
│ ├── home.js
│ ├── app.js
│ ├── profile.js
│ └── header.js
├── README.md
├── webpack.config.babel.js
├── package.json
└── .eslintrc
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /npm-debug.log
3 | /build
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "sourceMaps": true,
3 | "presets": [
4 | ["es2015", { "loose":true }],
5 | "stage-0"
6 | ],
7 | "plugins": [
8 | "styled-jsx/babel",
9 | ["transform-react-jsx", { "pragma": "h" }]
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | end_of_line = lf
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [{package.json,.*rc,*.yml}]
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { h, render } from 'preact';
2 |
3 | Object.defineProperty(h().constructor.prototype, 'props', { enumerable:true, get(){ return this.attributes; } });
4 |
5 | let root;
6 | function init() {
7 | let App = require('./components/app').default;
8 | root = render(, document.body, root);
9 | }
10 | init();
11 |
12 | // HMR:
13 | if (module.hot) module.hot.accept('./components/app', init);
14 |
--------------------------------------------------------------------------------
/src/components/home.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 |
3 | export default class Home extends Component {
4 | render() {
5 | return (
6 |
7 |
14 |
15 |
Home
16 |
17 |
This is the Home component.
18 |
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Preact] + [styled-jsx] Demo
2 |
3 | Just a simple demo showing [preact-boilerplate] converted over to [styled-jsx], running without [preact-compat].
4 |
5 | **Demo:** https://preact-styled-jsx-demo.now.sh
6 |
7 | ---
8 |
9 |
10 | ## License
11 |
12 | MIT
13 |
14 |
15 | [Preact]: https://github.com/developit/preact
16 | [preact-compat]: https://github.com/developit/preact-compat
17 | [styled-jsx]: https://github.com/zeit/styled-jsx
18 |
--------------------------------------------------------------------------------
/webpack.config.babel.js:
--------------------------------------------------------------------------------
1 | import HtmlWebpackPlugin from 'html-webpack-plugin';
2 | import path from 'path';
3 |
4 | const file = name => path.resolve(__dirname, name);
5 |
6 | module.exports = {
7 | context: file('src'),
8 | entry: './index.js',
9 |
10 | output: {
11 | path: file('build'),
12 | publicPath: '/',
13 | filename: 'bundle.js'
14 | },
15 |
16 | resolve: {
17 | alias: {
18 | // all that's needed to make styled-jsx work:
19 | 'react': 'preact'
20 | }
21 | },
22 |
23 | module: {
24 | loaders: [
25 | {
26 | test: /\.jsx?$/,
27 | exclude: /node_modules/,
28 | loader: 'babel'
29 | }
30 | ]
31 | },
32 |
33 | plugins: [
34 | new HtmlWebpackPlugin({
35 | minify: { collapseWhitespace: true }
36 | })
37 | ],
38 |
39 | node: false,
40 |
41 | devtool: 'source-map',
42 |
43 | devServer: {
44 | port: process.env.PORT || 8080,
45 | publicPath: '/',
46 | contentBase: './src',
47 | historyApiFallback: true
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/src/components/app.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 | import { Router } from 'preact-router';
3 |
4 | import Header from './header';
5 | import Home from './home';
6 | import Profile from './profile';
7 |
8 | export default class App extends Component {
9 | render() {
10 | return (
11 |
12 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "preact-styled-jsx-demo",
3 | "version": "1.0.0",
4 | "description": "Example of using preact + styled-jsx",
5 | "scripts": {
6 | "dev": "webpack-dev-server --inline --hot --progress",
7 | "start": "serve build -s -c 1",
8 | "prestart": "npm run build",
9 | "build": "webpack -p --progress",
10 | "test": "eslint {src,test}"
11 | },
12 | "keywords": [
13 | "preact",
14 | "boilerplate",
15 | "webpack"
16 | ],
17 | "license": "MIT",
18 | "author": "Jason Miller ",
19 | "devDependencies": {
20 | "babel": "^6.5.2",
21 | "babel-core": "^6.14.0",
22 | "babel-eslint": "^7.0.0",
23 | "babel-loader": "^6.2.5",
24 | "babel-plugin-transform-react-jsx": "^6.8.0",
25 | "babel-preset-es2015": "^6.14.0",
26 | "babel-preset-stage-0": "^6.5.0",
27 | "eslint": "^3.0.1",
28 | "html-webpack-plugin": "^2.22.0",
29 | "webpack": "^1.13.2",
30 | "webpack-dev-server": "^1.15.0"
31 | },
32 | "dependencies": {
33 | "preact": "^6.0.0",
34 | "preact-router": "^2.0.0",
35 | "serve": "^2.0.0",
36 | "styled-jsx": "^0.1.0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/profile.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 |
3 | export default class Profile extends Component {
4 | state = {
5 | count: 0
6 | };
7 |
8 | // gets called when this route is navigated to
9 | componentDidMount() {
10 | // start a timer for the clock:
11 | this.timer = setInterval(::this.updateTime, 1000);
12 | this.updateTime();
13 |
14 | // every time we get remounted, increment a counter:
15 | this.setState({ count: this.state.count+1 });
16 | }
17 |
18 | // gets called just before navigating away from the route
19 | componentWillUnmount() {
20 | clearInterval(this.timer);
21 | }
22 |
23 | // update the current time
24 | updateTime() {
25 | let time = new Date().toLocaleString();
26 | this.setState({ time });
27 | }
28 |
29 | // Note: `user` comes from the URL, courtesy of our router
30 | render({ user }, { time, count }) {
31 | return (
32 |
33 |
41 |
42 |
Profile: { user }
43 |
44 |
This is the user profile for a user named { user }.
45 |
46 |
Current time: { time }
47 |
48 |
Profile route mounted { count } times.
49 |
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/components/header.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 | import { Link } from 'preact-router';
3 |
4 | export default class Header extends Component {
5 | render() {
6 | return (
7 |
62 | );
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "eslint:recommended",
4 | "env": {
5 | "browser": true,
6 | "node": true,
7 | "mocha": true,
8 | "es6": true
9 | },
10 | "parserOptions": {
11 | "ecmaFeatures": {
12 | "modules": true,
13 | "jsx": true
14 | }
15 | },
16 | "globals": {},
17 | "rules": {
18 | "no-empty": 0,
19 | "no-console": 0,
20 | "no-empty-pattern": 0,
21 | "no-unused-vars": [0, { "varsIgnorePattern": "^h$" }],
22 | "no-cond-assign": 1,
23 | "semi": 2,
24 | "camelcase": 0,
25 | "comma-style": 2,
26 | "comma-dangle": [2, "never"],
27 | "indent": [2, "tab", {"SwitchCase": 1}],
28 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"],
29 | "no-trailing-spaces": [2, { "skipBlankLines": true }],
30 | "max-nested-callbacks": [2, 3],
31 | "no-eval": 2,
32 | "no-implied-eval": 2,
33 | "no-new-func": 2,
34 | "guard-for-in": 2,
35 | "eqeqeq": 1,
36 | "no-else-return": 2,
37 | "no-redeclare": 2,
38 | "no-dupe-keys": 2,
39 | "radix": 2,
40 | "strict": [2, "never"],
41 | "no-shadow": 0,
42 | "no-delete-var": 2,
43 | "no-undef-init": 2,
44 | "no-shadow-restricted-names": 2,
45 | "handle-callback-err": 0,
46 | "no-lonely-if": 2,
47 | "keyword-spacing": 2,
48 | "constructor-super": 2,
49 | "no-this-before-super": 2,
50 | "no-dupe-class-members": 2,
51 | "no-const-assign": 2,
52 | "prefer-spread": 2,
53 | "no-useless-concat": 2,
54 | "no-var": 2,
55 | "object-shorthand": 2,
56 | "prefer-arrow-callback": 2
57 | }
58 | }
59 |
--------------------------------------------------------------------------------