├── .editorconfig ├── .env ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── LIBRARY.md ├── LICENSE ├── README.md ├── config-overrides.js ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── rewires ├── eslint.js └── resolve.js ├── scripts └── copyBuildFiles.js ├── src ├── components │ ├── Button │ │ ├── Readme.md │ │ ├── index.js │ │ └── index.test.js │ └── index.js ├── demo │ ├── index.js │ └── registerServiceWorker.js ├── index.js └── setupTests.js ├── styleguide.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*.{js,jsx,ts,tsx,css}] 5 | indent_style = space 6 | indent_size = 2 7 | tab_width=8 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | 16 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | NODE_PATH=./src 2 | BROWSER=false -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /tests/** 2 | nightwatch.config.js 3 | test-setup.js 4 | src/resources/** 5 | /lib/ 6 | /styleguide/ 7 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb", 4 | "react-app", 5 | "prettier", 6 | "prettier/react" 7 | ], 8 | "plugins": [ 9 | "prettier" 10 | ], 11 | "settings": { 12 | "import/resolver": { 13 | "node": { 14 | "paths": [ 15 | "src" 16 | ] 17 | } 18 | } 19 | }, 20 | "rules": { 21 | "react/jsx-filename-extension": 0, 22 | "import/extensions": 0, 23 | "react/jsx-no-bind": [ 24 | "error", 25 | { 26 | "ignoreRefs": false, 27 | "allowArrowFunctions": false, 28 | "allowBind": false 29 | } 30 | ], 31 | "react/sort-prop-types": [ 32 | 1, 33 | { 34 | "callbacksLast": true 35 | } 36 | ], 37 | "prettier/prettier": [ 38 | 1, 39 | { 40 | "singleQuote": true, 41 | "trailingComma": "all", 42 | "semi": false 43 | } 44 | ] 45 | } 46 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | npm-debug.log* 15 | yarn-debug.log* 16 | 17 | 18 | # Runtime data 19 | pids 20 | *.pid 21 | *.seed 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Debug log from npm 37 | npm-debug.log 38 | 39 | # sass 40 | .sass-cache/ 41 | 42 | #ngrok 43 | ngrok 44 | /.idea 45 | /reports 46 | /screenshots 47 | /dist 48 | .project 49 | npm-debug.log.* 50 | /selenium-debug.log 51 | /grocerycop-website-3.1-ui.iml 52 | /.vscode/ 53 | /lib/ 54 | /.env.local 55 | /styleguide/ 56 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /build 2 | /node_modules -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false, 4 | "trailingComma": "all" 5 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "7" 5 | - "8" -------------------------------------------------------------------------------- /LIBRARY.md: -------------------------------------------------------------------------------- 1 | Set of the reusable components made of `semantic-ui-react` as a base 2 | 3 | 100% compatible with projects bootstrapped with create-react-app since 4 | was transpiled using `react-app` babel preset. 5 | 6 | ## How to install: 7 | ```bash 8 | npm i generic-components --save 9 | ``` 10 | or: 11 | ```bash 12 | yarn add generic-components 13 | ``` 14 | if you use Yarn instead of the npm. 15 | 16 | ## Usage: 17 | ```javascript 18 | import React, { Component } from "react"; 19 | import Button from "generic-components/Button"; 20 | // supported too but not recommended 21 | // import { Button } from "generic-components"; 22 | 23 | class App extends Component { 24 | render() { 25 | return ( 26 |
27 | 28 |
29 | ); 30 | } 31 | } 32 | ``` 33 | 34 | ## [Documentation styleguide](https://rip21.github.io/CRA-components-development/) 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Andrii Los 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 all 13 | 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 THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [create-react-app](https://github.com/facebookincubator/create-react-app) for components development 2 | 3 | [![Build Status](https://travis-ci.org/RIP21/CRA-components-development.svg?branch=master)](https://travis-ci.org/RIP21/CRA-components-development) 4 | [![Greenkeeper badge](https://badges.greenkeeper.io/RIP21/CRA-components-development.svg)](https://greenkeeper.io/) 5 | Is a minimal yet another boilerplate based on top of the famous 6 | create-react-app, made especially for creating components libraries with 7 | rich online docs powered by [Styleguidist](https://github.com/styleguidist/react-styleguidist) and all power of CRA. 8 | 9 | ### Includes: 10 | - [Styleguidist](https://github.com/styleguidist/react-styleguidist) for automatic styleguide docs generation 11 | - stylelint of [styled-components](https://github.com/styled-components/styled-components) 12 | - [prettier](https://github.com/prettier/prettier) 13 | - eslint 14 | - [create-react-app](https://github.com/facebookincubator/create-react-app) 15 | - [react-app-rewired](https://github.com/timarney/react-app-rewired) 16 | - babel with CRA preset and ENV preset (https://www.npmjs.com/package/babel-preset-react-app) for components libs transpiling 17 | - Scripts for publishing components with ES6 imports support 18 | - Publishing script for handy 19 | ```javascript 20 | import Button from "components-lib/Button"; 21 | ``` 22 | imports. Which means no import of unnecessary components! 23 | And also tree shaking! 24 | - Enzyme with `jest-enzyme` and `jest-styled-components` goodness! 25 | - [lint-staged 💩](https://github.com/okonet/lint-staged) installed for running prettier before any commit. 26 | So no wrong codestyle will leak into the codebase! 27 | - GitHub pages styleguide automatic deploy right after next release 28 | 29 | ## Commands 30 | To develop components run 31 | ```bash 32 | npm run styleguide 33 | ``` 34 | 35 | To test 36 | ```bash 37 | npm run test 38 | # For watch mode 39 | npm run test:watch 40 | # For tests with coverage info 41 | npm run test:coverage 42 | ``` 43 | 44 | To publish your lib run (which also will run a build process) 45 | ```bash 46 | npm run release 47 | ``` 48 | 49 | Also you can run `build, (stylelint, eslint, prettier) -> stylecheck, demo:start / build` for your 50 | amazing landing page for your component lib and other commands 51 | which are pretty descriptive but just a part of the release/build process :) 52 | 53 | ## More details 54 | As an example in boilerplate there is a `normalize.css` imported to styleguidist. 55 | Landing page is empty styled with `styled-components`. 56 | 57 | Since I use `styled-components` every day. There is also stylelint with 58 | `styled-components` preprocessor for linting styles in them. And hence 59 | no stylelinting of plain CSS. 60 | 61 | All your components should be in `src/components` folder, so it will be visible 62 | by styleguidist and so they will be bundled to the `lib` for future publishing. 63 | 64 | There is CRA underneath, so you can use all its goodness to write your landing page 65 | and also for testing your components library, collect test coverage on them etc. 66 | All setup this way so they will run only on `src/components` and will ignore all other 67 | folders which are not related to components library. 68 | 69 | Readme for your lib lay down in `LIBRARY.md` and will automatically be attached to 70 | the newly released version of the lib. 71 | 72 | ## More on release process 73 | Basically when you run `npm run release` 74 | It will run prettier, all linters, then all tests, and after all will bundle 75 | ignoring `test.js` your components. After that it will generate `package.json` for 76 | `lib` folder so handy `name/Button` imports will be possible. Then he will run `npm publish` 77 | on that newly created `package.json` and publish on Github Pages updated docs of 78 | your components. 79 | 80 | All you need to do is to change package name in `scripts/copyBuildFiles.js` on line 52. 81 | Version of the components lib will be derived from root `package.json` 82 | 83 | ## Known issues 84 | If you run `npm run deploy:docs` or any other scripts that call him too, on Windows `cmd.exe` you will 85 | get error like 86 | ``` 87 | bash: /dev/tty: No such device or address 88 | error: failed to execute prompt script (exit code 1) 89 | fatal: could not read Username for 'https://github.com': Invalid argument 90 | ``` 91 | To successfully run it on Windows please use git bash or cygwin or anything that simulates linux bash. 92 | -------------------------------------------------------------------------------- /config-overrides.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | 3 | const rewireEslint = require('./rewires/eslint') 4 | const rewireSc = require('react-app-rewire-styled-components') 5 | const rewirePolished = require('react-app-rewire-polished') 6 | const rewireResolve = require('./rewires/resolve') 7 | 8 | module.exports = function override(config, env) { 9 | rewireResolve(config) 10 | rewireEslint(config) 11 | rewireSc(config, env, { 12 | displayName: true, 13 | }), 14 | rewirePolished(config) 15 | return config 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CRA-components-development", 3 | "version": "0.1.12", 4 | "private": true, 5 | "homepage": "http://rip21.github.io/CRA-components-development/", 6 | "engines": { 7 | "node": ">=6.0.0" 8 | }, 9 | "author": { 10 | "name": "Andrii Los", 11 | "email": "puha212@gmail.com", 12 | "url": "https://twitter.com/RIP212" 13 | }, 14 | "keywords": [ 15 | "components", 16 | "react", 17 | "react-component", 18 | "toolkit" 19 | ], 20 | "scripts": { 21 | "demo:start": "react-app-rewired start", 22 | "demo:build": "react-app-rewired build", 23 | "styleguide": "styleguidist server", 24 | "styleguide:build": "styleguidist build", 25 | "test": "cross-env CI=true react-app-rewired test --env=jsdom", 26 | "test:watch": "react-app-rewired test --env=jsdom", 27 | "test:coverage": "npm test -- --coverage", 28 | "prettier": "eslint --fix ./src", 29 | "lint": "eslint ./src", 30 | "stylelint": "stylelint src/*/**.js", 31 | "prestylecheck": "run-s prettier", 32 | "stylecheck": "run-p lint", 33 | "clean": "rimraf lib", 34 | "build:css": "cpx \"./src/components/**/*.css\" ./lib", 35 | "build:es6": "cross-env NODE_ENV=production babel src/components --out-dir lib --ignore test.js", 36 | "prebuild": "run-p stylecheck test clean", 37 | "build": "run-p build:*", 38 | "postbuild": "node scripts/copyBuildFiles.js", 39 | "predeploy:docs": "npm run styleguide:build", 40 | "deploy:docs": "gh-pages -d styleguide", 41 | "prerelease": "npm run build", 42 | "release": "cd lib && npm publish && cd .. && npm run deploy:docs", 43 | "precommit": "lint-staged" 44 | }, 45 | "peerDependencies": { 46 | "react": "^16.1.1", 47 | "react-dom": "^16.1.1", 48 | "styled-components": "^2.2.3" 49 | }, 50 | "dependencies": { 51 | "normalize.css": "^7.0.0", 52 | "prop-types": "^15.6.0" 53 | }, 54 | "devDependencies": { 55 | "babel-cli": "^6.26.0", 56 | "cpx": "^1.5.0", 57 | "cross-env": "^5.1.1", 58 | "enzyme": "^3.2.0", 59 | "enzyme-adapter-react-16": "^1.1.0", 60 | "eslint-config-airbnb": "^16.1.0", 61 | "eslint-config-prettier": "^2.9.0", 62 | "eslint-plugin-prettier": "^2.3.1", 63 | "gh-pages": "^1.1.0", 64 | "husky": "^0.14.3", 65 | "jest-enzyme": "^4.0.1", 66 | "jest-styled-components": "^4.9.0", 67 | "lint-staged": "^6.0.0", 68 | "npm-run-all": "^4.1.2", 69 | "prettier": "^1.8.2", 70 | "react": "^16.1.1", 71 | "react-app-rewire-polished": "^1.0.3", 72 | "react-app-rewire-styled-components": "^3.0.0", 73 | "react-app-rewired": "^1.3.5", 74 | "react-dom": "^16.1.1", 75 | "react-scripts": "1.1.0", 76 | "react-styleguidist": "^6.0.33", 77 | "react-test-renderer": "^16.1.1", 78 | "rimraf": "^2.6.2", 79 | "styled-components": "^2.2.3", 80 | "stylelint": "^8.3.1", 81 | "stylelint-config-standard": "^18.0.0", 82 | "stylelint-processor-styled-components": "^1.1.1" 83 | }, 84 | "files": [ 85 | "lib" 86 | ], 87 | "babel": { 88 | "presets": [ 89 | [ 90 | "env", 91 | { 92 | "targets": { 93 | "node": "6.10" 94 | } 95 | } 96 | ], 97 | [ 98 | "react-app" 99 | ] 100 | ] 101 | }, 102 | "jest": { 103 | "collectCoverageFrom": [ 104 | "src/components/**/*.{js,jsx}", 105 | "!src/components/**/*/index.{js,jsx}", 106 | "!src/components/index.js" 107 | ] 108 | }, 109 | "stylelint": { 110 | "processors": [ 111 | "stylelint-processor-styled-components" 112 | ], 113 | "extends": "stylelint-config-standard", 114 | "syntax": "scss", 115 | "rules": { 116 | "block-opening-brace-space-after": "never-single-line", 117 | "block-closing-brace-space-before": "never-single-line" 118 | } 119 | }, 120 | "lint-staged": { 121 | "*.js": [ 122 | "eslint --fix", 123 | "git add" 124 | ] 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RIP21/CRA-components-development/96fc117acd33f710619e6f90d4bc738ac81cd43f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /rewires/eslint.js: -------------------------------------------------------------------------------- 1 | const rewireEslint = config => { 2 | const eslintLoader = config.module.rules[0] // Eslint loader is first in the list 3 | eslintLoader.use[0].options.useEslintrc = true 4 | } 5 | 6 | module.exports = rewireEslint 7 | -------------------------------------------------------------------------------- /rewires/resolve.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const root = path.join(process.cwd(), 'src') 3 | 4 | const rewireResolve = config => { 5 | config.resolve.modules.push(root) 6 | } 7 | 8 | module.exports = rewireResolve 9 | -------------------------------------------------------------------------------- /scripts/copyBuildFiles.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-var,import/no-extraneous-dependencies,no-console */ 2 | 3 | var path = require('path') 4 | var fse = require('fs-extra') 5 | var fs = require('fs') 6 | 7 | const files = ['LIBRARY.md', 'LICENSE'] 8 | 9 | Promise.all(files.map(file => copyFile(file))).then(() => 10 | createPackageFile().then(renameLibraryToReadme(files[0])), 11 | ) 12 | 13 | function copyFile(file) { 14 | const libPath = resolveBuildPath(file) 15 | return new Promise(resolve => { 16 | fse.copy(file, libPath, err => { 17 | if (err) throw err 18 | resolve() 19 | }) 20 | }).then(() => console.log(`Copied ${file} to ${libPath}`)) 21 | } 22 | 23 | function renameLibraryToReadme(file) { 24 | const libPath = resolveBuildPath(file) 25 | fs.rename( 26 | `${libPath}`, 27 | path.resolve(__dirname, '../lib/', 'README.md'), 28 | err => { 29 | if (err) throw err 30 | console.log(`Renamed ${file} to README.md`) 31 | }, 32 | ) 33 | } 34 | 35 | function resolveBuildPath(file) { 36 | return path.resolve(__dirname, '../lib/', path.basename(file)) 37 | } 38 | 39 | function createPackageFile() { 40 | return new Promise(resolve => { 41 | fse.readFile( 42 | path.resolve(__dirname, '../package.json'), 43 | 'utf8', 44 | (err, data) => { 45 | if (err) { 46 | throw err 47 | } 48 | 49 | resolve(data) 50 | }, 51 | ) 52 | }) 53 | .then(data => JSON.parse(data)) 54 | .then(packageData => { 55 | const { 56 | author, 57 | version, 58 | description, 59 | keywords, 60 | repository, 61 | license, 62 | bugs, 63 | homepage, 64 | peerDependencies, 65 | dependencies, 66 | } = packageData 67 | 68 | const minimalPackage = { 69 | name: 'generic-components', // Change it to your components name 70 | author, 71 | version, 72 | description, 73 | main: './index.js', 74 | keywords, 75 | repository, 76 | license, 77 | bugs, 78 | homepage, 79 | peerDependencies, 80 | dependencies, 81 | } 82 | 83 | return new Promise(resolve => { 84 | const libPath = path.resolve(__dirname, '../lib/package.json') 85 | const data = JSON.stringify(minimalPackage, null, 2) 86 | fse.writeFile(libPath, data, err => { 87 | if (err) throw err 88 | console.log(`Created package.json in ${libPath}`) 89 | resolve() 90 | }) 91 | }) 92 | }) 93 | } 94 | -------------------------------------------------------------------------------- /src/components/Button/Readme.md: -------------------------------------------------------------------------------- 1 | Basic button: 2 | 3 | ```js 4 | 5 | ``` 6 | 7 | Styled button: 8 | ```js 9 | const styled = require('styled-components').default; 10 | 11 | const Styled = styled(Button)` 12 | background-color: palevioletred; 13 | `; 14 | 15 | Styled 16 | ``` -------------------------------------------------------------------------------- /src/components/Button/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PT from 'prop-types' 3 | import styled from 'styled-components' 4 | 5 | const StyledButton = styled.button` 6 | padding: 0.5em 1em; 7 | background-color: #007878; 8 | color: white; 9 | font-family: Trebuchet MS, sans-serif; 10 | border-radius: 1em; 11 | font-size: 16px; 12 | ` 13 | 14 | /** 15 | * A regular button 16 | */ 17 | const Button = ({ children, ...rest }) => ( 18 | {children} 19 | ) 20 | 21 | Button.propTypes = { 22 | /** Button label */ 23 | children: PT.string.isRequired, 24 | } 25 | 26 | export default Button 27 | -------------------------------------------------------------------------------- /src/components/Button/index.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { shallow } from 'enzyme' 3 | import Button from './index' 4 | 5 | test('Button is rendering and showing content', () => { 6 | const text = 'Hello world!;' 7 | const component = shallow() 8 | expect(component.contains(text)).toBe(true) 9 | }) 10 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | export { default as Button } from './Button' 3 | -------------------------------------------------------------------------------- /src/demo/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PT from 'prop-types' 3 | import { Button } from 'components' 4 | import styled from 'styled-components' 5 | import 'normalize.css/normalize.css' 6 | 7 | const App = ({ className }) => ( 8 |
9 | 10 |
11 | ) 12 | 13 | App.propTypes = { 14 | className: PT.string, 15 | } 16 | 17 | App.defaultProps = { 18 | className: '', 19 | } 20 | 21 | export default styled(App)` 22 | padding: 1rem; 23 | height: 100vh; 24 | width: 100vw; 25 | display: flex; 26 | align-items: flex-start; 27 | justify-content: center; 28 | ` 29 | -------------------------------------------------------------------------------- /src/demo/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign,no-console */ 2 | 3 | // In production, we register a service worker to serve assets from local cache. 4 | 5 | // This lets the app load faster on subsequent visits in production, and gives 6 | // it offline capabilities. However, it also means that developers (and users) 7 | // will only see deployed updates on the "N+1" visit to a page, since previously 8 | // cached resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 11 | // This link also includes instructions on opting out of this behavior. 12 | 13 | export default function register() { 14 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 15 | window.addEventListener('load', () => { 16 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js` 17 | navigator.serviceWorker 18 | .register(swUrl) 19 | .then(registration => { 20 | registration.onupdatefound = () => { 21 | const installingWorker = registration.installing 22 | installingWorker.onstatechange = () => { 23 | if (installingWorker.state === 'installed') { 24 | if (navigator.serviceWorker.controller) { 25 | // At this point, the old content will have been purged and 26 | // the fresh content will have been added to the cache. 27 | // It's the perfect time to display a "New content is 28 | // available; please refresh." message in your web app. 29 | console.log('New content is available; please refresh.') 30 | } else { 31 | // At this point, everything has been precached. 32 | // It's the perfect time to display a 33 | // "Content is cached for offline use." message. 34 | console.log('Content is cached for offline use.') 35 | } 36 | } 37 | } 38 | } 39 | }) 40 | .catch(error => { 41 | console.error('Error during service worker registration:', error) 42 | }) 43 | }) 44 | } 45 | } 46 | 47 | export function unregister() { 48 | if ('serviceWorker' in navigator) { 49 | navigator.serviceWorker.ready.then(registration => { 50 | registration.unregister() 51 | }) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './demo' 4 | import registerServiceWorker from './demo/registerServiceWorker' 5 | 6 | ReactDOM.render(, document.getElementById('root')) 7 | registerServiceWorker() 8 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies,no-console */ 2 | 3 | import 'jest-enzyme' 4 | import 'jest-styled-components' 5 | import enzyme from 'enzyme' 6 | 7 | import Adapter from 'enzyme-adapter-react-16' 8 | 9 | enzyme.configure({ adapter: new Adapter() }) 10 | console.error = () => {} // To suppress browser errors that React generates for tests 11 | -------------------------------------------------------------------------------- /styleguide.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-dynamic-require,no-shadow,import/no-extraneous-dependencies */ 2 | 3 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 4 | 5 | const paths = require('react-app-rewired/scripts/utils/paths') 6 | 7 | require(`${paths.scriptVersion}/config/env`) 8 | 9 | const webpackConfig = `${paths.scriptVersion}/config/webpack.config.dev` 10 | const config = require(webpackConfig) 11 | const override = require(paths.configOverrides) 12 | const overrideFn = 13 | typeof override === 'function' 14 | ? override 15 | : override.webpack || ((config, env) => config) 16 | 17 | module.exports = { 18 | webpackConfig: overrideFn(config, process.env.NODE_ENV), 19 | require: ['normalize.css/normalize.css'], 20 | compilerConfig: { 21 | transforms: { dangerousTaggedTemplateString: true }, // This to support styled-components in example Markdowns 22 | }, 23 | } 24 | --------------------------------------------------------------------------------