├── .gitignore ├── .npmignore ├── README.md ├── audit-resolve.json ├── config ├── env.js ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── modules.js ├── paths.js ├── pnpTs.js ├── webpack.config.js └── webpackDevServer.config.js ├── package-lock.json ├── package.json ├── public ├── demo │ ├── accuracy.png │ ├── completed.png │ ├── consistent.png │ ├── correct.png │ ├── rules.png │ └── understable.png ├── favicon.ico ├── index.html ├── logo.png ├── logo192.png ├── logo512.png ├── manifest.json ├── person.png ├── robots.txt └── rtg-logo-white.png ├── scripts ├── build.js ├── demo.js ├── logo512.png ├── start.js └── test.js ├── src ├── demo │ ├── App.js │ ├── App.test.js │ ├── Pages │ │ ├── Horizonal │ │ │ ├── Horizontal.js │ │ │ └── Sections │ │ │ │ ├── Intro.js │ │ │ │ ├── Roentgen.js │ │ │ │ ├── Sources.js │ │ │ │ └── index.js │ │ ├── Vertical │ │ │ ├── Sections │ │ │ │ ├── Documentation.js │ │ │ │ ├── Footer.js │ │ │ │ ├── Header.js │ │ │ │ ├── Intro.js │ │ │ │ ├── List.js │ │ │ │ ├── Newsletter.js │ │ │ │ ├── Slider.js │ │ │ │ └── index.js │ │ │ └── Vertical.js │ │ └── hooks │ │ │ ├── useFullPageSlider.js │ │ │ └── useSlider.js │ ├── Tour │ │ ├── GuideTourHorizontal.js │ │ └── GuideTourVertical.js │ ├── index.css │ ├── index.js │ ├── serviceWorker.js │ └── style │ │ ├── colors.scss │ │ ├── components │ │ ├── buttons.scss │ │ ├── form.scss │ │ ├── fp-slider.scss │ │ ├── headings.scss │ │ ├── link.scss │ │ ├── mixins.scss │ │ ├── scrolls.scss │ │ └── slider.scss │ │ ├── general.scss │ │ ├── grid.scss │ │ ├── horizontal │ │ ├── horizontal.scss │ │ ├── intro.scss │ │ ├── roentgen.scss │ │ ├── rtg.scss │ │ └── sources.scss │ │ ├── main.scss │ │ └── vertical │ │ ├── documentation.scss │ │ ├── footer.scss │ │ ├── header.scss │ │ ├── intro.scss │ │ ├── list.scss │ │ ├── newsletter.scss │ │ ├── rtg.scss │ │ ├── slider.scss │ │ └── vertical.scss └── lib │ ├── components │ ├── Backdrop │ │ ├── Backdrop.js │ │ └── backdrop.scss │ ├── Badge │ │ ├── Badge.js │ │ └── badge.scss │ ├── CloseButton │ │ ├── CloseButton.js │ │ └── close-button.scss │ ├── Context │ │ └── Context.js │ ├── Control │ │ ├── Button.js │ │ ├── Control.js │ │ ├── Selector │ │ │ ├── Button.js │ │ │ └── Selector.js │ │ └── control.scss │ ├── Modal │ │ ├── Modal.js │ │ └── modal.scss │ ├── Pin │ │ ├── Pin.js │ │ └── pin.scss │ ├── Step │ │ └── Step.js │ ├── Tour │ │ ├── Tour.js │ │ └── tour.scss │ ├── hooks │ │ └── useTour.js │ └── utils │ │ ├── firstOf.js │ │ ├── getOverflowedParent.js │ │ ├── isMounted.js │ │ ├── offsetTop.js │ │ ├── placementToObj.js │ │ ├── scrollTo.js │ │ ├── throttle.js │ │ ├── toRange.js │ │ └── useStates.js │ └── index.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | build 14 | 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # misc 8 | .DS_Store 9 | .env.local 10 | .env.development.local 11 | .env.test.local 12 | .env.production.local 13 | 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # Development folders and files 19 | public 20 | src 21 | scripts 22 | config 23 | demo 24 | CHANGELOG.md 25 | README.md 26 | UPGRADE.md 27 | .storybook -------------------------------------------------------------------------------- /audit-resolve.json: -------------------------------------------------------------------------------- 1 | { 2 | "decisions": { 3 | "1426|terser-webpack-plugin>serialize-javascript": { 4 | "decision": "fix", 5 | "madeAt": 1622840928280 6 | }, 7 | "1548|terser-webpack-plugin>serialize-javascript": { 8 | "decision": "fix", 9 | "madeAt": 1622840928280 10 | }, 11 | "1573|resolve-url-loader>adjust-sourcemap-loader>object-path": { 12 | "decision": "fix", 13 | "madeAt": 1622840975414 14 | }, 15 | "1693|css-loader>icss-utils>postcss": { 16 | "decision": "fix", 17 | "madeAt": 1622841033237 18 | }, 19 | "1693|css-loader>postcss": { 20 | "decision": "fix", 21 | "madeAt": 1622841033237 22 | }, 23 | "1693|css-loader>postcss-modules-extract-imports>postcss": { 24 | "decision": "fix", 25 | "madeAt": 1622841033237 26 | }, 27 | "1693|css-loader>postcss-modules-local-by-default>postcss": { 28 | "decision": "fix", 29 | "madeAt": 1622841033237 30 | }, 31 | "1693|css-loader>postcss-modules-scope>postcss": { 32 | "decision": "fix", 33 | "madeAt": 1622841033237 34 | }, 35 | "1693|css-loader>postcss-modules-values>postcss": { 36 | "decision": "fix", 37 | "madeAt": 1622841033237 38 | }, 39 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>css-declaration-sorter>postcss": { 40 | "decision": "fix", 41 | "madeAt": 1622841092367 42 | }, 43 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>cssnano-util-raw-cache>postcss": { 44 | "decision": "fix", 45 | "madeAt": 1622841092368 46 | }, 47 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss": { 48 | "decision": "fix", 49 | "madeAt": 1622841092368 50 | }, 51 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-colormin>postcss": { 52 | "decision": "fix", 53 | "madeAt": 1622841092368 54 | }, 55 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-convert-values>postcss": { 56 | "decision": "fix", 57 | "madeAt": 1622841092368 58 | }, 59 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-discard-comments>postcss": { 60 | "decision": "fix", 61 | "madeAt": 1622841092368 62 | }, 63 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-discard-duplicates>postcss": { 64 | "decision": "fix", 65 | "madeAt": 1622841092368 66 | }, 67 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-discard-empty>postcss": { 68 | "decision": "fix", 69 | "madeAt": 1622841092368 70 | }, 71 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-discard-overridden>postcss": { 72 | "decision": "fix", 73 | "madeAt": 1622841092368 74 | }, 75 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-merge-longhand>postcss": { 76 | "decision": "fix", 77 | "madeAt": 1622841092368 78 | }, 79 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-merge-longhand>stylehacks>postcss": { 80 | "decision": "fix", 81 | "madeAt": 1622841092368 82 | }, 83 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-merge-rules>postcss": { 84 | "decision": "fix", 85 | "madeAt": 1622841092368 86 | }, 87 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-minify-font-values>postcss": { 88 | "decision": "fix", 89 | "madeAt": 1622841092368 90 | }, 91 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-minify-gradients>postcss": { 92 | "decision": "fix", 93 | "madeAt": 1622841092368 94 | }, 95 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-minify-params>postcss": { 96 | "decision": "fix", 97 | "madeAt": 1622841092368 98 | }, 99 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-minify-selectors>postcss": { 100 | "decision": "fix", 101 | "madeAt": 1622841092368 102 | }, 103 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-charset>postcss": { 104 | "decision": "fix", 105 | "madeAt": 1622841092368 106 | }, 107 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-display-values>postcss": { 108 | "decision": "fix", 109 | "madeAt": 1622841092368 110 | }, 111 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-positions>postcss": { 112 | "decision": "fix", 113 | "madeAt": 1622841092368 114 | }, 115 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-repeat-style>postcss": { 116 | "decision": "fix", 117 | "madeAt": 1622841092368 118 | }, 119 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-string>postcss": { 120 | "decision": "fix", 121 | "madeAt": 1622841092368 122 | }, 123 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-timing-functions>postcss": { 124 | "decision": "fix", 125 | "madeAt": 1622841092368 126 | }, 127 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-unicode>postcss": { 128 | "decision": "fix", 129 | "madeAt": 1622841092368 130 | }, 131 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-url>postcss": { 132 | "decision": "fix", 133 | "madeAt": 1622841092368 134 | }, 135 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-normalize-whitespace>postcss": { 136 | "decision": "fix", 137 | "madeAt": 1622841092368 138 | }, 139 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-ordered-values>postcss": { 140 | "decision": "fix", 141 | "madeAt": 1622841092368 142 | }, 143 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-reduce-initial>postcss": { 144 | "decision": "fix", 145 | "madeAt": 1622841092368 146 | }, 147 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-reduce-transforms>postcss": { 148 | "decision": "fix", 149 | "madeAt": 1622841092368 150 | }, 151 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-svgo>postcss": { 152 | "decision": "fix", 153 | "madeAt": 1622841092368 154 | }, 155 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-unique-selectors>postcss": { 156 | "decision": "fix", 157 | "madeAt": 1622841092368 158 | }, 159 | "1693|optimize-css-assets-webpack-plugin>cssnano>postcss": { 160 | "decision": "fix", 161 | "madeAt": 1622841092368 162 | }, 163 | "1693|optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-calc>postcss": { 164 | "decision": "fix", 165 | "madeAt": 1622841092368 166 | }, 167 | "1693|postcss-flexbugs-fixes>postcss": { 168 | "decision": "fix", 169 | "madeAt": 1622841152030 170 | }, 171 | "1693|postcss-loader>postcss": { 172 | "decision": "fix", 173 | "madeAt": 1622841197857 174 | }, 175 | "1693|postcss-normalize>postcss": { 176 | "decision": "fix", 177 | "madeAt": 1622841237554 178 | }, 179 | "1693|postcss-normalize>postcss-browser-comments>postcss": { 180 | "decision": "fix", 181 | "madeAt": 1622841237554 182 | }, 183 | "1693|postcss-safe-parser>postcss": { 184 | "decision": "fix", 185 | "madeAt": 1622841287168 186 | }, 187 | "1748|jest>jest-cli>@jest/core>@jest/reporters>jest-runtime>jest-config>jest-environment-jsdom>jsdom>ws": { 188 | "decision": "fix", 189 | "madeAt": 1622841661773 190 | }, 191 | "1748|jest>jest-cli>@jest/core>jest-runner>jest-jasmine2>jest-runtime>jest-config>jest-environment-jsdom>jsdom>ws": { 192 | "decision": "fix", 193 | "madeAt": 1622841661773 194 | }, 195 | "1748|jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>jest-environment-jsdom>jsdom>ws": { 196 | "decision": "fix", 197 | "madeAt": 1622841661773 198 | }, 199 | "1748|jest>jest-cli>@jest/core>jest-runtime>jest-config>jest-environment-jsdom>jsdom>ws": { 200 | "decision": "fix", 201 | "madeAt": 1622841661773 202 | }, 203 | "1748|jest>jest-cli>@jest/core>jest-runner>jest-config>jest-environment-jsdom>jsdom>ws": { 204 | "decision": "fix", 205 | "madeAt": 1622841661773 206 | }, 207 | "1748|jest>jest-cli>@jest/core>jest-config>jest-environment-jsdom>jsdom>ws": { 208 | "decision": "fix", 209 | "madeAt": 1622841661773 210 | }, 211 | "1748|jest>jest-cli>jest-config>jest-environment-jsdom>jsdom>ws": { 212 | "decision": "fix", 213 | "madeAt": 1622841661773 214 | }, 215 | "1179|eslint-loader>loader-fs-cache>find-cache-dir>mkdirp>minimist": { 216 | "decision": "fix", 217 | "madeAt": 1622842211203 218 | } 219 | }, 220 | "rules": {}, 221 | "version": 1 222 | } -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | 7 | // Make sure that including paths.js after env.js will read .env variables. 8 | delete require.cache[require.resolve('./paths')]; 9 | 10 | const NODE_ENV = process.env.NODE_ENV; 11 | if (!NODE_ENV) { 12 | throw new Error( 13 | 'The NODE_ENV environment variable is required but was not specified.' 14 | ); 15 | } 16 | 17 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 18 | const dotenvFiles = [ 19 | `${paths.dotenv}.${NODE_ENV}.local`, 20 | `${paths.dotenv}.${NODE_ENV}`, 21 | // Don't include `.env.local` for `test` environment 22 | // since normally you expect tests to produce the same 23 | // results for everyone 24 | NODE_ENV !== 'test' && `${paths.dotenv}.local`, 25 | paths.dotenv, 26 | ].filter(Boolean); 27 | 28 | // Load environment variables from .env* files. Suppress warnings using silent 29 | // if this file is missing. dotenv will never modify any environment variables 30 | // that have already been set. Variable expansion is supported in .env files. 31 | // https://github.com/motdotla/dotenv 32 | // https://github.com/motdotla/dotenv-expand 33 | dotenvFiles.forEach(dotenvFile => { 34 | if (fs.existsSync(dotenvFile)) { 35 | require('dotenv-expand')( 36 | require('dotenv').config({ 37 | path: dotenvFile, 38 | }) 39 | ); 40 | } 41 | }); 42 | 43 | // We support resolving modules according to `NODE_PATH`. 44 | // This lets you use absolute paths in imports inside large monorepos: 45 | // https://github.com/facebook/create-react-app/issues/253. 46 | // It works similar to `NODE_PATH` in Node itself: 47 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 48 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 49 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. 50 | // https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 51 | // We also resolve them to make sure all tools using them work consistently. 52 | const appDirectory = fs.realpathSync(process.cwd()); 53 | process.env.NODE_PATH = (process.env.NODE_PATH || '') 54 | .split(path.delimiter) 55 | .filter(folder => folder && !path.isAbsolute(folder)) 56 | .map(folder => path.resolve(appDirectory, folder)) 57 | .join(path.delimiter); 58 | 59 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 60 | // injected into the application via DefinePlugin in Webpack configuration. 61 | const REACT_APP = /^REACT_APP_/i; 62 | 63 | function getClientEnvironment(publicUrl) { 64 | const raw = Object.keys(process.env) 65 | .filter(key => REACT_APP.test(key)) 66 | .reduce( 67 | (env, key) => { 68 | env[key] = process.env[key]; 69 | return env; 70 | }, 71 | { 72 | // Useful for determining whether we’re running in production mode. 73 | // Most importantly, it switches React into the correct mode. 74 | NODE_ENV: process.env.NODE_ENV || 'development', 75 | // Useful for resolving the correct path to static assets in `public`. 76 | // For example, . 77 | // This should only be used as an escape hatch. Normally you would put 78 | // images into the `src` and `import` them in code to get their paths. 79 | PUBLIC_URL: publicUrl, 80 | } 81 | ); 82 | // Stringify all values so we can feed into Webpack DefinePlugin 83 | const stringified = { 84 | 'process.env': Object.keys(raw).reduce((env, key) => { 85 | env[key] = JSON.stringify(raw[key]); 86 | return env; 87 | }, {}), 88 | }; 89 | 90 | return { raw, stringified }; 91 | } 92 | 93 | module.exports = getClientEnvironment; 94 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /config/modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | const resolve = require('resolve'); 8 | 9 | /** 10 | * Get additional module paths based on the baseUrl of a compilerOptions object. 11 | * 12 | * @param {Object} options 13 | */ 14 | function getAdditionalModulePaths(options = {}) { 15 | const baseUrl = options.baseUrl; 16 | 17 | // We need to explicitly check for null and undefined (and not a falsy value) because 18 | // TypeScript treats an empty string as `.`. 19 | if (baseUrl == null) { 20 | // If there's no baseUrl set we respect NODE_PATH 21 | // Note that NODE_PATH is deprecated and will be removed 22 | // in the next major release of create-react-app. 23 | 24 | const nodePath = process.env.NODE_PATH || ''; 25 | return nodePath.split(path.delimiter).filter(Boolean); 26 | } 27 | 28 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 29 | 30 | // We don't need to do anything if `baseUrl` is set to `node_modules`. This is 31 | // the default behavior. 32 | if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { 33 | return null; 34 | } 35 | 36 | // Allow the user set the `baseUrl` to `appSrc`. 37 | if (path.relative(paths.appSrc, baseUrlResolved) === '') { 38 | return [paths.appSrc]; 39 | } 40 | 41 | // If the path is equal to the root directory we ignore it here. 42 | // We don't want to allow importing from the root directly as source files are 43 | // not transpiled outside of `src`. We do allow importing them with the 44 | // absolute path (e.g. `src/Components/Button.js`) but we set that up with 45 | // an alias. 46 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 47 | return null; 48 | } 49 | 50 | // Otherwise, throw an error. 51 | throw new Error( 52 | chalk.red.bold( 53 | "Your project's `baseUrl` can only be set to `src` or `node_modules`." + 54 | ' Create React App does not support other values at this time.' 55 | ) 56 | ); 57 | } 58 | 59 | /** 60 | * Get webpack aliases based on the baseUrl of a compilerOptions object. 61 | * 62 | * @param {*} options 63 | */ 64 | function getWebpackAliases(options = {}) { 65 | const baseUrl = options.baseUrl; 66 | 67 | if (!baseUrl) { 68 | return {}; 69 | } 70 | 71 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 72 | 73 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 74 | return { 75 | src: paths.appSrc, 76 | }; 77 | } 78 | } 79 | 80 | /** 81 | * Get jest aliases based on the baseUrl of a compilerOptions object. 82 | * 83 | * @param {*} options 84 | */ 85 | function getJestAliases(options = {}) { 86 | const baseUrl = options.baseUrl; 87 | 88 | if (!baseUrl) { 89 | return {}; 90 | } 91 | 92 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 93 | 94 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 95 | return { 96 | 'src/(.*)$': '/src/$1', 97 | }; 98 | } 99 | } 100 | 101 | function getModules() { 102 | // Check if TypeScript is setup 103 | const hasTsConfig = fs.existsSync(paths.appTsConfig); 104 | const hasJsConfig = fs.existsSync(paths.appJsConfig); 105 | 106 | if (hasTsConfig && hasJsConfig) { 107 | throw new Error( 108 | 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' 109 | ); 110 | } 111 | 112 | let config; 113 | 114 | // If there's a tsconfig.json we assume it's a 115 | // TypeScript project and set up the config 116 | // based on tsconfig.json 117 | if (hasTsConfig) { 118 | const ts = require(resolve.sync('typescript', { 119 | basedir: paths.appNodeModules, 120 | })); 121 | config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; 122 | // Otherwise we'll check if there is jsconfig.json 123 | // for non TS projects. 124 | } else if (hasJsConfig) { 125 | config = require(paths.appJsConfig); 126 | } 127 | 128 | config = config || {}; 129 | const options = config.compilerOptions || {}; 130 | 131 | const additionalModulePaths = getAdditionalModulePaths(options); 132 | 133 | return { 134 | additionalModulePaths: additionalModulePaths, 135 | webpackAliases: getWebpackAliases(options), 136 | jestAliases: getJestAliases(options), 137 | hasTsConfig, 138 | }; 139 | } 140 | 141 | module.exports = getModules(); 142 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebook/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(inputPath, needsSlash) { 15 | const hasSlash = inputPath.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return inputPath.substr(0, inputPath.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${inputPath}/`; 20 | } else { 21 | return inputPath; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => 26 | envPublicUrl || require(appPackageJson).homepage; 27 | 28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 29 | // "public path" at which the app is served. 30 | // Webpack needs to know it to put the right