├── .editorconfig ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.txt ├── README.md ├── config └── CSSStub.js ├── docs ├── README.md ├── data-fetching.md ├── getting-started.md ├── how-to-configure-text-editors.md ├── react-style-guide.md ├── recipes │ ├── how-to-implement-routing.md │ ├── how-to-integrate-disqus.md │ ├── how-to-integrate-react-intl.md │ ├── how-to-integrate-redux.md │ ├── how-to-use-sass.md │ └── using-npm-and-webpack-as-a-build-tool.md └── testing-your-application.md ├── package.json ├── public ├── apple-touch-icon.png ├── browserconfig.xml ├── crossdomain.xml ├── favicon.ico ├── humans.txt ├── robots.txt ├── screenshot.png ├── tile-round.png ├── tile-wide.png └── tile.png ├── src ├── client.js ├── components │ ├── App.js │ ├── CrossFader │ │ ├── CrossFader.css │ │ ├── CrossFader.js │ │ └── package.json │ ├── Deck │ │ ├── Deck.css │ │ ├── Deck.js │ │ └── package.json │ ├── Feedback │ │ ├── Feedback.css │ │ ├── Feedback.js │ │ └── package.json │ ├── Footer │ │ ├── Footer.css │ │ ├── Footer.js │ │ └── package.json │ ├── FxUnit │ │ ├── FxUnit.css │ │ ├── FxUnit.js │ │ └── package.json │ ├── Header │ │ ├── Header.css │ │ ├── Header.js │ │ ├── logo-small.png │ │ ├── logo-small@2x.png │ │ └── package.json │ ├── Html.js │ ├── Layout │ │ ├── Layout.css │ │ ├── Layout.js │ │ ├── Layout.test.js │ │ └── package.json │ ├── Link │ │ ├── Link.js │ │ └── package.json │ ├── Mixer │ │ ├── Mixer.css │ │ ├── Mixer.js │ │ └── package.json │ ├── Navigation │ │ ├── Navigation.css │ │ ├── Navigation.js │ │ └── package.json │ ├── Page │ │ ├── Page.css │ │ ├── Page.js │ │ └── package.json │ ├── Player │ │ ├── Player.css │ │ ├── Player.js │ │ └── package.json │ ├── SoundcloudPlayer │ │ ├── SoundcloudPlayer.css │ │ ├── SoundcloudPlayer.js │ │ └── package.json │ ├── YoutubeDeck │ │ ├── YoutubeDeck.css │ │ ├── YoutubeDeck.js │ │ └── package.json │ ├── YoutubeMedia │ │ ├── YoutubeMedia.css │ │ ├── YoutubeMedia.js │ │ └── package.json │ └── variables.css ├── config.js ├── core │ ├── DOMUtils.js │ ├── devUtils.js │ ├── fetch │ │ ├── fetch.client.js │ │ ├── fetch.server.js │ │ └── package.json │ ├── history.js │ ├── passport.js │ └── router.js ├── data │ ├── models │ │ ├── .eslintrc │ │ ├── User.js │ │ ├── UserClaim.js │ │ ├── UserLogin.js │ │ ├── UserProfile.js │ │ └── index.js │ ├── queries │ │ ├── me.js │ │ └── news.js │ ├── schema.js │ ├── sequelize.js │ └── types │ │ ├── NewsItemType.js │ │ └── UserType.js ├── routes │ ├── about │ │ ├── about.md │ │ └── index.js │ ├── admin │ │ ├── Admin.css │ │ ├── Admin.js │ │ └── index.js │ ├── contact │ │ ├── Contact.css │ │ ├── Contact.js │ │ └── index.js │ ├── error │ │ ├── ErrorPage.css │ │ ├── ErrorPage.js │ │ └── index.js │ ├── home │ │ ├── Home.css │ │ ├── Home.js │ │ ├── index.js │ │ └── slider.css │ ├── index.js │ ├── login │ │ ├── Login.css │ │ ├── Login.js │ │ └── index.js │ ├── notFound │ │ ├── NotFound.css │ │ ├── NotFound.js │ │ └── index.js │ ├── privacy │ │ ├── index.js │ │ └── privacy.md │ └── register │ │ ├── Register.css │ │ ├── Register.js │ │ └── index.js └── server.js ├── test ├── .eslintrc └── setup.js ├── tools ├── .eslintrc ├── README.md ├── build.js ├── bundle.js ├── clean.js ├── copy.js ├── deploy.js ├── deployDev.js ├── lib │ ├── cp.js │ ├── fs.js │ └── markdown-loader.js ├── postcss.config.js ├── render.js ├── run.js ├── runServer.js ├── start.js └── webpack.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | # editorconfig-tools is unable to ignore longs strings or urls 20 | max_line_length = null 21 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/build 3 | .*/config 4 | .*/node_modules 5 | .*/gulpfile.js 6 | 7 | [include] 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Automatically normalize line endings for all text-based files 2 | # http://git-scm.com/docs/gitattributes#_end_of_line_conversion 3 | * text=auto 4 | 5 | # For the following file types, normalize line endings to LF on 6 | # checkin and prevent conversion to CRLF when they are checked out 7 | # (this is required in order to prevent newline related issues like, 8 | # for example, after the build script is run) 9 | .* text eol=lf 10 | *.html text eol=lf 11 | *.css text eol=lf 12 | *.less text eol=lf 13 | *.scss text eol=lf 14 | *.sss text eol=lf 15 | *.js text eol=lf 16 | *.json text eol=lf 17 | *.md text eol=lf 18 | *.sh text eol=lf 19 | *.txt text eol=lf 20 | *.xml text eol=lf 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Include your project-specific ignores in this file 2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files 3 | 4 | build 5 | database.sqlite 6 | node_modules 7 | ncp-debug.log 8 | npm-debug.log 9 | stats.json 10 | report.html 11 | .env 12 | .idea 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '7' 4 | - '6' 5 | env: 6 | - CXX=g++-4.8 7 | addons: 8 | apt: 9 | sources: 10 | - ubuntu-toolchain-r-test 11 | packages: 12 | - g++-4.8 13 | script: 14 | - yarn lint 15 | - yarn test 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## React Starter Kit Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ### [Unreleased][unreleased] 6 | 7 | - Split the `App` component into `App` setting context variables and `Layout` setting general look and feel of the app (BREAKING CHANGE) 8 | - Upgrade `history` npm module to v4.x, update `Link` component (BREAKING CHANGE) 9 | - Remove `core/createHistory.js` in favor of initializing a new history instance inside `server.js` and `client.js` (BREAKING CHANGE) 10 | - Remove Jade dependency in favor of React-based templates: `src/views/index.jade => src/components/Html` 11 | (BREAKING CHANGE) [#711](https://github.com/kriasoft/react-starter-kit/pull/711) 12 | - Update `isomorphic-style-loader` to `v1.0.0`, it adds comparability with ES2015+ decorators. 13 | Code such as `export default withStyles(MyComponent, style1, style2)` must be replaced with 14 | `export default withStyles(style1, style2)(MyComponent)` (BREAKING CHANGE). 15 | - Replace Jest with Mocha, Chai, Sinon. Unit test files must be renamed from 16 | `MyComponent/__test__/MyComponent-test.js` to `MyComponent/MyComponent.test.js` (BREAKING CHANGE). 17 | - Remove `actions`, `stores` folders since there is no Flux library included into the kit 18 | - Rename `server` variable in `server.js` to `app` 19 | - Integrate [Sequelize](http://docs.sequelizejs.com/) to make the project compatible with different types of databases 20 | - Rename `onSetTitle`, `onSetMeta` context variables to `setTitle`, `setMeta` 21 | - Move `Content` component to `src/routes/content` 22 | - Move `ErrorPage` component to `src/routes/error` 23 | - Move the list of top-level routes to `src/routes/index` 24 | - Update routing to use `universal-router` library 25 | - Move Babel, ESLint and JSCS configurations to `package.json` [#497](https://github.com/kriasoft/react-starter-kit/pull/497) 26 | - Convert `Feedback`, `Footer`, `Header`, and `Navigation` to functional stateless components 27 | - Move page / screen components into the `src/routes` folder along with the routing information for them (BREAKING CHANGE). [6553936](https://github.com/kriasoft/react-starter-kit/commit/6553936e693e24a8ac6178f4962af15e0ea87dfd) 28 | 29 | ### [v0.5.1] 30 | > 2016-03-02 31 | 32 | - Remove `Html` React component in favor of compiled Jade templates (`src/views`) (BREAKING CHANGE). [e188388](https://github.com/kriasoft/react-starter-kit/commit/e188388f87069cdc7d501b385d6b0e46c98fed60) 33 | - Add global error handling in Node.js/Express app. [e188388](https://github.com/kriasoft/react-starter-kit/commit/e188388f87069cdc7d501b385d6b0e46c98fed60) 34 | - Add support for Markdown and HTML for static pages. [#469](https://github.com/kriasoft/react-starter-kit/pull/469), [#477](https://github.com/kriasoft/react-starter-kit/pull/477) 35 | 36 | ### [v0.5.0] 37 | > 2016-02-27 38 | 39 | - Replace RESTful API endpoint (`src/api`) with GraphQL (`src/data`) 40 | - Add a sample GraphQL endpoint [localhost:3000/graphql](https://localhost:3000/graphql) 41 | - Change the default Node.js server port from `5000` to `3000` 42 | - Add a JWT-based authentication cookies (see `src/server.js`) 43 | - Add a reference implementation of Facebook authentication strategy (`src/core/passport.js`) 44 | - Add a sample database client utility for PostgreSQL (`src/core/db.js`) 45 | - Optimize the `tools/start.js` script that launches dev server with Browsersync and HMR 46 | - Replace Superagent with WHATWG Fetch library 47 | - Rename `app.js` to `client.js` (aka client-side code) 48 | - Integrate [CSS Modules](https://github.com/css-modules/css-modules) and 49 | [isomorphic-style-loader](https://github.com/kriasoft/isomorphic-style-loader) 50 | - Move `DOMUtils.js` to `src/core` folder; remove `src/utils` folder 51 | - Replace [cssnext](http://cssnext.io/) with [precss](https://github.com/jonathantneal/precss) 52 | - Update build automation scripts to use plain functions 53 | - Add support of `--release` and `--verbose` flags to build scripts 54 | - Add `CHANGELOG.md` file with a list of notable changes to this project 55 | 56 | ### [v0.4.1] 57 | > 2015-10-04 58 | 59 | - Replace React Hot Loader (deprecated) with React Transform 60 | - Replace `index.html` template with `Html` (shell) React component 61 | - Update the deployment script (`tools/deploy.js`), add Git-based deployment example 62 | - Update ESLint and JSCS settings to use AirBnb JavaScript style guide 63 | - Update `docs/how-to-configure-text-editors.md` to cover Atom editor 64 | - Update NPM production and dev dependencies to use the latest versions 65 | 66 | [unreleased]: https://github.com/kriasoft/react-starter-kit/compare/v0.5.1...HEAD 67 | [v0.5.1]: https://github.com/kriasoft/react-starter-kit/compare/v0.5.0...v0.5.1 68 | [v0.5.0]: https://github.com/kriasoft/react-starter-kit/compare/v0.4.1...v0.5.0 69 | [v0.4.1]: https://github.com/kriasoft/react-starter-kit/compare/v0.4.0...v0.4.1 70 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to React Starter Kit 2 | 3 | React Starter Kit is currently the most widely adopted Node.js/React boilerplate used by many 4 | tech startups around the globe. We're working hard to keep it up to date, making sure that it 5 | follows best practices and high coding standards, paying extremely close attention to details. 6 | 7 | Your contributions are welcome and are greatly appreciated! Every little bit helps, and credit 8 | will always be given. 9 | 10 | Please take a moment to review this document in order to make the contribution process easy and 11 | effective for everyone involved. 12 | 13 | ### Conduct 14 | 15 | Please, follow the [golden rule](https://en.wikipedia.org/wiki/Golden_Rule). Be respectful, even to 16 | those that are disrespectful. 17 | 18 | ### Feedback 19 | 20 | Feedback is the breakfast for champions! We'd love to hear your opinions, discuss potential 21 | improvements, architecture, theory, internal implementation, etc. Please, join or start a new 22 | conversation in our [issue tracker](https://github.com/kriasoft/react-starter-kit/issues), 23 | [Gitter](https://gitter.im/kriasoft/react-starter-kit) chat room, or let's talk face-to-face on 24 | [Appear.in](https://appear.in/react) or [Skype](http://hatscripts.com/addskype?koistya). 25 | 26 | ### Documentation 27 | 28 | We need your help with improving documentation to the project. This might be the easiest way for 29 | you to contribute, because you don't even need to clone the repo but can edit or create new `.md` 30 | files right from GitHub website as described [here](https://help.github.com/articles/editing-files-in-your-repository/). 31 | 32 | ### Bugs & Feature Requests 33 | 34 | Before opening an issue, please: 35 | 36 | * Check the [Getting Started](https://github.com/kriasoft/react-starter-kit/blob/master/docs/getting-started.md) guide. 37 | * Search the [issue tracker](https://github.com/kriasoft/react-starter-kit/issues) to make sure 38 | your issue hasn’t already been reported. 39 | * If your issue sounds more like a question, please post it on StackOverflow.com instead with the 40 | tag [react-starter-kit](http://stackoverflow.com/questions/tagged/react-starter-kit). 41 | 42 | ### Pull Requests 43 | 44 | Before you submit a [pull request](https://help.github.com/articles/using-pull-requests/) from your 45 | forked repo, check that it meets these guidelines: 46 | 47 | * If the pull request adds functionality, the docs should be updated as part of the same PR. 48 | * Create a separate PR for each small feature or bug fix. 49 | * [Squash](http://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git) 50 | your commits into one for each PR. 51 | * Run `yarn test` to make sure that your code style is OK and there are no any regression bugs. 52 | * When contributing to an opt-in feature, apply the `[feature/...]` tag as a prefix to your PR title 53 | 54 | #### Style Guide 55 | 56 | Our linter will catch most styling issues that may exist in your code. You can check the status 57 | of your code styling by simply running: `yarn lint` 58 | 59 | However, there are still some styles that the linter cannot pick up. If you are unsure about 60 | something, looking at [Airbnb's Style Guide](https://github.com/airbnb/javascript) will guide you 61 | in the right direction. 62 | 63 | ### License 64 | 65 | By contributing to React Starter Kit, you agree that your contributions will be licensed under its 66 | [MIT license](https://github.com/kriasoft/react-starter-kit/blob/master/LICENSE.txt). 67 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.9.5-alpine 2 | 3 | # Copy application files 4 | COPY ./build /usr/src/app 5 | WORKDIR /usr/src/app 6 | 7 | # Install Yarn and Node.js dependencies 8 | RUN npm install yarn --global --no-progress --silent --depth 0 && \ 9 | yarn install --production --no-progress 10 | 11 | CMD [ "node", "server.js" ] 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2017 Kevin Chau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TReactr 2 | A Traktor clone in React 3 | 4 | 5 | 6 | TReactr is a javascript digital DJ mixing application built for the modern web, based on the legendary UI from Native Instruments' Traktor. 7 | 8 | ## Features: 9 | - Stream music from Youtube or Soundcloud 10 | - Apply EQ's and filter to html5 audio sources 11 | 12 | ## TReactr is brought to you by: 13 | Node.js, Express, GraphQL, React, Babel, ESLint, PostCSS, Webpack, and Browsersync. 14 | 15 | ## Install: 16 | This project uses `yarn` for managing packages, running build scripts, and starting the development server. 17 | If you don't already have `yarn` you can install it with: 18 | 19 | npm install -g yarn 20 | 21 | To install TReactr, use: 22 | 23 | yarn 24 | 25 | This is equivalent to `yarn install` or `npm install`. 26 | 27 | ## Run: 28 | To start a dev server and launch TReactr in your browser, use: 29 | 30 | yarn start 31 | 32 | This is equivalent to `npm start`. 33 | 34 | For a full list of scripts that can be ran with `yarn` or `npm`, see `package.json`. 35 | 36 | ## Contributing: 37 | The easiest way to start contributing is to check out the deployment on Heroku and open up an issue if you have problems with it. 38 | 39 | If you want to help with development, there's a to-do list of small features that need to be implemented in the Wiki. 40 | 41 | If you like thinking about the bigger picture, we have a build/release plan on the Wiki as well. TReactr will be officially released sometime in late 2017. 42 | -------------------------------------------------------------------------------- /config/CSSStub.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | ### General 4 | 5 | * [Getting Started](./getting-started.md) 6 | * [React Style Guide](./react-style-guide.md) 7 | * [How to configure text editors and IDEs](./how-to-configure-text-editors.md) 8 | * [Data fetching with WHATWG Fetch](./data-fetching.md) 9 | * [Testing your application](./testing-your-application.md) 10 | 11 | ### Questions 12 | 13 | * [Which module bundler should I use?](https://github.com/kriasoft/react-starter-kit/issues/3) 14 | * [Which Flux implementation should I use?](https://github.com/kriasoft/react-starter-kit/issues/22) 15 | 16 | ### Recipes 17 | 18 | * [How to Implement Routing and Navigation](./recipes/how-to-implement-routing.md) 19 | * [How to Integrate Redux](./recipes/how-to-integrate-redux.md) 20 | * [How to Integrate React Intl](./recipes/how-to-integrate-react-intl.md) 21 | * [How to Integrate Disqus](./recipes/how-to-integrate-disqus.md) 22 | * [How to Use Sass/SCSS](./recipes/how-to-use-sass.md) 23 | -------------------------------------------------------------------------------- /docs/data-fetching.md: -------------------------------------------------------------------------------- 1 | ## Data Fetching with WHATWG Fetch 2 | 3 | There is isomorphic `core/fetch` module that can be used the same way in both 4 | client-side and server-side code as follows: 5 | 6 | ```jsx 7 | import fetch from '../core/fetch'; 8 | 9 | export const path = '/products'; 10 | export const action = async () => { 11 | const response = await fetch('/graphql?query={products{id,name}}'); 12 | const data = await response.json(); 13 | return ; 14 | }; 15 | ``` 16 | 17 | When this code executes on the client, the Ajax request will be sent via 18 | GitHub's [fetch](https://github.com/github/fetch) library (`whatwg-fetch`), 19 | that itself uses XHMLHttpRequest behind the scene unless `fetch` is supported 20 | natively by the user's browser. 21 | 22 | Whenever the same code executes on the server, it uses 23 | [node-fetch](https://github.com/bitinn/node-fetch) module behind the scene that 24 | itself sends an HTTP request via Node.js `http` module. It also converts 25 | relative URLs to absolute (see `./core/fetch/fetch.server.js`). 26 | 27 | Both `whatwg-fetch` and `node-fetch` modules have almost identical API. If 28 | you're new to this API, the following article may give you a good introduction: 29 | 30 | https://jakearchibald.com/2015/thats-so-fetch/ 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | ## Getting Started 2 | 3 | ### Requirements 4 | 5 | * Mac OS X, Windows, or Linux 6 | * [Yarn](https://yarnpkg.com/) package + [Node.js](https://nodejs.org/) v6.5 or newer 7 | * Text editor or IDE pre-configured with React/JSX/Flow/ESlint ([learn more](./how-to-configure-text-editors.md)) 8 | 9 | ### Directory Layout 10 | 11 | Before you start, take a moment to see how the project structure looks like: 12 | 13 | ``` 14 | . 15 | ├── /build/ # The folder for compiled output 16 | ├── /docs/ # Documentation files for the project 17 | ├── /node_modules/ # 3rd-party libraries and utilities 18 | ├── /public/ # Static files which are copied into the /build/public folder 19 | ├── /src/ # The source code of the application 20 | │ ├── /components/ # React components 21 | │ ├── /core/ # Core framework and utility functions 22 | │ ├── /data/ # GraphQL server schema and data models 23 | │ ├── /routes/ # Page/screen components along with the routing information 24 | │ ├── /client.js # Client-side startup script 25 | │ ├── /config.js # Global application settings 26 | │ └── /server.js # Server-side startup script 27 | ├── /test/ # Unit and end-to-end tests 28 | ├── /tools/ # Build automation scripts and utilities 29 | │ ├── /lib/ # Library for utility snippets 30 | │ ├── /build.js # Builds the project from source to output (build) folder 31 | │ ├── /bundle.js # Bundles the web resources into package(s) through Webpack 32 | │ ├── /clean.js # Cleans up the output (build) folder 33 | │ ├── /copy.js # Copies static files to output (build) folder 34 | │ ├── /deploy.js # Deploys your web application 35 | │ ├── /postcss.config.js # Configuration for transforming styles with PostCSS plugins 36 | │ ├── /run.js # Helper function for running build automation tasks 37 | │ ├── /runServer.js # Launches (or restarts) Node.js server 38 | │ ├── /start.js # Launches the development web server with "live reload" 39 | │ └── /webpack.config.js # Configurations for client-side and server-side bundles 40 | ├── Dockerfile # Commands for building a Docker image for production 41 | ├── package.json # The list of 3rd party libraries and utilities 42 | └── yarn.lock # Fixed versions of all the dependencies 43 | ``` 44 | 45 | **Note**: The current version of RSK does not contain a Flux implementation. 46 | It can be easily integrated with any Flux library of your choice. The most 47 | commonly used Flux libraries are [Flux](http://facebook.github.io/flux/), 48 | [Redux](http://redux.js.org/) and [Relay](http://facebook.github.io/relay/). 49 | 50 | ### Quick Start 51 | 52 | #### 1. Get the latest version 53 | 54 | You can start by cloning the latest version of React Starter Kit (RSK) on your 55 | local machine by running: 56 | 57 | ```shell 58 | $ git clone -o react-starter-kit -b master --single-branch \ 59 | https://github.com/kriasoft/react-starter-kit.git MyApp 60 | $ cd MyApp 61 | ``` 62 | 63 | Alternatively, you can start a new project based on RSK right from 64 | [WebStorm IDE](https://www.jetbrains.com/webstorm/help/create-new-project-react-starter-kit.html), 65 | or by using [Yeoman generator](https://www.npmjs.com/package/generator-react-fullstack). 66 | 67 | #### 2. Run `yarn install` 68 | 69 | This will install both run-time project dependencies and developer tools listed 70 | in [package.json](../package.json) file. 71 | 72 | #### 3. Run `yarn start` 73 | 74 | This command will build the app from the source files (`/src`) into the output 75 | `/build` folder. As soon as the initial build completes, it will start the 76 | Node.js server (`node build/server.js`) and [Browsersync](https://browsersync.io/) 77 | with [HMR](https://webpack.github.io/docs/hot-module-replacement) on top of it. 78 | 79 | > [http://localhost:3000/](http://localhost:3000/) — Node.js server (`build/server.js`)
80 | > [http://localhost:3000/graphql](http://localhost:3000/graphql) — GraphQL server and IDE
81 | > [http://localhost:3001/](http://localhost:3001/) — BrowserSync proxy with HMR, React Hot Transform
82 | > [http://localhost:3002/](http://localhost:3002/) — BrowserSync control panel (UI) 83 | 84 | Now you can open your web app in a browser, on mobile devices and start 85 | hacking. Whenever you modify any of the source files inside the `/src` folder, 86 | the module bundler ([Webpack](http://webpack.github.io/)) will recompile the 87 | app on the fly and refresh all the connected browsers. 88 | 89 | ![browsersync](https://dl.dropboxusercontent.com/u/16006521/react-starter-kit/brwosersync.jpg) 90 | 91 | Note that the `yarn start` command launches the app in `development` mode, 92 | the compiled output files are not optimized and minimized in this case. 93 | You can use `--release` command line argument to check how your app works 94 | in release (production) mode: 95 | 96 | ```shell 97 | $ yarn start -- --release 98 | ``` 99 | *NOTE: double dashes are required* 100 | 101 | 102 | ### How to Build, Test, Deploy 103 | 104 | If you need just to build the app (without running a dev server), simply run: 105 | 106 | ```shell 107 | $ yarn run build 108 | ``` 109 | 110 | or, for a production build: 111 | 112 | ```shell 113 | $ yarn run build -- --release 114 | ``` 115 | 116 | or, for a production docker build: 117 | 118 | ```shell 119 | $ yarn run build -- --release --docker 120 | ``` 121 | 122 | *NOTE: double dashes are required* 123 | 124 | After running this command, the `/build` folder will contain the compiled 125 | version of the app. For example, you can launch Node.js server normally by 126 | running `node build/server.js`. 127 | 128 | To check the source code for syntax errors and potential issues run: 129 | 130 | ```shell 131 | $ yarn run lint 132 | ``` 133 | 134 | To launch unit tests: 135 | 136 | ```shell 137 | $ yarn run test # Run unit tests with Mocha 138 | $ yarn run test:watch # Launch unit test runner and start watching for changes 139 | ``` 140 | 141 | By default, [Mocha](https://mochajs.org/) test runner is looking for test files 142 | matching the `src/**/*.test.js` pattern. Take a look at `src/components/Layout/Layout.test.js` 143 | as an example. 144 | 145 | To deploy the app, run: 146 | 147 | ```shell 148 | $ yarn run deploy 149 | ``` 150 | 151 | The deployment script `tools/deploy.js` is configured to push the contents of 152 | the `/build` folder to a remote server via Git. You can easily deploy your app 153 | to [Azure Web Apps](https://azure.microsoft.com/en-us/services/app-service/web/), 154 | or [Heroku](https://www.heroku.com/) this way. Both will execute `yarn install --production` 155 | upon receiving new files from you. Note, you should only deploy the contents 156 | of the `/build` folder to a remote server. 157 | 158 | ### How to Update 159 | 160 | If you need to keep your project up to date with the recent changes made to RSK, 161 | you can always fetch and merge them from [this repo](https://github.com/kriasoft/react-starter-kit) 162 | back into your own project by running: 163 | 164 | ```shell 165 | $ git checkout master 166 | $ git fetch react-starter-kit 167 | $ git merge react-starter-kit/master 168 | $ yarn install 169 | ``` 170 | -------------------------------------------------------------------------------- /docs/how-to-configure-text-editors.md: -------------------------------------------------------------------------------- 1 | ## How to Configure Text Editors and IDEs for React.js [![img](https://img.shields.io/badge/discussion-join-green.svg?style=flat-square)](https://github.com/kriasoft/react-starter-kit/issues/117) 2 | 3 | > Tips and tricks on how to configure your favorite text editor or IDE to work 4 | > with React.js/ES6+/JSX. 5 | 6 | ### WebStorm 7 | 8 | Create a new project based on **React Starter Kit template** 9 | 10 | ![react-project-template-in-webstorm](https://dl.dropboxusercontent.com/u/16006521/react-starter-kit/webstorm-new-project.png) 11 | 12 | Make sure that **JSX** support is enabled in your project. This is set by default, if you create a new project based on React.js template. 13 | 14 | ![jsx-support-in-webstorm](https://dl.dropboxusercontent.com/u/16006521/react-starter-kit/webstorm-jsx.png) 15 | 16 | Configure JavaScript libraries for **auto-complete** 17 | 18 | ![javascript-libraries-in-webstorm](https://dl.dropboxusercontent.com/u/16006521/react-starter-kit/webstorm-libraries.png) 19 | 20 | Enable **ESLint** support 21 | 22 | ![eslint-support-in-webstorm](https://dl.dropboxusercontent.com/u/16006521/react-starter-kit/webstorm-eslint.png) 23 | 24 | Enable **CSSComb** by following the instructions [here](https://github.com/csscomb/jetbrains-csscomb). 25 | 26 | **If you have trouble with autoreloading** try to disable "safe write" in `File > Settings > System Settings > Use "safe write" (save changes to a temporary file first)` 27 | 28 | ### Atom 29 | 30 | Install atom packages 31 | 32 | * [linter](https://atom.io/packages/linter) 33 | * [linter-eslint](https://atom.io/packages/linter-eslint) 34 | * [linter-stylelint](https://atom.io/packages/linter-stylelint) 35 | * [react](https://atom.io/packages/react) 36 | 37 | ```shell 38 | apm install linter linter-eslint react linter-stylelint 39 | ``` 40 | 41 | Install local npm packages 42 | 43 | * [eslint](https://www.npmjs.com/package/eslint) 44 | * [babel-eslint](https://www.npmjs.com/package/babel-eslint) 45 | * [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) 46 | * [stylelint](https://www.npmjs.com/package/stylelint) 47 | 48 | ```shell 49 | yarn add --dev eslint babel-eslint eslint-plugin-react stylelint 50 | ``` 51 | 52 | *You may need to restart atom for changes to take effect* 53 | 54 | ### SublimeText 55 | 56 | Install SublimeText packages 57 | Easiest with [Package Control](https://packagecontrol.io/) and then "Package Control: Install Package" (Ctrl+Shift+P) 58 | 59 | * [Babel](https://packagecontrol.io/packages/Babel) 60 | * [Sublime-linter](http://www.sublimelinter.com/en/latest/) 61 | * [SublimeLinter-contrib-eslint](https://packagecontrol.io/packages/SublimeLinter-contrib-eslint) 62 | * [SublimeLinter-contrib-stylelint](https://packagecontrol.io/packages/SublimeLinter-contrib-stylelint) 63 | 64 | You can also use [SublimeLinter-contrib-eslint_d](https://packagecontrol.io/packages/SublimeLinter-contrib-eslint_d) for faster linting. 65 | 66 | Set Babel as default syntax for a particular extension: 67 | 68 | * Open a file with that extension, 69 | * Select `View` from the menu, 70 | * Then `Syntax` `->` `Open all with current extension as...` `->` `Babel` `->` `JavaScript (Babel)`. 71 | * Repeat this for each extension (e.g.: .js and .jsx). 72 | 73 | Install local npm packages 74 | 75 | ``` 76 | yarn add --dev eslint@latest 77 | yarn add --dev babel-eslint@latest 78 | yarn add --dev eslint-plugin-react 79 | yarn add --dev stylelint 80 | ``` 81 | -------------------------------------------------------------------------------- /docs/react-style-guide.md: -------------------------------------------------------------------------------- 1 | ## React Style Guide 2 | 3 | > This style guide comes as an addition to [Airbnb React/JSX Guide](https://github.com/airbnb/javascript/tree/master/react). 4 | <<<<<<< HEAD 5 | > Feel free to modify it to suit your project's needs. 6 | ======= 7 | > Feel free to modify it to suit your project's needs. 8 | >>>>>>> c442026a6b8df5af1a0b74d002a2cc5a71c4b168 9 | 10 | ### Table of Contents 11 | 12 | * [Separate folder per UI component](#separate-folder-per-ui-component) 13 | * [Prefer using functional components](#prefer-using-functional-components) 14 | * [Use CSS Modules](#use-css-modules) 15 | * [Use higher-order components](#use-higher-order-components) 16 | 17 | ### Separate folder per UI component 18 | 19 | * Place each major UI component along with its resources in a separate folder
20 | This will make it easier to find related resources for any particular UI 21 | element (CSS, images, unit tests, localization files etc.). Removing such 22 | components during refactorings should also be easy. 23 | * Avoid having CSS, images and other resource files shared between multiple components.
24 | This will make your code more maintainable, easy to refactor. 25 | * Add `package.json` file into each component's folder.
26 | This will allow to easily reference such components from other places in 27 | your code.
28 | Use `import Nav from '../Navigation'` instead of `import Nav from '../Navigation/Navigation.js'` 29 | 30 | ``` 31 | /components/Navigation/icon.svg 32 | /components/Navigation/Navigation.css 33 | /components/Navigation/Navigation.js 34 | /components/Navigation/Navigation.test.js 35 | /components/Navigation/Navigation.ru-RU.css 36 | /components/Navigation/package.json 37 | ``` 38 | 39 | ``` 40 | <<<<<<< HEAD 41 | // components/Navigation/package.json 42 | ======= 43 | // components/Navigation/package.json 44 | >>>>>>> c442026a6b8df5af1a0b74d002a2cc5a71c4b168 45 | { 46 | "name:": "Navigation", 47 | "main": "./Navigation.js" 48 | } 49 | ``` 50 | 51 | For more information google for [component-based UI development](https://google.com/search?q=component-based+ui+development). 52 | 53 | ### Prefer using functional components 54 | 55 | * Prefer using stateless functional components whenever possible.
56 | Components that don't use state are better to be written as simple pure functions. 57 | 58 | ```jsx 59 | // Bad 60 | class Navigation extends Component { 61 | static propTypes = { items: PropTypes.array.isRequired }; 62 | render() { 63 | return ; 64 | } 65 | } 66 | 67 | // Better 68 | function Navigation({ items }) { 69 | return ( 70 | ; 71 | ); 72 | } 73 | Navigation.propTypes = { items: PropTypes.array.isRequired }; 74 | ``` 75 | 76 | ### Use CSS Modules 77 | 78 | * Use CSS Modules
79 | This will allow using short CSS class names and at the same time avoid conflicts. 80 | * Keep CSS simple and declarative. Avoid loops, mixins etc. 81 | * Feel free to use variables in CSS via [precss](https://github.com/jonathantneal/precss) plugin for [PostCSS](https://github.com/postcss/postcss) 82 | * Prefer CSS class selectors instead of element and `id` selectors (see [BEM](https://bem.info/)) 83 | * Avoid nested CSS selectors (see [BEM](https://bem.info/)) 84 | * When in doubt, use `.root { }` class name for the root elements of your components 85 | 86 | ```scss 87 | // Navigation.scss 88 | @import '../variables.scss'; 89 | 90 | .root { 91 | width: 300px; 92 | } 93 | 94 | .items { 95 | margin: 0; 96 | padding: 0; 97 | list-style-type: none; 98 | text-align: center; 99 | } 100 | 101 | .item { 102 | display: inline-block; 103 | vertical-align: top; 104 | } 105 | 106 | .link { 107 | display: block; 108 | padding: 0 25px; 109 | outline: 0; 110 | border: 0; 111 | color: $default-color; 112 | text-decoration: none; 113 | line-height: 25px; 114 | transition: background-color .3s ease; 115 | 116 | &, 117 | .items:hover & { 118 | background: $default-bg-color; 119 | } 120 | 121 | .selected, 122 | .items:hover &:hover { 123 | background: $active-bg-color; 124 | } 125 | } 126 | ``` 127 | 128 | ```jsx 129 | // Navigation.js 130 | <<<<<<< HEAD 131 | import React, { PropTypes } from 'react'; 132 | ======= 133 | import React from 'react'; 134 | import PropTypes from 'prop-types'; 135 | >>>>>>> c442026a6b8df5af1a0b74d002a2cc5a71c4b168 136 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 137 | import s from './Navigation.scss'; 138 | 139 | function Navigation() { 140 | return ( 141 | 151 | ); 152 | } 153 | 154 | Navigation.propTypes = { className: PropTypes.string }; 155 | 156 | export default withStyles(Navigation, s); 157 | ``` 158 | 159 | ### Use higher-order components 160 | 161 | * Use higher-order components (HOC) to extend existing React components.
162 | Here is an example: 163 | 164 | ```js 165 | // withViewport.js 166 | import React, { Component } from 'react'; 167 | import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment'; 168 | 169 | function withViewport(ComposedComponent) { 170 | return class WithViewport extends Component { 171 | 172 | state = { 173 | viewport: canUseDOM ? 174 | {width: window.innerWidth, height: window.innerHeight} : 175 | {width: 1366, height: 768} // Default size for server-side rendering 176 | }; 177 | 178 | componentDidMount() { 179 | window.addEventListener('resize', this.handleResize); 180 | window.addEventListener('orientationchange', this.handleResize); 181 | } 182 | 183 | componentWillUnmount() { 184 | window.removeEventListener('resize', this.handleResize); 185 | window.removeEventListener('orientationchange', this.handleResize); 186 | } 187 | 188 | handleResize = () => { 189 | let viewport = {width: window.innerWidth, height: window.innerHeight}; 190 | if (this.state.viewport.width !== viewport.width || 191 | this.state.viewport.height !== viewport.height) { 192 | this.setState({ viewport }); 193 | } 194 | }; 195 | 196 | render() { 197 | return ; 198 | } 199 | 200 | }; 201 | }; 202 | 203 | export default withViewport; 204 | ``` 205 | 206 | ```js 207 | // MyComponent.js 208 | import React from 'react'; 209 | import withViewport from './withViewport'; 210 | 211 | class MyComponent { 212 | render() { 213 | let { width, height } = this.props.viewport; 214 | return
{`Viewport: ${width}x${height}`}
; 215 | } 216 | } 217 | 218 | export default withViewport(MyComponent); 219 | ``` 220 | 221 | **[⬆ back to top](#table-of-contents)** 222 | -------------------------------------------------------------------------------- /docs/recipes/how-to-integrate-disqus.md: -------------------------------------------------------------------------------- 1 | ## How to Integrate [Disqus](https://disqus.com) 2 | 3 | https://disqus.com/admin/create/ 4 | 5 | #### `DisqusThread.js` 6 | 7 | ```js 8 | <<<<<<< HEAD 9 | import React, { PropTypes } from 'react'; 10 | ======= 11 | import React from 'react'; 12 | import PropTypes from 'prop-types'; 13 | >>>>>>> c442026a6b8df5af1a0b74d002a2cc5a71c4b168 14 | 15 | const SHORTNAME = 'example'; 16 | const WEBSITE_URL = 'http://www.example.com'; 17 | 18 | function renderDisqus() { 19 | if (window.DISQUS === undefined) { 20 | var script = document.createElement('script'); 21 | script.async = true; 22 | script.src = 'https://' + SHORTNAME + '.disqus.com/embed.js'; 23 | document.getElementsByTagName('head')[0].appendChild(script); 24 | } else { 25 | window.DISQUS.reset({reload: true}); 26 | } 27 | } 28 | 29 | class DisqusThread extends React.Component{ 30 | 31 | static propTypes = { 32 | id: PropTypes.string.isRequired, 33 | title: PropTypes.string.isRequired, 34 | path: PropTypes.string.isRequired 35 | }; 36 | 37 | shouldComponentUpdate(nextProps) { 38 | return this.props.id !== nextProps.id || 39 | this.props.title !== nextProps.title || 40 | this.props.path !== nextProps.path; 41 | } 42 | 43 | componentDidMount() { 44 | renderDisqus(); 45 | } 46 | 47 | componentDidUpdate() { 48 | renderDisqus(); 49 | } 50 | 51 | render() { 52 | let { id, title, path, ...other} = this.props; 53 | 54 | if (process.env.BROWSER) { 55 | window.disqus_shortname = SHORTNAME; 56 | window.disqus_identifier = id; 57 | window.disqus_title = title; 58 | window.disqus_url = WEBSITE_URL + path; 59 | } 60 | 61 | return
; 62 | } 63 | 64 | } 65 | 66 | export default DisqusThread; 67 | ``` 68 | 69 | #### `MyComponent.js` 70 | 71 | ```js 72 | import React from 'react'; 73 | import DisqusThread from './DisqusThread.js'; 74 | 75 | class MyComponent extends React.Component{ 76 | 77 | render() { 78 | return ( 79 |
80 | 83 |
84 | ); 85 | } 86 | 87 | } 88 | 89 | export default MyComponent; 90 | ``` 91 | -------------------------------------------------------------------------------- /docs/recipes/how-to-integrate-react-intl.md: -------------------------------------------------------------------------------- 1 | ## How to Integrate [React Intl](https://github.com/yahoo/react-intl#react-intl) 2 | 3 | 1. Merge `feature/react-intl` branch with git. 4 | Because react-intl integration is built on top of `feature/redux`, you'll also get all the features. 5 | 6 | 2. Adjust `INTL_REQUIRE_DESCRIPTIONS` constant in `tools/webpack.config.js` around line 17: 7 | ```js 8 | const INTL_REQUIRE_DESCRIPTIONS = true; 9 | ``` 10 | When this boolean is set to true, the build will only succeed if a `description` is set for every message descriptor. 11 | 12 | 3. Adjust `locales` settings in `src/config.js`: 13 | ```js 14 | // default locale is the first one 15 | export const locales = ['en-GB', 'cs-CZ']; 16 | ``` 17 | Note that you should follow 18 | [BCP 47](https://tools.ietf.org/html/bcp47) 19 | ([RFC 5646](https://tools.ietf.org/html/rfc5646)). 20 | 21 | 4. Add locale support in `src/client.js`: 22 | ```js 23 | import en from 'react-intl/locale-data/en'; 24 | import cs from 'react-intl/locale-data/cs'; 25 | ... 26 | 27 | [en, cs].forEach(addLocaleData); 28 | ``` 29 | 30 | 5. Execute `yarn run extractMessages` or `yarn start` to strip out messages. 31 | Message files are created in `src/messages` directory. 32 | 33 | 6. Edit `src/messages/*.json` files, change only `message` property. 34 | 35 | 7. Execute `yarn run build`, 36 | your translations should be copied to `build/messages/` directory. 37 | 38 | 39 | ### How to write localizable components 40 | 41 | Just import the appropriate [component](https://github.com/yahoo/react-intl/wiki#the-react-intl-module) from `react-intl` 42 | 43 | - For localizable text use 44 | [``](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage). 45 | - You can also use it with 46 | the [`defineMessages()`](https://github.com/yahoo/react-intl/wiki/API#definemessages) helper. 47 | 48 | - For date and time: 49 | [``](https://github.com/yahoo/react-intl/wiki/Components#formatteddate) 50 | [``](https://github.com/yahoo/react-intl/wiki/Components#formattedtime) 51 | [``](https://github.com/yahoo/react-intl/wiki/Components#formattedrelative) 52 | 53 | - For numbers and currencies: 54 | [``](https://github.com/yahoo/react-intl/wiki/Components#formattednumber) 55 | [``](https://github.com/yahoo/react-intl/wiki/Components#formattedplural) 56 | 57 | - If possible, do not use ``, see how to use *Rich Text Formatting* with 58 | [``](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) 59 | 60 | - When you need an imperative formatting API, use the [`injectIntl`](https://github.com/yahoo/react-intl/wiki/API#injectintl) High-Order Component. 61 | 62 | #### Example 63 | 64 | ```jsx 65 | import { defineMessages, FormattedMessage, injectIntl, intlShape } from 'react-intl'; 66 | 67 | const messages = defineMessages({ 68 | text: { 69 | id: 'example.text', 70 | defaultMessage: 'Example text', 71 | description: 'Hi Pavel', 72 | }, 73 | textTemplate: { 74 | id: 'example.text.template', 75 | defaultMessage: 'Example text template', 76 | description: 'Hi {name}', 77 | }, 78 | }); 79 | 80 | function Example(props) { 81 | const text = props.intl.formatMessage(messages.textTemplate, { name: 'Pavel'}); 82 | return ( 83 |
84 | 89 | 90 | Pavel 94 | }} 95 | /> 96 |
97 | ); 98 | } 99 | 100 | Example.propTypes = { 101 | intl: intlShape, 102 | } 103 | 104 | export default injectIntl(Example); 105 | ``` 106 | 107 | ### Updating translations 108 | 109 | When running the development server, every source file is watched and parsed for changed messages. 110 | 111 | Messages files are updated on the fly. 112 | If a new definition is found, this definition is added to the end of every used `src/messages/xx-XX.json` file so when committing, new translations will be at the tail of file. 113 | 114 | When an untranslated message is removed and its `message` field is empty as well, the message will be deleted from all translation files. This is why the `files` array is present. 115 | 116 | When editing a translation file, it should be copied to `build/messages/` directory. 117 | 118 | ### Other References 119 | 120 | * [`Intl documentation on MDN`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl) 121 | * [express-request-language](https://github.com/tinganho/express-request-language#readme) 122 | – for more details how initial language negotiation works. 123 | -------------------------------------------------------------------------------- /docs/recipes/how-to-integrate-redux.md: -------------------------------------------------------------------------------- 1 | ## How to Integrate [Redux](http://redux.js.org/index.html) 2 | 3 | Merge `feature/redux` branch with Git. If you are interested in `feature/react-intl`, merge that 4 | branch instead as it also includes Redux. 5 | 6 | **If you don't know Redux well, you should [read about it first](http://redux.js.org/docs/basics/index.html).** 7 | 8 | 9 | ### Creating Actions 10 | 11 | 1. Go to `src/constants/index.js` and define action name there. 12 | 13 | 2. Go to `src/actions/` and create file with appropriate name. You can copy 14 | `src/actions/runtime.js` as a template. 15 | 16 | 3. If you need async actions, use [`redux-thunk`](https://github.com/gaearon/redux-thunk#readme). 17 | For inspiration on how to create async actions you can look at 18 | [`setLocale`](https://github.com/kriasoft/react-starter-kit/blob/feature/react-intl/src/actions/intl.js) 19 | action from `feature/react-intl`. 20 | See [Async Flow](http://redux.js.org/docs/advanced/AsyncFlow.html) for more information on this 21 | topic. 22 | 23 | 24 | ### Creating Reducer (aka Store) 25 | 26 | 1. Go to [`src/reducers/`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers) and create new file there. 27 | 28 | You can copy [`src/reducers/runtime.js`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers/runtime.js) as a template. 29 | 30 | - Do not forget to always return `state`. 31 | - Never mutate provided `state`. 32 | If you mutate state, rendering of connected component will not be triggered because of `===` equality. 33 | Always return new value if you perform state update. 34 | You can use this construct: `{ ...state, updatedKey: action.payload.value, }` 35 | - Keep in mind that store state *must* be repeatable by replaying actions on it. 36 | For example, when you store timestamp, pass it into *action payload*. 37 | If you call REST API, do it in action. *Never do this in reducer!* 38 | 39 | 2. Edit [`src/reducers/index.js`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers/index.js), import your reducer and add it to root reducer created by 40 | [`combineReducers`](http://redux.js.org/docs/api/combineReducers.html) 41 | 42 | 43 | ### Connecting Components 44 | 45 | You can use [`connect()`](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) High-Order Component from [`react-redux`](https://github.com/reactjs/react-redux#readme) package. 46 | 47 | See [Usage With React](http://redux.js.org/docs/basics/UsageWithReact.html) on redux.js.org. 48 | 49 | For an example you can look at 50 | [``](https://github.com/kriasoft/react-starter-kit/blob/feature/react-intl/src/components/LanguageSwitcher/LanguageSwitcher.js) 51 | component from `feature/react-intl` branch. It demonstrates both subscribing to store and dispatching actions. 52 | 53 | 54 | ### Dispatching Actions On Server 55 | 56 | See source of `src/server.js` 57 | -------------------------------------------------------------------------------- /docs/recipes/how-to-use-sass.md: -------------------------------------------------------------------------------- 1 | ## How to Use Sass/SCSS 2 | 3 | > **Note**: Using plain CSS via [PostCSS](http://postcss.org/) is recommended approach because it 4 | reduces the size of the tech stack used in the project, enforces you to learn vanilla CSS syntax 5 | with modern CSS Level 3+ features that allow you doing everything you would normally do with 6 | Sass/SCSS. Also compilation of plain `.css` files should work faster with `postcss` pre-processor 7 | than `node-sass`. 8 | 9 | ### Step 1 10 | 11 | Install [`node-sass`](https://github.com/sass/node-sass) 12 | (includes [node-gyp](https://github.com/nodejs/node-gyp#readme) 13 | and [prerequisites](https://github.com/nodejs/node-gyp#installation)) and 14 | [`sass-loader`](https://github.com/jtangelder/sass-loader) modules as dev dependencies: 15 | 16 | ```sh 17 | $ yarn add node-sass --dev 18 | $ yarn add sass-loader --dev 19 | ``` 20 | 21 | ### Step 2 22 | 23 | Update [`webpack.config.js`](../../tools/webpack.config.js) file to use `sass-loader` for `.scss` files: 24 | 25 | ```js 26 | const config = { 27 | ... 28 | module: { 29 | rules: [ 30 | ... 31 | { 32 | test: /\.scss$/, 33 | use: [ 34 | { 35 | loader: 'isomorphic-style-loader', 36 | }, 37 | { 38 | loader: 'css-loader', 39 | options: { 40 | sourceMap: isDebug, 41 | minimize: !isDebug, 42 | }, 43 | }, 44 | { 45 | loader: 'postcss-loader', 46 | options: { 47 | config: './tools/postcss.sass.js', 48 | }, 49 | }, 50 | { 51 | loader: 'sass-loader', 52 | }, 53 | ], 54 | }, 55 | ... 56 | ] 57 | } 58 | ... 59 | } 60 | ``` 61 | 62 | ### Step 3 63 | 64 | Add one more configuration (`tools/postcss.sass.js`) for [PostCSS](https://github.com/postcss/postcss) to 65 | enable [Autoprefixer](https://github.com/postcss/autoprefixer) for your `.scss` files: 66 | 67 | ```js 68 | module.exports = () => ({ 69 | plugins: [ 70 | require('autoprefixer')(), 71 | ], 72 | }); 73 | ``` 74 | 75 | For more information visit https://github.com/jtangelder/sass-loader and https://github.com/sass/node-sass 76 | -------------------------------------------------------------------------------- /docs/recipes/using-npm-and-webpack-as-a-build-tool.md: -------------------------------------------------------------------------------- 1 | ## Using Yarn and Webpack as a Build Tool 2 | 3 | The [Yarn](https://yarnpkg.com/) command line utility that comes with Node.js 4 | allows you to run arbitrary scripts and [Node.js modules](https://www.npmjs.com/) 5 | without them being globally installed. This is very convenient, because other 6 | developers in your team don't need to worry about having some set of tools 7 | installed globally before they can execute build automation scripts in your 8 | project. 9 | 10 | For example, if you need to lint your JavaScript code with [ESLint](http://eslint.org/) 11 | and [JSCS](http://jscs.info/), you just install them as project's dependencies: 12 | 13 | ```shell 14 | $ yarn add eslint jscs --dev 15 | ``` 16 | 17 | Add a new command line to `package.json/scripts`: 18 | 19 | ```json 20 | { 21 | "devDependencies": { 22 | "eslint": "^1.10.0", 23 | "jscs": "^2.7.0" 24 | }, 25 | "scripts": { 26 | "lint": "eslint src && jscs src" 27 | } 28 | } 29 | ``` 30 | 31 | And execute it by running: 32 | 33 | ```shell 34 | $ yarn run lint # yarn run 35 | ``` 36 | 37 | Which will be the same as running `./node_modules/bin/eslint src && ./node_modules/bin/jscs src`, 38 | except that the former has a shorter syntax and works the the same way on all 39 | platforms (Mac OS X, Windows, Linux). 40 | 41 | The same way you can run [Webpack](http://webpack.github.io/) module bundler 42 | to compile the source code of your app into a distributable format. Since 43 | Webpack has numerous [configuration options](http://webpack.github.io/docs/configuration), 44 | it's a good idea to have all of them in a separate configuration file, as 45 | opposed to feeding them to Webpack's CLI as command line arguments. As a rule 46 | of thumb, you want to keep the "scripts" section in your `package.json` file 47 | short enough and easy to read. 48 | 49 | For example, you may have `src/client.js` and `src/server.js` files that used 50 | as entry points to the client-side and server-side code of your app. The 51 | following Webpack configuration file (`webpack.config.js`) can be used 52 | to bundle them into client-side and server-side application bundles - 53 | `build/public/client.js` and `build/server.js` respectively: 54 | 55 | ```js 56 | module.exports = [{ 57 | context: __dirname + '/src' 58 | entry: './client.js', 59 | output: { 60 | path: __dirname + '/build/public', 61 | filename: 'client.js' 62 | } 63 | }, { 64 | context: __dirname + '/src', 65 | entry: './server.js', 66 | output: { 67 | path: __dirname + '/build', 68 | filename: 'server.js', 69 | libraryTarget: 'commonjs2' 70 | }, 71 | target: 'node', 72 | externals: /node_modules/, 73 | }]; 74 | ``` 75 | 76 | The `npm` script for it may look like this: 77 | 78 | ```json 79 | { 80 | "devDependencies": { 81 | "webpack": "^1.12.0" 82 | }, 83 | "scripts": { 84 | "build": "webpack --config webpack.config.js" 85 | } 86 | } 87 | ``` 88 | 89 | You can run it as follows: 90 | 91 | ```shell 92 | $ yarn run build 93 | ``` 94 | -------------------------------------------------------------------------------- /docs/testing-your-application.md: -------------------------------------------------------------------------------- 1 | ## Testing your application 2 | 3 | ### Used libraries 4 | 5 | RSK comes with the following libraries for testing purposes: 6 | 7 | - [Mocha](https://mochajs.org/) - Node.js and browser test runner 8 | - [Chai](http://chaijs.com/) - Assertion library 9 | - [Enzyme](https://github.com/airbnb/enzyme) - Testing utilities for React 10 | 11 | You may also want to take a look at the following related packages: 12 | 13 | - [jsdom](https://github.com/tmpvar/jsdom) 14 | - [react-addons-test-utils](https://www.npmjs.com/package/react-addons-test-utils) 15 | 16 | ### Running tests 17 | 18 | To test your application simply run the 19 | [`yarn test`](https://github.com/kriasoft/react-starter-kit/blob/b22b1810461cec9c53eedffe632a3ce70a6b29a3/package.json#L154) 20 | command which will: 21 | - recursively find all files ending with `.test.js` in your `src/` directory 22 | - mocha execute found files 23 | 24 | ```bash 25 | yarn test 26 | ``` 27 | 28 | ### Conventions 29 | 30 | - test filenames MUST end with `test.js` or `yarn test` will not be able to detect them 31 | - test filenames SHOULD be named after the related component (e.g. create `Login.test.js` for 32 | `Login.js` component) 33 | 34 | ### Basic example 35 | 36 | To help you on your way RSK comes with the following 37 | [basic test case](https://github.com/kriasoft/react-starter-kit/blob/master/src/components/Layout/Layout.test.js) 38 | you can use as a starting point: 39 | 40 | ```js 41 | import React from 'react'; 42 | import { expect } from 'chai'; 43 | import { shallow } from 'enzyme'; 44 | import App from '../App'; 45 | import Layout from './Layout'; 46 | 47 | describe('Layout', () => { 48 | 49 | it('renders children correctly', () => { 50 | const wrapper = shallow( 51 | {} }}> 52 | 53 |
54 | 55 | 56 | ); 57 | 58 | expect(wrapper.contains(
)).to.be.true; 59 | }); 60 | 61 | }); 62 | ``` 63 | 64 | ### React-intl exampleß 65 | 66 | React-intl users MUST render/wrap components inside an IntlProvider like the example below: 67 | 68 | The example below example is a drop-in test for the RSK `Header` component: 69 | 70 | ```js 71 | import React from 'react'; 72 | import Header from './Header'; 73 | import IntlProvider from 'react-intl'; 74 | import Navigation from '../../components/Navigation'; 75 | 76 | describe('A test suite for
', () => { 77 | 78 | it('should contain a component', () => { 79 | it('rendering', () => { 80 | const wrapper = renderIntoDocument(
); 81 | expect(wrapper.find(Navigation)).to.have.length(1); 82 | }); 83 | }); 84 | 85 | }); 86 | ``` 87 | 88 | Please note that NOT using IntlProvider will produce the following error: 89 | 90 | > Invariant Violation: [React Intl] Could not find required `intl` object. 91 | > needs to exist in the component ancestry. 92 | 93 | ### Linting 94 | 95 | In order to check if your JavaScript and CSS code follows the suggested style guidelines run: 96 | 97 | ```bash 98 | yarn run lint 99 | ``` 100 | 101 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web", 3 | "version": "0.0.0", 4 | "private": true, 5 | "engines": { 6 | "node": ">=6.5", 7 | "npm": ">=3.10" 8 | }, 9 | "browserslist": [ 10 | ">1%", 11 | "last 4 versions", 12 | "Firefox ESR", 13 | "not ie < 9" 14 | ], 15 | "dependencies": { 16 | "babel-polyfill": "^6.23.0", 17 | "bluebird": "^3.5.0", 18 | "body-parser": "^1.17.1", 19 | "classnames": "^2.2.5", 20 | "cookie-parser": "^1.4.3", 21 | "core-js": "^2.4.1", 22 | "dotenv": "^4.0.0", 23 | "express": "^4.15.2", 24 | "express-graphql": "^0.6.4", 25 | "express-jwt": "^5.1.0", 26 | "fastclick": "^1.0.6", 27 | "graphql": "^0.9.2", 28 | "history": "^4.6.1", 29 | "hls.js": "^0.7.5", 30 | "isomorphic-style-loader": "^1.1.0", 31 | "jest": "^20.0.0", 32 | "jquery": "^3.2.1", 33 | "jsonwebtoken": "^7.3.0", 34 | "mediaelement": "^4.0.6", 35 | "node-fetch": "^1.6.3", 36 | "normalize.css": "^6.0.0", 37 | "passport": "^0.3.2", 38 | "passport-facebook": "^2.1.1", 39 | "pretty-error": "^2.1.0", 40 | "prop-types": "^15.5.6", 41 | "query-string": "^4.3.2", 42 | "react": "^15.5.3", 43 | "react-dom": "^15.5.3", 44 | "react-player": "^0.15.0", 45 | "react-redux": "^5.0.3", 46 | "react-wavesurfer": "^0.8.3", 47 | "redux": "^3.6.0", 48 | "sequelize": "^3.30.4", 49 | "source-map-support": "^0.4.14", 50 | "treactr-canvas-knob": "^0.3.6", 51 | "treactr-slider": "^7.0.1", 52 | "treactr-toggle": "^3.0.8", 53 | "universal-router": "^3.0.0", 54 | "wavesurfer.js": "^5.0.0", 55 | "webmidi": "^2.0.0-rc.5", 56 | "whatwg-fetch": "^2.0.3", 57 | "youtube-audio-stream": "^0.0.46" 58 | }, 59 | "devDependencies": { 60 | "assets-webpack-plugin": "^3.9.12", 61 | "autoprefixer": "^6.7.7", 62 | "babel-cli": "^6.26.0", 63 | "babel-core": "^6.24.1", 64 | "babel-eslint": "^7.1.1", 65 | "babel-loader": "^6.4.1", 66 | "babel-node": "^0.0.1-security", 67 | "babel-plugin-rewire": "^1.1.0", 68 | "babel-preset-env": "^1.3.3", 69 | "babel-preset-react": "^6.24.1", 70 | "babel-preset-react-optimize": "^1.0.1", 71 | "babel-preset-stage-2": "^6.24.1", 72 | "babel-register": "^6.24.1", 73 | "babel-template": "^6.24.1", 74 | "babel-types": "^6.24.1", 75 | "browser-sync": "^2.18.8", 76 | "chai": "^3.5.0", 77 | "chokidar": "^1.6.1", 78 | "css-loader": "^0.28.0", 79 | "editorconfig-tools": "^0.1.1", 80 | "enzyme": "^2.8.0", 81 | "eslint": "^3.19.0", 82 | "eslint-config-airbnb": "^14.1.0", 83 | "eslint-loader": "^1.7.1", 84 | "eslint-plugin-css-modules": "^2.7.1", 85 | "eslint-plugin-import": "^2.2.0", 86 | "eslint-plugin-jsx-a11y": "^4.0.0", 87 | "eslint-plugin-react": "^6.10.3", 88 | "file-loader": "^0.11.1", 89 | "front-matter": "^2.1.2", 90 | "glob": "^7.1.1", 91 | "json-loader": "^0.5.4", 92 | "lint-staged": "^3.4.0", 93 | "markdown-it": "^8.3.1", 94 | "mkdirp": "^0.5.1", 95 | "mocha": "^3.2.0", 96 | "pixrem": "^3.0.2", 97 | "pleeease-filters": "^3.0.1", 98 | "postcss": "^5.2.16", 99 | "postcss-calc": "^5.3.1", 100 | "postcss-color-function": "^3.0.0", 101 | "postcss-custom-media": "^5.0.1", 102 | "postcss-custom-properties": "^5.0.2", 103 | "postcss-custom-selectors": "^3.0.0", 104 | "postcss-flexbugs-fixes": "^2.1.0", 105 | "postcss-global-import": "^1.0.0", 106 | "postcss-import": "^9.1.0", 107 | "postcss-loader": "^1.3.3", 108 | "postcss-media-minmax": "^2.1.2", 109 | "postcss-nested": "^1.0.0", 110 | "postcss-nesting": "^2.3.1", 111 | "postcss-pseudoelements": "^4.0.0", 112 | "postcss-selector-matches": "^2.0.5", 113 | "postcss-selector-not": "^2.0.0", 114 | "postcss-url": "^5.1.2", 115 | "pre-commit": "^1.2.2", 116 | "raw-loader": "^0.5.1", 117 | "react-addons-test-utils": "^15.5.1", 118 | "react-deep-force-update": "^2.0.1", 119 | "react-hot-loader": "^3.0.0-beta.6", 120 | "redbox-react": "^1.3.6", 121 | "redux-devtools": "^3.3.2", 122 | "rimraf": "^2.6.1", 123 | "sinon": "^2.1.0", 124 | "sqlite3": "^5.0.2", 125 | "stylefmt": "^5.3.2", 126 | "stylelint": "^7.10.0", 127 | "stylelint-config-standard": "^16.0.0", 128 | "url-loader": "^0.5.8", 129 | "wavesurfer": "^1.3.4", 130 | "wavesurfer.js": "^5.0.0", 131 | "webmidi": "^2.0.0-rc.5", 132 | "webpack": "^2.3.3", 133 | "webpack-bundle-analyzer": "^2.3.1", 134 | "webpack-dev-middleware": "^1.10.1", 135 | "webpack-hot-middleware": "^2.18.0", 136 | "write-file-webpack-plugin": "^4.0.0" 137 | }, 138 | "babel": { 139 | "presets": [ 140 | [ 141 | "env", 142 | { 143 | "targets": { 144 | "node": "current" 145 | } 146 | } 147 | ], 148 | "stage-2", 149 | "react" 150 | ], 151 | "env": { 152 | "test": { 153 | "plugins": [ 154 | "rewire" 155 | ] 156 | } 157 | } 158 | }, 159 | "eslintConfig": { 160 | "parser": "babel-eslint", 161 | "extends": [ 162 | "airbnb", 163 | "plugin:css-modules/recommended" 164 | ], 165 | "plugins": [ 166 | "css-modules" 167 | ], 168 | "globals": { 169 | "__DEV__": true 170 | }, 171 | "env": { 172 | "browser": true 173 | }, 174 | "rules": { 175 | "import/extensions": "off", 176 | "import/no-extraneous-dependencies": "off", 177 | "react/jsx-filename-extension": "off", 178 | "react/prefer-stateless-function": "off" 179 | } 180 | }, 181 | "stylelint": { 182 | "extends": "stylelint-config-standard", 183 | "rules": { 184 | "string-quotes": "single", 185 | "property-no-unknown": [ 186 | true, 187 | { 188 | "ignoreProperties": [ 189 | "composes" 190 | ] 191 | } 192 | ], 193 | "selector-pseudo-class-no-unknown": [ 194 | true, 195 | { 196 | "ignorePseudoClasses": [ 197 | "global" 198 | ] 199 | } 200 | ] 201 | } 202 | }, 203 | "pre-commit": "lint:staged", 204 | "lint-staged": { 205 | "*.{cmd,html,json,md,sh,txt,xml,yml}": [ 206 | "editorconfig-tools fix", 207 | "git add" 208 | ], 209 | "*.{js,jsx}": [ 210 | "eslint --fix", 211 | "git add" 212 | ], 213 | "*.{css,less,scss,sss}": [ 214 | "stylefmt", 215 | "stylelint", 216 | "git add" 217 | ] 218 | }, 219 | "jest": { 220 | "moduleNameMapper": { 221 | "^.+\\.(css|less)$": "/config/CSSStub.js" 222 | } 223 | }, 224 | "scripts": { 225 | "lint:js": "eslint src tools", 226 | "lint:css": "stylelint \"src/**/*.{css,less,scss,sss}\"", 227 | "lint:staged": "lint-staged", 228 | "lint": "yarn run lint:js && yarn run lint:css", 229 | "test": "mocha \"src/**/*.test.js\" --require babel-register --require test/setup.js", 230 | "test:watch": "yarn run test -- --reporter min --watch", 231 | "clean": "babel-node tools/run clean", 232 | "copy": "babel-node tools/run copy", 233 | "bundle": "babel-node tools/run bundle", 234 | "build": "babel-node tools/run build", 235 | "build:stats": "yarn run build -- --release --analyse", 236 | "deploy": "babel-node tools/run deploy", 237 | "deployDev": "babel-node tools/run deployDev", 238 | "render": "babel-node tools/run render", 239 | "serve": "babel-node tools/run runServer", 240 | "start": "babel-node tools/run start" 241 | }, 242 | "resolutions": { 243 | "graceful-fs": "^4.2.4" 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/public/favicon.ico -------------------------------------------------------------------------------- /public/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | CSS3, HTML5, JavaScript 15 | React Starter Kit -- https://reactstarter.com/ 16 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /public/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/public/screenshot.png -------------------------------------------------------------------------------- /public/tile-round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/public/tile-round.png -------------------------------------------------------------------------------- /public/tile-wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/public/tile-wide.png -------------------------------------------------------------------------------- /public/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/public/tile.png -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | import React from 'react'; 11 | import ReactDOM from 'react-dom'; 12 | import FastClick from 'fastclick'; 13 | import queryString from 'query-string'; 14 | import { createPath } from 'history/PathUtils'; 15 | import history from './core/history'; 16 | import App from './components/App'; 17 | import { updateMeta } from './core/DOMUtils'; 18 | import { ErrorReporter, deepForceUpdate } from './core/devUtils'; 19 | 20 | /* eslint-disable global-require */ 21 | 22 | // Global (context) variables that can be easily accessed from any React component 23 | // https://facebook.github.io/react/docs/context.html 24 | const context = { 25 | // Enables critical path CSS rendering 26 | // https://github.com/kriasoft/isomorphic-style-loader 27 | insertCss: (...styles) => { 28 | // eslint-disable-next-line no-underscore-dangle 29 | const removeCss = styles.map(x => x._insertCss()); 30 | return () => { removeCss.forEach(f => f()); }; 31 | }, 32 | }; 33 | 34 | // Switch off the native scroll restoration behavior and handle it manually 35 | // https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration 36 | const scrollPositionsHistory = {}; 37 | if (window.history && 'scrollRestoration' in window.history) { 38 | window.history.scrollRestoration = 'manual'; 39 | } 40 | 41 | let onRenderComplete = function initialRenderComplete() { 42 | const elem = document.getElementById('css'); 43 | if (elem) elem.parentNode.removeChild(elem); 44 | onRenderComplete = function renderComplete(route, location) { 45 | document.title = route.title; 46 | 47 | updateMeta('description', route.description); 48 | // Update necessary tags in at runtime here, ie: 49 | // updateMeta('keywords', route.keywords); 50 | // updateCustomMeta('og:url', route.canonicalUrl); 51 | // updateCustomMeta('og:image', route.imageUrl); 52 | // updateLink('canonical', route.canonicalUrl); 53 | // etc. 54 | 55 | let scrollX = 0; 56 | let scrollY = 0; 57 | const pos = scrollPositionsHistory[location.key]; 58 | if (pos) { 59 | scrollX = pos.scrollX; 60 | scrollY = pos.scrollY; 61 | } else { 62 | const targetHash = location.hash.substr(1); 63 | if (targetHash) { 64 | const target = document.getElementById(targetHash); 65 | if (target) { 66 | scrollY = window.pageYOffset + target.getBoundingClientRect().top; 67 | } 68 | } 69 | } 70 | 71 | // Restore the scroll position if it was saved into the state 72 | // or scroll to the given #hash anchor 73 | // or scroll to top of the page 74 | window.scrollTo(scrollX, scrollY); 75 | 76 | // Google Analytics tracking. Don't send 'pageview' event after 77 | // the initial rendering, as it was already sent 78 | if (window.ga) { 79 | window.ga('send', 'pageview', createPath(location)); 80 | } 81 | }; 82 | }; 83 | 84 | // Make taps on links and buttons work fast on mobiles 85 | FastClick.attach(document.body); 86 | 87 | const container = document.getElementById('app'); 88 | let appInstance; 89 | let currentLocation = history.location; 90 | let router = require('./core/router').default; 91 | 92 | // Re-render the app when window.location changes 93 | async function onLocationChange(location, action) { 94 | // Remember the latest scroll position for the previous location 95 | scrollPositionsHistory[currentLocation.key] = { 96 | scrollX: window.pageXOffset, 97 | scrollY: window.pageYOffset, 98 | }; 99 | // Delete stored scroll position for next page if any 100 | if (action === 'PUSH') { 101 | delete scrollPositionsHistory[location.key]; 102 | } 103 | currentLocation = location; 104 | 105 | try { 106 | // Traverses the list of routes in the order they are defined until 107 | // it finds the first route that matches provided URL path string 108 | // and whose action method returns anything other than `undefined`. 109 | const route = await router.resolve({ 110 | path: location.pathname, 111 | query: queryString.parse(location.search), 112 | }); 113 | 114 | // Prevent multiple page renders during the routing process 115 | if (currentLocation.key !== location.key) { 116 | return; 117 | } 118 | 119 | if (route.redirect) { 120 | history.replace(route.redirect); 121 | return; 122 | } 123 | 124 | appInstance = ReactDOM.render( 125 | {route.component}, 126 | container, 127 | () => onRenderComplete(route, location), 128 | ); 129 | } catch (error) { 130 | // Display the error in full-screen for development mode 131 | if (__DEV__) { 132 | appInstance = null; 133 | document.title = `Error: ${error.message}`; 134 | ReactDOM.render(, container); 135 | throw error; 136 | } 137 | 138 | console.error(error); // eslint-disable-line no-console 139 | 140 | // Do a full page reload if error occurs during client-side navigation 141 | if (action && currentLocation.key === location.key) { 142 | window.location.reload(); 143 | } 144 | } 145 | } 146 | 147 | // Handle client-side navigation by using HTML5 History API 148 | // For more information visit https://github.com/mjackson/history#readme 149 | history.listen(onLocationChange); 150 | onLocationChange(currentLocation); 151 | 152 | // Handle errors that might happen after rendering 153 | // Display the error in full-screen for development mode 154 | if (__DEV__) { 155 | window.addEventListener('error', (event) => { 156 | appInstance = null; 157 | document.title = `Runtime Error: ${event.error.message}`; 158 | ReactDOM.render(, container); 159 | }); 160 | } 161 | 162 | // Enable Hot Module Replacement (HMR) 163 | if (module.hot) { 164 | module.hot.accept('./core/router', () => { 165 | router = require('./core/router').default; 166 | 167 | if (appInstance) { 168 | try { 169 | // Force-update the whole tree, including components that refuse to update 170 | deepForceUpdate(appInstance); 171 | } catch (error) { 172 | appInstance = null; 173 | document.title = `Hot Update Error: ${error.message}`; 174 | ReactDOM.render(, container); 175 | return; 176 | } 177 | } 178 | 179 | onLocationChange(currentLocation); 180 | }); 181 | } 182 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | import React from 'react'; 11 | import PropTypes from 'prop-types'; 12 | 13 | const ContextType = { 14 | // Enables critical path CSS rendering 15 | // https://github.com/kriasoft/isomorphic-style-loader 16 | insertCss: PropTypes.func.isRequired, 17 | }; 18 | 19 | /** 20 | * The top-level React component setting context (global) variables 21 | * that can be accessed from all the child components. 22 | * 23 | * https://facebook.github.io/react/docs/context.html 24 | * 25 | * Usage example: 26 | * 27 | * const context = { 28 | * history: createBrowserHistory(), 29 | * store: createStore(), 30 | * }; 31 | * 32 | * ReactDOM.render( 33 | * 34 | * 35 | * 36 | * 37 | * , 38 | * container, 39 | * ); 40 | */ 41 | class App extends React.PureComponent { 42 | 43 | static propTypes = { 44 | context: PropTypes.shape(ContextType).isRequired, 45 | children: PropTypes.element.isRequired, 46 | }; 47 | 48 | static childContextTypes = ContextType; 49 | 50 | getChildContext() { 51 | return this.props.context; 52 | } 53 | 54 | render() { 55 | // NOTE: If you need to add or modify header, footer etc. of the app, 56 | // please do that inside the Layout component. 57 | return React.Children.only(this.props.children); 58 | } 59 | 60 | } 61 | 62 | export default App; 63 | -------------------------------------------------------------------------------- /src/components/CrossFader/CrossFader.css: -------------------------------------------------------------------------------- 1 | @global-import 'treactr-slider/dist/treactr-slider.css'; 2 | 3 | :global { 4 | .rc-slider-vertical { 5 | margin: auto; 6 | } 7 | 8 | .rc-slider-vertical .rc-slider-rail { 9 | margin-left: -8px; 10 | height: 100%; 11 | width: 19px; 12 | background: linear-gradient(to bottom, #071212, #071212 50%, #313a3a 50%, #313a3a); 13 | background-size: 100% 4px; 14 | border: solid 3px #071212; 15 | outline: solid 3px #4f5353; 16 | } 17 | 18 | .rc-slider-vertical .rc-slider-track { 19 | margin-left: -8px; 20 | width: 19px; 21 | background-color: white; 22 | opacity: 0; 23 | } 24 | 25 | .rc-slider-vertical .rc-slider-handle { 26 | margin-left: -17px; 27 | margin-bottom: -6px; 28 | } 29 | 30 | /* .rc-slider { 31 | position: relative; 32 | height: 14px; 33 | padding: 5px 0; 34 | width: 100%; 35 | border-radius: 6px; 36 | box-sizing: border-box; 37 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 38 | } */ 39 | 40 | .rc-slider-track { 41 | background-color: #0b0c0c; 42 | } 43 | 44 | .rc-slider-rail { 45 | background-color: #0b0c0c; 46 | } 47 | 48 | .rc-slider-handle { 49 | background-color: #2b2d2d; 50 | position: absolute; 51 | margin-left: -6px; 52 | margin-top: -16px; 53 | width: 14px; 54 | height: 36px; 55 | cursor: pointer; 56 | border-radius: 2px; 57 | border: solid 1px #2b2d2d; 58 | border-top: solid 1px #3d3e3e; 59 | box-shadow: 0 0 0 1px black; 60 | } 61 | 62 | .rc-slider-handle:hover { 63 | border-color: #2b2d2d; 64 | } 65 | 66 | /* hr { 67 | width: 20%; 68 | height: 80%; 69 | background: #c22; 70 | } */ 71 | 72 | /* 73 | .rc-slider-handle-active:active { 74 | border-color: #57c5f7; 75 | box-shadow: 0 0 5px #57c5f7; 76 | } 77 | 78 | .rc-slider-mark { 79 | position: absolute; 80 | top: 18px; 81 | left: 0; 82 | width: 100%; 83 | font-size: 12px; 84 | } 85 | 86 | .rc-slider-mark-text { 87 | position: absolute; 88 | display: inline-block; 89 | vertical-align: middle; 90 | text-align: center; 91 | cursor: pointer; 92 | color: #999; 93 | } 94 | 95 | .rc-slider-mark-text-active { 96 | color: #666; 97 | } 98 | 99 | .rc-slider-step { 100 | position: absolute; 101 | width: 100%; 102 | height: 4px; 103 | background: transparent; 104 | } 105 | 106 | .rc-slider-dot { 107 | position: absolute; 108 | bottom: -2px; 109 | margin-left: -4px; 110 | width: 8px; 111 | height: 8px; 112 | border: 2px solid #e9e9e9; 113 | background-color: #fff; 114 | cursor: pointer; 115 | border-radius: 50%; 116 | vertical-align: middle; 117 | } 118 | 119 | .rc-slider-dot:first-child { 120 | margin-left: -4px; 121 | } 122 | 123 | .rc-slider-dot:last-child { 124 | margin-left: -4px; 125 | } 126 | 127 | .rc-slider-dot-active { 128 | border-color: #96dbfa; 129 | } 130 | 131 | .rc-slider-disabled { 132 | background-color: #e9e9e9; 133 | } 134 | 135 | .rc-slider-disabled .rc-slider-track { 136 | background-color: #ccc; 137 | } 138 | 139 | .rc-slider-disabled .rc-slider-handle, 140 | .rc-slider-disabled .rc-slider-dot { 141 | border-color: #ccc; 142 | background-color: #fff; 143 | cursor: not-allowed; 144 | } 145 | 146 | .rc-slider-disabled .rc-slider-mark-text, 147 | .rc-slider-disabled .rc-slider-dot { 148 | cursor: not-allowed !important; 149 | } */ 150 | } 151 | 152 | p { 153 | color: #bdbdbd; 154 | margin: 2px 1px; 155 | font-size: 0.5em; 156 | text-align: center; 157 | } 158 | 159 | .slider { 160 | width: 150px; 161 | margin: 7px auto; 162 | } 163 | 164 | .CrossFader_container { 165 | background: #242828; 166 | border: solid 1px #000; 167 | width: 1000px; 168 | overflow: hidden; 169 | } 170 | 171 | .CrossFader_Box { 172 | /* Background Gradient */ 173 | background: -webkit-linear-gradient(#373b3c, #313334); 174 | background: -moz-linear-gradient(#373b3c, #313334); 175 | background-color: #373b3c; 176 | background-image: linear-gradient(#373b3c, #313334); 177 | 178 | /* Border */ 179 | border-bottom: solid 1px #2a2d2e; 180 | border-top: solid 1px #434748; 181 | border-radius: 2px; 182 | -moz-border-radius: 2px; 183 | -webkit-border-radius: 2px; 184 | color: #8f9091; 185 | width: 1000px; 186 | height: 44px; 187 | overflow: hidden; 188 | } 189 | 190 | .xf_top_border { 191 | margin-top: 5px; 192 | margin-bottom: 5px; 193 | } 194 | 195 | .xf_bottom_border { 196 | margin-top: 5px; 197 | margin-bottom: 5px; 198 | } 199 | -------------------------------------------------------------------------------- /src/components/CrossFader/CrossFader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import { BiDirectionalKnob } from 'treactr-canvas-knob'; 3 | // import { Kill, FxToggle1, FxToggle2, ToggleMonitorCue } from 'treactr-toggle'; 4 | import Slider from 'treactr-slider'; 5 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 6 | import s from './CrossFader.css'; 7 | 8 | class CrossFader extends React.Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | // Position 13 | position: 63, 14 | }; 15 | } 16 | 17 | render() { 18 | return ( 19 |
20 | {/* EQ/Volume Box */} 21 |
22 |
23 |
24 |
25 |
26 | { 30 | this.setState({ position: newValue }); 31 | }} 32 | /> 33 |
34 |
35 |
36 |
37 |
38 |
39 | ); 40 | } 41 | } 42 | 43 | export default withStyles(s)(CrossFader); 44 | -------------------------------------------------------------------------------- /src/components/CrossFader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CrossFader", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "./CrossFader.js" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/Deck/Deck.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/src/components/Deck/Deck.css -------------------------------------------------------------------------------- /src/components/Deck/Deck.js: -------------------------------------------------------------------------------- 1 | // Deck component: contains a mixer object and a player object 2 | import React from 'react'; 3 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 4 | 5 | class Deck extends React.Component { 6 | 7 | } 8 | 9 | export default withStyles(s)(Deck); 10 | -------------------------------------------------------------------------------- /src/components/Deck/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Deck", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "./Deck.js" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/Feedback/Feedback.css: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | @import '../variables.css'; 11 | 12 | .root { 13 | background: #f5f5f5; 14 | color: #333; 15 | } 16 | 17 | .container { 18 | margin: 0 auto; 19 | padding: 20px 8px; 20 | max-width: var(--max-content-width); 21 | text-align: center; 22 | font-size: 1.5em; /* ~24px */ 23 | } 24 | 25 | .link, 26 | .link:active, 27 | .link:hover, 28 | .link:visited { 29 | color: #333; 30 | text-decoration: none; 31 | } 32 | 33 | .link:hover { 34 | text-decoration: underline; 35 | } 36 | 37 | .spacer { 38 | padding-right: 15px; 39 | padding-left: 15px; 40 | } 41 | -------------------------------------------------------------------------------- /src/components/Feedback/Feedback.js: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | import React from 'react'; 11 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 12 | import s from './Feedback.css'; 13 | 14 | class Feedback extends React.Component { 15 | render() { 16 | return ( 17 |
18 |
19 | Ask a question 23 | | 24 | Report an issue 28 |
29 |
30 | ); 31 | } 32 | } 33 | 34 | export default withStyles(s)(Feedback); 35 | -------------------------------------------------------------------------------- /src/components/Feedback/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Feedback", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "./Feedback.js" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.css: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | @import '../variables.css'; 11 | 12 | .root { 13 | background: #232525; 14 | color: #fff; 15 | } 16 | 17 | .container { 18 | margin: 0 auto; 19 | padding: 20px 15px; 20 | max-width: var(--max-content-width); 21 | text-align: center; 22 | } 23 | 24 | .text { 25 | color: rgba(255, 255, 255, 0.5); 26 | } 27 | 28 | .spacer { 29 | color: rgba(255, 255, 255, 0.3); 30 | } 31 | 32 | .text, 33 | .link { 34 | padding: 2px 5px; 35 | font-size: 1em; 36 | } 37 | 38 | .link, 39 | .link:active, 40 | .link:visited { 41 | color: rgba(255, 255, 255, 0.6); 42 | text-decoration: none; 43 | } 44 | 45 | .link:hover { 46 | color: rgba(255, 255, 255, 1); 47 | } 48 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | import React from 'react'; 11 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 12 | import s from './Footer.css'; 13 | import Link from '../Link'; 14 | 15 | class Footer extends React.Component { 16 | render() { 17 | return ( 18 |
19 |
20 | © TReactr 21 | · 22 | Home 23 | · 24 | Admin 25 | · 26 | Privacy 27 | · 28 | GitHub 29 |
30 |
31 | ); 32 | } 33 | } 34 | 35 | export default withStyles(s)(Footer); 36 | -------------------------------------------------------------------------------- /src/components/Footer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Footer", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "./Footer.js" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/FxUnit/FxUnit.css: -------------------------------------------------------------------------------- 1 | @global-import 'treactr-toggle/style.css'; 2 | 3 | .FX_Unit_Box { 4 | margin: 2px; 5 | 6 | /* Background Gradient */ 7 | background: -webkit-linear-gradient(#373b3c, #313334); 8 | background: -moz-linear-gradient(#373b3c, #313334); 9 | background-color: #373b3c; 10 | background-image: linear-gradient(#373b3c, #313334); 11 | padding-left: 10px; 12 | padding-right: 10px; 13 | padding-top: 5px; 14 | 15 | /* Border */ 16 | border-bottom: solid 1px #2a2d2e; 17 | border-top: solid 1px #434748; 18 | border-radius: 2px; 19 | -moz-border-radius: 2px; 20 | -webkit-border-radius: 2px; 21 | color: #8f9091; 22 | width: auto; 23 | height: auto; 24 | overflow: hidden; 25 | } 26 | 27 | p.knob_label { 28 | margin: auto; 29 | font-size: 50%; 30 | text-align: center; 31 | } 32 | 33 | .knob { 34 | float: left; 35 | margin-left: 10px; 36 | margin-right: 10px; 37 | } 38 | -------------------------------------------------------------------------------- /src/components/FxUnit/FxUnit.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Knob } from 'treactr-canvas-knob'; 3 | import { Toggle } from 'treactr-toggle'; 4 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 5 | import s from './FxUnit.css'; 6 | 7 | class FxUnit extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | DryWet: 63, 12 | Knob1: 63, 13 | Knob2: 63, 14 | Knob3: 63, 15 | onOff: false, 16 | Toggle1: false, 17 | Toggle2: false, 18 | Toggle3: false, 19 | }; 20 | } 21 | 22 | render() { 23 | return ( 24 |
25 | 26 |
27 | { 30 | this.setState({ DryWet: newValue }); 31 | }} 32 | /> 33 |

D/W

34 | { 36 | this.setState({ onOff: !this.state.onOff }); 37 | }} 38 | /> 39 |
40 | 41 |
42 | { 45 | this.setState({ Knob1: newValue }); 46 | }} 47 | /> 48 |

K1

49 | { 51 | this.setState({ Toggle1: !this.state.Toggle1 }); 52 | }} 53 | /> 54 |
55 | 56 |
57 | { 60 | this.setState({ Knob2: newValue }); 61 | }} 62 | /> 63 |

K2

64 | { 66 | this.setState({ Toggle2: !this.state.Toggle2 }); 67 | }} 68 | /> 69 |
70 | 71 |
72 | { 75 | this.setState({ Knob3: newValue }); 76 | }} 77 | /> 78 |

K3

79 | { 81 | this.setState({ Toggle3: !this.state.Toggle3 }); 82 | }} 83 | /> 84 |
85 | 86 |
87 | ); 88 | } 89 | } 90 | 91 | export default withStyles(s)(FxUnit); 92 | -------------------------------------------------------------------------------- /src/components/FxUnit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FxUnit", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "./FxUnit.js" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/Header/Header.css: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | @import '../variables.css'; 11 | 12 | :root { 13 | --brand-color: #fff; 14 | } 15 | 16 | .root { 17 | background: #232525; 18 | color: #fff; 19 | } 20 | 21 | .container { 22 | margin: 0 auto; 23 | padding: 20px 0; 24 | max-width: var(--max-content-width); 25 | } 26 | 27 | .brand { 28 | color: color(var(--brand-color) lightness(+10%)); 29 | text-decoration: none; 30 | font-size: 1.75em; /* ~28px */ 31 | } 32 | 33 | .brandTxt { 34 | margin-left: 5px; 35 | font-weight: 600; 36 | } 37 | 38 | .nav { 39 | float: right; 40 | margin-top: 6px; 41 | } 42 | 43 | .banner { 44 | text-align: center; 45 | } 46 | 47 | .bannerTitle { 48 | margin: 0; 49 | padding: 10px; 50 | font-weight: normal; 51 | font-size: 4em; 52 | line-height: 1em; 53 | } 54 | 55 | .bannerDesc { 56 | padding: 0; 57 | color: rgba(255, 255, 255, 0.5); 58 | font-size: 1.25em; 59 | margin: 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/components/Header/Header.js: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | import React from 'react'; 11 | import withStyles from 'isomorphic-style-loader/lib/withStyles'; 12 | import s from './Header.css'; 13 | import Link from '../Link'; 14 | import Navigation from '../Navigation'; 15 | import logoUrl from './logo-small.png'; 16 | import logoUrl2x from './logo-small@2x.png'; 17 | 18 | class Header extends React.Component { 19 | render() { 20 | return ( 21 |
22 |
23 | 24 | 25 | React 26 | TREACTR 27 | 28 |
29 |

TReactr

30 |

A Traktor clone in React

31 |
32 |
33 |
34 | ); 35 | } 36 | } 37 | 38 | export default withStyles(s)(Header); 39 | -------------------------------------------------------------------------------- /src/components/Header/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/src/components/Header/logo-small.png -------------------------------------------------------------------------------- /src/components/Header/logo-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevin-chau/TReactr/8460424c7a812a79661e7b32d1a7dc4203ffff4d/src/components/Header/logo-small@2x.png -------------------------------------------------------------------------------- /src/components/Header/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Header", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "./Header.js" 6 | } 7 | -------------------------------------------------------------------------------- /src/components/Html.js: -------------------------------------------------------------------------------- 1 | /** 2 | * React Starter Kit (https://www.reactstarterkit.com/) 3 | * 4 | * Copyright © 2014-present Kriasoft, LLC. All rights reserved. 5 | * 6 | * This source code is licensed under the MIT license found in the 7 | * LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | import React from 'react'; 11 | import PropTypes from 'prop-types'; 12 | import { analytics } from '../config'; 13 | 14 | class Html extends React.Component { 15 | static propTypes = { 16 | title: PropTypes.string.isRequired, 17 | description: PropTypes.string.isRequired, 18 | styles: PropTypes.arrayOf(PropTypes.shape({ 19 | id: PropTypes.string.isRequired, 20 | cssText: PropTypes.string.isRequired, 21 | }).isRequired), 22 | scripts: PropTypes.arrayOf(PropTypes.string.isRequired), 23 | children: PropTypes.string.isRequired, 24 | }; 25 | 26 | static defaultProps = { 27 | styles: [], 28 | scripts: [], 29 | }; 30 | 31 | render() { 32 | const { title, description, styles, scripts, children } = this.props; 33 | return ( 34 | 35 | 36 | 37 | 38 | {title} 39 | 40 | 41 | 42 | {styles.map(style => 43 |