├── .babelrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── Procfile ├── README.md ├── dist └── react-delayed.js ├── example ├── css │ ├── default.scss │ └── modal.scss ├── images │ └── nyan.gif ├── index.html ├── js │ ├── default.js │ └── modal.js └── server │ └── default.js ├── package-lock.json ├── package.json ├── src └── react-delayed.js ├── tests ├── helpers │ └── browser-env.js └── react-delayed.test.js ├── webpack.config.example.js └── webpack.config.release.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # os 2 | .DS_Store 3 | 4 | # ide 5 | .idea 6 | 7 | # npm 8 | node_modules 9 | npm-debug.log 10 | yarn.lock 11 | 12 | # example 13 | example/js/build.js 14 | example/css/default.css 15 | 16 | # coverage 17 | coverage 18 | .nyc_output 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: stable 3 | 4 | after_success: 5 | - ./node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls 6 | 7 | script: 8 | - npm install 9 | - npm test 10 | - npm run build 11 | 12 | deploy: 13 | provider: heroku 14 | api_key: 15 | secure: RtWvyS5xmLYIEjG7fmYbrnvx2zScs8ryDMkHyar52CwlSloPfH+TlF9thuIWgNbUQTXF5xWi/moKY2Dm4i2ojXXI15pgOviuQGVUm4ZoAaKClZIrA9kjW/q+srU8hGKlwVAywtV0TMIZN4F8JZZ5fiQLjamJnDHrbxZ2/dNs1kkV7D6hJhmLh6RMe+gCSlfnttZwV1/Ed0PJbIV5n0PDYBFCwqqCfLLWG9M4A2MN9l9gtsHenbZBF7NTw95frSHv8TjIZrMejsi4NEC8vQ0WyvbIzW/JIkteitkhB4H2BRw70pByWF0gI04W4sNxBIAQbMTUARViZDQt2qHsiv6zCy0zztlf6oNbbgciZea8OFopZCvnodGvkFo5klIG3yAsJifMY75/b7SJYIieLWba8BW5aK+UyEjec8BMN5m4KjQFyjVA0i94hjiEvHguKcsPEzZStjGWpX9Sg+oo3327Sdf4XOzjm/1aCOVX/wG37mePIcRoDrils2H+1kFRxHbqheoGUfj+EzhSEVNunKML7x+eLJVY8tp+2lIO9xrRDNkRW4UeRxYnYDhVFcX4w00D6nQI6u3P1YfP+pdG88p6YpVqu5Z3O1lRM/8CtwzshvZKtB8odUNCWIMUAcP4DMbVNdYF02PzD1ZBlFhTVb8pzdYpnXtp2segTvXssobnaZQ= 16 | app: react-delayed 17 | on: 18 | repo: Wildhoney/ReactDelayed 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Adam Timberlake 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. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: npm run start 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Delayed 2 | 3 | > Small component for delaying the mounting and unmounting of a child component for CSS animation purposes. 4 | 5 | ![Travis](http://img.shields.io/travis/Wildhoney/ReactDelayed.svg?style=flat-square) 6 |   7 | ![Coveralls](https://img.shields.io/coveralls/Wildhoney/ReactDelayed.svg?style=flat-square) 8 |   9 | ![npm](http://img.shields.io/npm/v/react-delayed.svg?style=flat-square) 10 |   11 | ![License MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square) 12 | 13 | * **npm**: `npm i react-delayed --save` 14 | * **Heroku**: [http://react-delayed.herokuapp.com/](http://react-delayed.herokuapp.com/) 15 | 16 | --- 17 | 18 | ## Getting Started 19 | 20 | Use the optional `mountAfter` and `unmountAfter` props for delaying the mounting and unmounting of nested components. 21 | 22 | ```javascript 23 | 24 | Nyan 25 | 26 | ``` 27 | 28 | When `mounted` is `false` a dummy node will be rendered, which defaults to `span` and can be changed with the `nodeName` prop. 29 | 30 | You're also able to pass a *thunk* as the `children` for truly deferred components. 31 | 32 | ```javascript 33 | 34 | {() => Nyan} 35 | 36 | ``` 37 | -------------------------------------------------------------------------------- /dist/react-delayed.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | /******/ 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | /******/ 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) 11 | /******/ return installedModules[moduleId].exports; 12 | /******/ 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ i: moduleId, 16 | /******/ l: false, 17 | /******/ exports: {} 18 | /******/ }; 19 | /******/ 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | /******/ 23 | /******/ // Flag the module as loaded 24 | /******/ module.l = true; 25 | /******/ 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | /******/ 30 | /******/ 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | /******/ 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | /******/ 37 | /******/ // identity function for calling harmony imports with the correct context 38 | /******/ __webpack_require__.i = function(value) { return value; }; 39 | /******/ 40 | /******/ // define getter function for harmony exports 41 | /******/ __webpack_require__.d = function(exports, name, getter) { 42 | /******/ if(!__webpack_require__.o(exports, name)) { 43 | /******/ Object.defineProperty(exports, name, { 44 | /******/ configurable: false, 45 | /******/ enumerable: true, 46 | /******/ get: getter 47 | /******/ }); 48 | /******/ } 49 | /******/ }; 50 | /******/ 51 | /******/ // getDefaultExport function for compatibility with non-harmony modules 52 | /******/ __webpack_require__.n = function(module) { 53 | /******/ var getter = module && module.__esModule ? 54 | /******/ function getDefault() { return module['default']; } : 55 | /******/ function getModuleExports() { return module; }; 56 | /******/ __webpack_require__.d(getter, 'a', getter); 57 | /******/ return getter; 58 | /******/ }; 59 | /******/ 60 | /******/ // Object.prototype.hasOwnProperty.call 61 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 62 | /******/ 63 | /******/ // __webpack_public_path__ 64 | /******/ __webpack_require__.p = ""; 65 | /******/ 66 | /******/ // Load entry module and return exports 67 | /******/ return __webpack_require__(__webpack_require__.s = 10); 68 | /******/ }) 69 | /************************************************************************/ 70 | /******/ ([ 71 | /* 0 */ 72 | /***/ (function(module, exports, __webpack_require__) { 73 | 74 | "use strict"; 75 | 76 | 77 | // shim for using process in browser 78 | var process = module.exports = {}; 79 | 80 | // cached from whatever global is present so that test runners that stub it 81 | // don't break things. But we need to wrap it in a try catch in case it is 82 | // wrapped in strict mode code which doesn't define any globals. It's inside a 83 | // function because try/catches deoptimize in certain engines. 84 | 85 | var cachedSetTimeout; 86 | var cachedClearTimeout; 87 | 88 | function defaultSetTimout() { 89 | throw new Error('setTimeout has not been defined'); 90 | } 91 | function defaultClearTimeout() { 92 | throw new Error('clearTimeout has not been defined'); 93 | } 94 | (function () { 95 | try { 96 | if (typeof setTimeout === 'function') { 97 | cachedSetTimeout = setTimeout; 98 | } else { 99 | cachedSetTimeout = defaultSetTimout; 100 | } 101 | } catch (e) { 102 | cachedSetTimeout = defaultSetTimout; 103 | } 104 | try { 105 | if (typeof clearTimeout === 'function') { 106 | cachedClearTimeout = clearTimeout; 107 | } else { 108 | cachedClearTimeout = defaultClearTimeout; 109 | } 110 | } catch (e) { 111 | cachedClearTimeout = defaultClearTimeout; 112 | } 113 | })(); 114 | function runTimeout(fun) { 115 | if (cachedSetTimeout === setTimeout) { 116 | //normal enviroments in sane situations 117 | return setTimeout(fun, 0); 118 | } 119 | // if setTimeout wasn't available but was latter defined 120 | if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { 121 | cachedSetTimeout = setTimeout; 122 | return setTimeout(fun, 0); 123 | } 124 | try { 125 | // when when somebody has screwed with setTimeout but no I.E. maddness 126 | return cachedSetTimeout(fun, 0); 127 | } catch (e) { 128 | try { 129 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 130 | return cachedSetTimeout.call(null, fun, 0); 131 | } catch (e) { 132 | // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error 133 | return cachedSetTimeout.call(this, fun, 0); 134 | } 135 | } 136 | } 137 | function runClearTimeout(marker) { 138 | if (cachedClearTimeout === clearTimeout) { 139 | //normal enviroments in sane situations 140 | return clearTimeout(marker); 141 | } 142 | // if clearTimeout wasn't available but was latter defined 143 | if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { 144 | cachedClearTimeout = clearTimeout; 145 | return clearTimeout(marker); 146 | } 147 | try { 148 | // when when somebody has screwed with setTimeout but no I.E. maddness 149 | return cachedClearTimeout(marker); 150 | } catch (e) { 151 | try { 152 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 153 | return cachedClearTimeout.call(null, marker); 154 | } catch (e) { 155 | // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. 156 | // Some versions of I.E. have different rules for clearTimeout vs setTimeout 157 | return cachedClearTimeout.call(this, marker); 158 | } 159 | } 160 | } 161 | var queue = []; 162 | var draining = false; 163 | var currentQueue; 164 | var queueIndex = -1; 165 | 166 | function cleanUpNextTick() { 167 | if (!draining || !currentQueue) { 168 | return; 169 | } 170 | draining = false; 171 | if (currentQueue.length) { 172 | queue = currentQueue.concat(queue); 173 | } else { 174 | queueIndex = -1; 175 | } 176 | if (queue.length) { 177 | drainQueue(); 178 | } 179 | } 180 | 181 | function drainQueue() { 182 | if (draining) { 183 | return; 184 | } 185 | var timeout = runTimeout(cleanUpNextTick); 186 | draining = true; 187 | 188 | var len = queue.length; 189 | while (len) { 190 | currentQueue = queue; 191 | queue = []; 192 | while (++queueIndex < len) { 193 | if (currentQueue) { 194 | currentQueue[queueIndex].run(); 195 | } 196 | } 197 | queueIndex = -1; 198 | len = queue.length; 199 | } 200 | currentQueue = null; 201 | draining = false; 202 | runClearTimeout(timeout); 203 | } 204 | 205 | process.nextTick = function (fun) { 206 | var args = new Array(arguments.length - 1); 207 | if (arguments.length > 1) { 208 | for (var i = 1; i < arguments.length; i++) { 209 | args[i - 1] = arguments[i]; 210 | } 211 | } 212 | queue.push(new Item(fun, args)); 213 | if (queue.length === 1 && !draining) { 214 | runTimeout(drainQueue); 215 | } 216 | }; 217 | 218 | // v8 likes predictible objects 219 | function Item(fun, array) { 220 | this.fun = fun; 221 | this.array = array; 222 | } 223 | Item.prototype.run = function () { 224 | this.fun.apply(null, this.array); 225 | }; 226 | process.title = 'browser'; 227 | process.browser = true; 228 | process.env = {}; 229 | process.argv = []; 230 | process.version = ''; // empty string to avoid regexp issues 231 | process.versions = {}; 232 | 233 | function noop() {} 234 | 235 | process.on = noop; 236 | process.addListener = noop; 237 | process.once = noop; 238 | process.off = noop; 239 | process.removeListener = noop; 240 | process.removeAllListeners = noop; 241 | process.emit = noop; 242 | process.prependListener = noop; 243 | process.prependOnceListener = noop; 244 | 245 | process.listeners = function (name) { 246 | return []; 247 | }; 248 | 249 | process.binding = function (name) { 250 | throw new Error('process.binding is not supported'); 251 | }; 252 | 253 | process.cwd = function () { 254 | return '/'; 255 | }; 256 | process.chdir = function (dir) { 257 | throw new Error('process.chdir is not supported'); 258 | }; 259 | process.umask = function () { 260 | return 0; 261 | }; 262 | 263 | /***/ }), 264 | /* 1 */ 265 | /***/ (function(module, exports, __webpack_require__) { 266 | 267 | "use strict"; 268 | 269 | 270 | /** 271 | * Copyright (c) 2013-present, Facebook, Inc. 272 | * 273 | * This source code is licensed under the MIT license found in the 274 | * LICENSE file in the root directory of this source tree. 275 | * 276 | * 277 | */ 278 | 279 | function makeEmptyFunction(arg) { 280 | return function () { 281 | return arg; 282 | }; 283 | } 284 | 285 | /** 286 | * This function accepts and discards inputs; it has no side effects. This is 287 | * primarily useful idiomatically for overridable function endpoints which 288 | * always need to be callable, since JS lacks a null-call idiom ala Cocoa. 289 | */ 290 | var emptyFunction = function emptyFunction() {}; 291 | 292 | emptyFunction.thatReturns = makeEmptyFunction; 293 | emptyFunction.thatReturnsFalse = makeEmptyFunction(false); 294 | emptyFunction.thatReturnsTrue = makeEmptyFunction(true); 295 | emptyFunction.thatReturnsNull = makeEmptyFunction(null); 296 | emptyFunction.thatReturnsThis = function () { 297 | return this; 298 | }; 299 | emptyFunction.thatReturnsArgument = function (arg) { 300 | return arg; 301 | }; 302 | 303 | module.exports = emptyFunction; 304 | 305 | /***/ }), 306 | /* 2 */ 307 | /***/ (function(module, exports, __webpack_require__) { 308 | 309 | "use strict"; 310 | /* WEBPACK VAR INJECTION */(function(process) {/** 311 | * Copyright (c) 2013-present, Facebook, Inc. 312 | * 313 | * This source code is licensed under the MIT license found in the 314 | * LICENSE file in the root directory of this source tree. 315 | * 316 | */ 317 | 318 | 319 | 320 | /** 321 | * Use invariant() to assert state which your program assumes to be true. 322 | * 323 | * Provide sprintf-style format (only %s is supported) and arguments 324 | * to provide information about what broke and what you were 325 | * expecting. 326 | * 327 | * The invariant message will be stripped in production, but the invariant 328 | * will remain to ensure logic does not differ in production. 329 | */ 330 | 331 | var validateFormat = function validateFormat(format) {}; 332 | 333 | if (process.env.NODE_ENV !== 'production') { 334 | validateFormat = function validateFormat(format) { 335 | if (format === undefined) { 336 | throw new Error('invariant requires an error message argument'); 337 | } 338 | }; 339 | } 340 | 341 | function invariant(condition, format, a, b, c, d, e, f) { 342 | validateFormat(format); 343 | 344 | if (!condition) { 345 | var error; 346 | if (format === undefined) { 347 | error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); 348 | } else { 349 | var args = [a, b, c, d, e, f]; 350 | var argIndex = 0; 351 | error = new Error(format.replace(/%s/g, function () { 352 | return args[argIndex++]; 353 | })); 354 | error.name = 'Invariant Violation'; 355 | } 356 | 357 | error.framesToPop = 1; // we don't care about invariant's own frame 358 | throw error; 359 | } 360 | } 361 | 362 | module.exports = invariant; 363 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) 364 | 365 | /***/ }), 366 | /* 3 */ 367 | /***/ (function(module, exports, __webpack_require__) { 368 | 369 | "use strict"; 370 | /** 371 | * Copyright 2013-present, Facebook, Inc. 372 | * All rights reserved. 373 | * 374 | * This source code is licensed under the BSD-style license found in the 375 | * LICENSE file in the root directory of this source tree. An additional grant 376 | * of patent rights can be found in the PATENTS file in the same directory. 377 | */ 378 | 379 | 380 | 381 | var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; 382 | 383 | module.exports = ReactPropTypesSecret; 384 | 385 | /***/ }), 386 | /* 4 */ 387 | /***/ (function(module, exports, __webpack_require__) { 388 | 389 | "use strict"; 390 | /* WEBPACK VAR INJECTION */(function(process) {/** 391 | * Copyright (c) 2014-present, Facebook, Inc. 392 | * 393 | * This source code is licensed under the MIT license found in the 394 | * LICENSE file in the root directory of this source tree. 395 | * 396 | */ 397 | 398 | 399 | 400 | var emptyFunction = __webpack_require__(1); 401 | 402 | /** 403 | * Similar to invariant but only logs a warning if the condition is not met. 404 | * This can be used to log issues in development environments in critical 405 | * paths. Removing the logging code for production environments will keep the 406 | * same logic and follow the same code paths. 407 | */ 408 | 409 | var warning = emptyFunction; 410 | 411 | if (process.env.NODE_ENV !== 'production') { 412 | var printWarning = function printWarning(format) { 413 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 414 | args[_key - 1] = arguments[_key]; 415 | } 416 | 417 | var argIndex = 0; 418 | var message = 'Warning: ' + format.replace(/%s/g, function () { 419 | return args[argIndex++]; 420 | }); 421 | if (typeof console !== 'undefined') { 422 | console.error(message); 423 | } 424 | try { 425 | // --- Welcome to debugging React --- 426 | // This error was thrown as a convenience so that you can use this stack 427 | // to find the callsite that caused this warning to fire. 428 | throw new Error(message); 429 | } catch (x) {} 430 | }; 431 | 432 | warning = function warning(condition, format) { 433 | if (format === undefined) { 434 | throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); 435 | } 436 | 437 | if (format.indexOf('Failed Composite propType: ') === 0) { 438 | return; // Ignore CompositeComponent proptype check. 439 | } 440 | 441 | if (!condition) { 442 | for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { 443 | args[_key2 - 2] = arguments[_key2]; 444 | } 445 | 446 | printWarning.apply(undefined, [format].concat(args)); 447 | } 448 | }; 449 | } 450 | 451 | module.exports = warning; 452 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) 453 | 454 | /***/ }), 455 | /* 5 */ 456 | /***/ (function(module, exports, __webpack_require__) { 457 | 458 | "use strict"; 459 | /* WEBPACK VAR INJECTION */(function(process) { 460 | 461 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 462 | 463 | /** 464 | * Copyright 2013-present, Facebook, Inc. 465 | * All rights reserved. 466 | * 467 | * This source code is licensed under the BSD-style license found in the 468 | * LICENSE file in the root directory of this source tree. An additional grant 469 | * of patent rights can be found in the PATENTS file in the same directory. 470 | */ 471 | 472 | if (process.env.NODE_ENV !== 'production') { 473 | var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element') || 0xeac7; 474 | 475 | var isValidElement = function isValidElement(object) { 476 | return (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; 477 | }; 478 | 479 | // By explicitly using `prop-types` you are opting into new development behavior. 480 | // http://fb.me/prop-types-in-prod 481 | var throwOnDirectAccess = true; 482 | module.exports = __webpack_require__(9)(isValidElement, throwOnDirectAccess); 483 | } else { 484 | // By explicitly using `prop-types` you are opting into new production behavior. 485 | // http://fb.me/prop-types-in-prod 486 | module.exports = __webpack_require__(8)(); 487 | } 488 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) 489 | 490 | /***/ }), 491 | /* 6 */ 492 | /***/ (function(module, exports) { 493 | 494 | module.exports = require("react"); 495 | 496 | /***/ }), 497 | /* 7 */ 498 | /***/ (function(module, exports, __webpack_require__) { 499 | 500 | "use strict"; 501 | /* WEBPACK VAR INJECTION */(function(process) {/** 502 | * Copyright 2013-present, Facebook, Inc. 503 | * All rights reserved. 504 | * 505 | * This source code is licensed under the BSD-style license found in the 506 | * LICENSE file in the root directory of this source tree. An additional grant 507 | * of patent rights can be found in the PATENTS file in the same directory. 508 | */ 509 | 510 | 511 | 512 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 513 | 514 | if (process.env.NODE_ENV !== 'production') { 515 | var invariant = __webpack_require__(2); 516 | var warning = __webpack_require__(4); 517 | var ReactPropTypesSecret = __webpack_require__(3); 518 | var loggedTypeFailures = {}; 519 | } 520 | 521 | /** 522 | * Assert that the values match with the type specs. 523 | * Error messages are memorized and will only be shown once. 524 | * 525 | * @param {object} typeSpecs Map of name to a ReactPropType 526 | * @param {object} values Runtime values that need to be type-checked 527 | * @param {string} location e.g. "prop", "context", "child context" 528 | * @param {string} componentName Name of the component for error messages. 529 | * @param {?Function} getStack Returns the component stack. 530 | * @private 531 | */ 532 | function checkPropTypes(typeSpecs, values, location, componentName, getStack) { 533 | if (process.env.NODE_ENV !== 'production') { 534 | for (var typeSpecName in typeSpecs) { 535 | if (typeSpecs.hasOwnProperty(typeSpecName)) { 536 | var error; 537 | // Prop type validation may throw. In case they do, we don't want to 538 | // fail the render phase where it didn't fail before. So we log it. 539 | // After these have been cleaned up, we'll let them throw. 540 | try { 541 | // This is intentionally an invariant that gets caught. It's the same 542 | // behavior as without this statement except with a better message. 543 | invariant(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', componentName || 'React class', location, typeSpecName); 544 | error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); 545 | } catch (ex) { 546 | error = ex; 547 | } 548 | warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error === 'undefined' ? 'undefined' : _typeof(error)); 549 | if (error instanceof Error && !(error.message in loggedTypeFailures)) { 550 | // Only monitor this failure once because there tends to be a lot of the 551 | // same error. 552 | loggedTypeFailures[error.message] = true; 553 | 554 | var stack = getStack ? getStack() : ''; 555 | 556 | warning(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); 557 | } 558 | } 559 | } 560 | } 561 | } 562 | 563 | module.exports = checkPropTypes; 564 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) 565 | 566 | /***/ }), 567 | /* 8 */ 568 | /***/ (function(module, exports, __webpack_require__) { 569 | 570 | "use strict"; 571 | /** 572 | * Copyright 2013-present, Facebook, Inc. 573 | * All rights reserved. 574 | * 575 | * This source code is licensed under the BSD-style license found in the 576 | * LICENSE file in the root directory of this source tree. An additional grant 577 | * of patent rights can be found in the PATENTS file in the same directory. 578 | */ 579 | 580 | 581 | 582 | var emptyFunction = __webpack_require__(1); 583 | var invariant = __webpack_require__(2); 584 | var ReactPropTypesSecret = __webpack_require__(3); 585 | 586 | module.exports = function () { 587 | function shim(props, propName, componentName, location, propFullName, secret) { 588 | if (secret === ReactPropTypesSecret) { 589 | // It is still safe when called from React. 590 | return; 591 | } 592 | invariant(false, 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use PropTypes.checkPropTypes() to call them. ' + 'Read more at http://fb.me/use-check-prop-types'); 593 | }; 594 | shim.isRequired = shim; 595 | function getShim() { 596 | return shim; 597 | }; 598 | // Important! 599 | // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. 600 | var ReactPropTypes = { 601 | array: shim, 602 | bool: shim, 603 | func: shim, 604 | number: shim, 605 | object: shim, 606 | string: shim, 607 | symbol: shim, 608 | 609 | any: shim, 610 | arrayOf: getShim, 611 | element: shim, 612 | instanceOf: getShim, 613 | node: shim, 614 | objectOf: getShim, 615 | oneOf: getShim, 616 | oneOfType: getShim, 617 | shape: getShim 618 | }; 619 | 620 | ReactPropTypes.checkPropTypes = emptyFunction; 621 | ReactPropTypes.PropTypes = ReactPropTypes; 622 | 623 | return ReactPropTypes; 624 | }; 625 | 626 | /***/ }), 627 | /* 9 */ 628 | /***/ (function(module, exports, __webpack_require__) { 629 | 630 | "use strict"; 631 | /* WEBPACK VAR INJECTION */(function(process) {/** 632 | * Copyright 2013-present, Facebook, Inc. 633 | * All rights reserved. 634 | * 635 | * This source code is licensed under the BSD-style license found in the 636 | * LICENSE file in the root directory of this source tree. An additional grant 637 | * of patent rights can be found in the PATENTS file in the same directory. 638 | */ 639 | 640 | 641 | 642 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 643 | 644 | var emptyFunction = __webpack_require__(1); 645 | var invariant = __webpack_require__(2); 646 | var warning = __webpack_require__(4); 647 | 648 | var ReactPropTypesSecret = __webpack_require__(3); 649 | var checkPropTypes = __webpack_require__(7); 650 | 651 | module.exports = function (isValidElement, throwOnDirectAccess) { 652 | /* global Symbol */ 653 | var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; 654 | var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. 655 | 656 | /** 657 | * Returns the iterator method function contained on the iterable object. 658 | * 659 | * Be sure to invoke the function with the iterable as context: 660 | * 661 | * var iteratorFn = getIteratorFn(myIterable); 662 | * if (iteratorFn) { 663 | * var iterator = iteratorFn.call(myIterable); 664 | * ... 665 | * } 666 | * 667 | * @param {?object} maybeIterable 668 | * @return {?function} 669 | */ 670 | function getIteratorFn(maybeIterable) { 671 | var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); 672 | if (typeof iteratorFn === 'function') { 673 | return iteratorFn; 674 | } 675 | } 676 | 677 | /** 678 | * Collection of methods that allow declaration and validation of props that are 679 | * supplied to React components. Example usage: 680 | * 681 | * var Props = require('ReactPropTypes'); 682 | * var MyArticle = React.createClass({ 683 | * propTypes: { 684 | * // An optional string prop named "description". 685 | * description: Props.string, 686 | * 687 | * // A required enum prop named "category". 688 | * category: Props.oneOf(['News','Photos']).isRequired, 689 | * 690 | * // A prop named "dialog" that requires an instance of Dialog. 691 | * dialog: Props.instanceOf(Dialog).isRequired 692 | * }, 693 | * render: function() { ... } 694 | * }); 695 | * 696 | * A more formal specification of how these methods are used: 697 | * 698 | * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) 699 | * decl := ReactPropTypes.{type}(.isRequired)? 700 | * 701 | * Each and every declaration produces a function with the same signature. This 702 | * allows the creation of custom validation functions. For example: 703 | * 704 | * var MyLink = React.createClass({ 705 | * propTypes: { 706 | * // An optional string or URI prop named "href". 707 | * href: function(props, propName, componentName) { 708 | * var propValue = props[propName]; 709 | * if (propValue != null && typeof propValue !== 'string' && 710 | * !(propValue instanceof URI)) { 711 | * return new Error( 712 | * 'Expected a string or an URI for ' + propName + ' in ' + 713 | * componentName 714 | * ); 715 | * } 716 | * } 717 | * }, 718 | * render: function() {...} 719 | * }); 720 | * 721 | * @internal 722 | */ 723 | 724 | var ANONYMOUS = '<>'; 725 | 726 | // Important! 727 | // Keep this list in sync with production version in `./factoryWithThrowingShims.js`. 728 | var ReactPropTypes = { 729 | array: createPrimitiveTypeChecker('array'), 730 | bool: createPrimitiveTypeChecker('boolean'), 731 | func: createPrimitiveTypeChecker('function'), 732 | number: createPrimitiveTypeChecker('number'), 733 | object: createPrimitiveTypeChecker('object'), 734 | string: createPrimitiveTypeChecker('string'), 735 | symbol: createPrimitiveTypeChecker('symbol'), 736 | 737 | any: createAnyTypeChecker(), 738 | arrayOf: createArrayOfTypeChecker, 739 | element: createElementTypeChecker(), 740 | instanceOf: createInstanceTypeChecker, 741 | node: createNodeChecker(), 742 | objectOf: createObjectOfTypeChecker, 743 | oneOf: createEnumTypeChecker, 744 | oneOfType: createUnionTypeChecker, 745 | shape: createShapeTypeChecker 746 | }; 747 | 748 | /** 749 | * inlined Object.is polyfill to avoid requiring consumers ship their own 750 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 751 | */ 752 | /*eslint-disable no-self-compare*/ 753 | function is(x, y) { 754 | // SameValue algorithm 755 | if (x === y) { 756 | // Steps 1-5, 7-10 757 | // Steps 6.b-6.e: +0 != -0 758 | return x !== 0 || 1 / x === 1 / y; 759 | } else { 760 | // Step 6.a: NaN == NaN 761 | return x !== x && y !== y; 762 | } 763 | } 764 | /*eslint-enable no-self-compare*/ 765 | 766 | /** 767 | * We use an Error-like object for backward compatibility as people may call 768 | * PropTypes directly and inspect their output. However, we don't use real 769 | * Errors anymore. We don't inspect their stack anyway, and creating them 770 | * is prohibitively expensive if they are created too often, such as what 771 | * happens in oneOfType() for any type before the one that matched. 772 | */ 773 | function PropTypeError(message) { 774 | this.message = message; 775 | this.stack = ''; 776 | } 777 | // Make `instanceof Error` still work for returned errors. 778 | PropTypeError.prototype = Error.prototype; 779 | 780 | function createChainableTypeChecker(validate) { 781 | if (process.env.NODE_ENV !== 'production') { 782 | var manualPropTypeCallCache = {}; 783 | var manualPropTypeWarningCount = 0; 784 | } 785 | function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { 786 | componentName = componentName || ANONYMOUS; 787 | propFullName = propFullName || propName; 788 | 789 | if (secret !== ReactPropTypesSecret) { 790 | if (throwOnDirectAccess) { 791 | // New behavior only for users of `prop-types` package 792 | invariant(false, 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 'Use `PropTypes.checkPropTypes()` to call them. ' + 'Read more at http://fb.me/use-check-prop-types'); 793 | } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { 794 | // Old behavior for people using React.PropTypes 795 | var cacheKey = componentName + ':' + propName; 796 | if (!manualPropTypeCallCache[cacheKey] && 797 | // Avoid spamming the console because they are often not actionable except for lib authors 798 | manualPropTypeWarningCount < 3) { 799 | warning(false, 'You are manually calling a React.PropTypes validation ' + 'function for the `%s` prop on `%s`. This is deprecated ' + 'and will throw in the standalone `prop-types` package. ' + 'You may be seeing this warning due to a third-party PropTypes ' + 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.', propFullName, componentName); 800 | manualPropTypeCallCache[cacheKey] = true; 801 | manualPropTypeWarningCount++; 802 | } 803 | } 804 | } 805 | if (props[propName] == null) { 806 | if (isRequired) { 807 | if (props[propName] === null) { 808 | return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.')); 809 | } 810 | return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.')); 811 | } 812 | return null; 813 | } else { 814 | return validate(props, propName, componentName, location, propFullName); 815 | } 816 | } 817 | 818 | var chainedCheckType = checkType.bind(null, false); 819 | chainedCheckType.isRequired = checkType.bind(null, true); 820 | 821 | return chainedCheckType; 822 | } 823 | 824 | function createPrimitiveTypeChecker(expectedType) { 825 | function validate(props, propName, componentName, location, propFullName, secret) { 826 | var propValue = props[propName]; 827 | var propType = getPropType(propValue); 828 | if (propType !== expectedType) { 829 | // `propValue` being instance of, say, date/regexp, pass the 'object' 830 | // check, but we can offer a more precise error message here rather than 831 | // 'of type `object`'. 832 | var preciseType = getPreciseType(propValue); 833 | 834 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.')); 835 | } 836 | return null; 837 | } 838 | return createChainableTypeChecker(validate); 839 | } 840 | 841 | function createAnyTypeChecker() { 842 | return createChainableTypeChecker(emptyFunction.thatReturnsNull); 843 | } 844 | 845 | function createArrayOfTypeChecker(typeChecker) { 846 | function validate(props, propName, componentName, location, propFullName) { 847 | if (typeof typeChecker !== 'function') { 848 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.'); 849 | } 850 | var propValue = props[propName]; 851 | if (!Array.isArray(propValue)) { 852 | var propType = getPropType(propValue); 853 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); 854 | } 855 | for (var i = 0; i < propValue.length; i++) { 856 | var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret); 857 | if (error instanceof Error) { 858 | return error; 859 | } 860 | } 861 | return null; 862 | } 863 | return createChainableTypeChecker(validate); 864 | } 865 | 866 | function createElementTypeChecker() { 867 | function validate(props, propName, componentName, location, propFullName) { 868 | var propValue = props[propName]; 869 | if (!isValidElement(propValue)) { 870 | var propType = getPropType(propValue); 871 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.')); 872 | } 873 | return null; 874 | } 875 | return createChainableTypeChecker(validate); 876 | } 877 | 878 | function createInstanceTypeChecker(expectedClass) { 879 | function validate(props, propName, componentName, location, propFullName) { 880 | if (!(props[propName] instanceof expectedClass)) { 881 | var expectedClassName = expectedClass.name || ANONYMOUS; 882 | var actualClassName = getClassName(props[propName]); 883 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); 884 | } 885 | return null; 886 | } 887 | return createChainableTypeChecker(validate); 888 | } 889 | 890 | function createEnumTypeChecker(expectedValues) { 891 | if (!Array.isArray(expectedValues)) { 892 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.') : void 0; 893 | return emptyFunction.thatReturnsNull; 894 | } 895 | 896 | function validate(props, propName, componentName, location, propFullName) { 897 | var propValue = props[propName]; 898 | for (var i = 0; i < expectedValues.length; i++) { 899 | if (is(propValue, expectedValues[i])) { 900 | return null; 901 | } 902 | } 903 | 904 | var valuesString = JSON.stringify(expectedValues); 905 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); 906 | } 907 | return createChainableTypeChecker(validate); 908 | } 909 | 910 | function createObjectOfTypeChecker(typeChecker) { 911 | function validate(props, propName, componentName, location, propFullName) { 912 | if (typeof typeChecker !== 'function') { 913 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); 914 | } 915 | var propValue = props[propName]; 916 | var propType = getPropType(propValue); 917 | if (propType !== 'object') { 918 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); 919 | } 920 | for (var key in propValue) { 921 | if (propValue.hasOwnProperty(key)) { 922 | var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); 923 | if (error instanceof Error) { 924 | return error; 925 | } 926 | } 927 | } 928 | return null; 929 | } 930 | return createChainableTypeChecker(validate); 931 | } 932 | 933 | function createUnionTypeChecker(arrayOfTypeCheckers) { 934 | if (!Array.isArray(arrayOfTypeCheckers)) { 935 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; 936 | return emptyFunction.thatReturnsNull; 937 | } 938 | 939 | for (var i = 0; i < arrayOfTypeCheckers.length; i++) { 940 | var checker = arrayOfTypeCheckers[i]; 941 | if (typeof checker !== 'function') { 942 | warning(false, 'Invalid argument supplid to oneOfType. Expected an array of check functions, but ' + 'received %s at index %s.', getPostfixForTypeWarning(checker), i); 943 | return emptyFunction.thatReturnsNull; 944 | } 945 | } 946 | 947 | function validate(props, propName, componentName, location, propFullName) { 948 | for (var i = 0; i < arrayOfTypeCheckers.length; i++) { 949 | var checker = arrayOfTypeCheckers[i]; 950 | if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) { 951 | return null; 952 | } 953 | } 954 | 955 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.')); 956 | } 957 | return createChainableTypeChecker(validate); 958 | } 959 | 960 | function createNodeChecker() { 961 | function validate(props, propName, componentName, location, propFullName) { 962 | if (!isNode(props[propName])) { 963 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); 964 | } 965 | return null; 966 | } 967 | return createChainableTypeChecker(validate); 968 | } 969 | 970 | function createShapeTypeChecker(shapeTypes) { 971 | function validate(props, propName, componentName, location, propFullName) { 972 | var propValue = props[propName]; 973 | var propType = getPropType(propValue); 974 | if (propType !== 'object') { 975 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); 976 | } 977 | for (var key in shapeTypes) { 978 | var checker = shapeTypes[key]; 979 | if (!checker) { 980 | continue; 981 | } 982 | var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); 983 | if (error) { 984 | return error; 985 | } 986 | } 987 | return null; 988 | } 989 | return createChainableTypeChecker(validate); 990 | } 991 | 992 | function isNode(propValue) { 993 | switch (typeof propValue === 'undefined' ? 'undefined' : _typeof(propValue)) { 994 | case 'number': 995 | case 'string': 996 | case 'undefined': 997 | return true; 998 | case 'boolean': 999 | return !propValue; 1000 | case 'object': 1001 | if (Array.isArray(propValue)) { 1002 | return propValue.every(isNode); 1003 | } 1004 | if (propValue === null || isValidElement(propValue)) { 1005 | return true; 1006 | } 1007 | 1008 | var iteratorFn = getIteratorFn(propValue); 1009 | if (iteratorFn) { 1010 | var iterator = iteratorFn.call(propValue); 1011 | var step; 1012 | if (iteratorFn !== propValue.entries) { 1013 | while (!(step = iterator.next()).done) { 1014 | if (!isNode(step.value)) { 1015 | return false; 1016 | } 1017 | } 1018 | } else { 1019 | // Iterator will provide entry [k,v] tuples rather than values. 1020 | while (!(step = iterator.next()).done) { 1021 | var entry = step.value; 1022 | if (entry) { 1023 | if (!isNode(entry[1])) { 1024 | return false; 1025 | } 1026 | } 1027 | } 1028 | } 1029 | } else { 1030 | return false; 1031 | } 1032 | 1033 | return true; 1034 | default: 1035 | return false; 1036 | } 1037 | } 1038 | 1039 | function isSymbol(propType, propValue) { 1040 | // Native Symbol. 1041 | if (propType === 'symbol') { 1042 | return true; 1043 | } 1044 | 1045 | // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' 1046 | if (propValue['@@toStringTag'] === 'Symbol') { 1047 | return true; 1048 | } 1049 | 1050 | // Fallback for non-spec compliant Symbols which are polyfilled. 1051 | if (typeof Symbol === 'function' && propValue instanceof Symbol) { 1052 | return true; 1053 | } 1054 | 1055 | return false; 1056 | } 1057 | 1058 | // Equivalent of `typeof` but with special handling for array and regexp. 1059 | function getPropType(propValue) { 1060 | var propType = typeof propValue === 'undefined' ? 'undefined' : _typeof(propValue); 1061 | if (Array.isArray(propValue)) { 1062 | return 'array'; 1063 | } 1064 | if (propValue instanceof RegExp) { 1065 | // Old webkits (at least until Android 4.0) return 'function' rather than 1066 | // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ 1067 | // passes PropTypes.object. 1068 | return 'object'; 1069 | } 1070 | if (isSymbol(propType, propValue)) { 1071 | return 'symbol'; 1072 | } 1073 | return propType; 1074 | } 1075 | 1076 | // This handles more types than `getPropType`. Only used for error messages. 1077 | // See `createPrimitiveTypeChecker`. 1078 | function getPreciseType(propValue) { 1079 | if (typeof propValue === 'undefined' || propValue === null) { 1080 | return '' + propValue; 1081 | } 1082 | var propType = getPropType(propValue); 1083 | if (propType === 'object') { 1084 | if (propValue instanceof Date) { 1085 | return 'date'; 1086 | } else if (propValue instanceof RegExp) { 1087 | return 'regexp'; 1088 | } 1089 | } 1090 | return propType; 1091 | } 1092 | 1093 | // Returns a string that is postfixed to a warning about an invalid type. 1094 | // For example, "undefined" or "of type array" 1095 | function getPostfixForTypeWarning(value) { 1096 | var type = getPreciseType(value); 1097 | switch (type) { 1098 | case 'array': 1099 | case 'object': 1100 | return 'an ' + type; 1101 | case 'boolean': 1102 | case 'date': 1103 | case 'regexp': 1104 | return 'a ' + type; 1105 | default: 1106 | return type; 1107 | } 1108 | } 1109 | 1110 | // Returns class name of the object, if any. 1111 | function getClassName(propValue) { 1112 | if (!propValue.constructor || !propValue.constructor.name) { 1113 | return ANONYMOUS; 1114 | } 1115 | return propValue.constructor.name; 1116 | } 1117 | 1118 | ReactPropTypes.checkPropTypes = checkPropTypes; 1119 | ReactPropTypes.PropTypes = ReactPropTypes; 1120 | 1121 | return ReactPropTypes; 1122 | }; 1123 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) 1124 | 1125 | /***/ }), 1126 | /* 10 */ 1127 | /***/ (function(module, exports, __webpack_require__) { 1128 | 1129 | "use strict"; 1130 | 1131 | 1132 | Object.defineProperty(exports, "__esModule", { 1133 | value: true 1134 | }); 1135 | 1136 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1137 | 1138 | var _react = __webpack_require__(6); 1139 | 1140 | var _react2 = _interopRequireDefault(_react); 1141 | 1142 | var _propTypes = __webpack_require__(5); 1143 | 1144 | var _propTypes2 = _interopRequireDefault(_propTypes); 1145 | 1146 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1147 | 1148 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1149 | 1150 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1151 | 1152 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1153 | 1154 | /** 1155 | * @constant types 1156 | * @type {{mount: string, unmounted: string}} 1157 | */ 1158 | var types = { 1159 | MOUNT: 'mount', 1160 | UNMOUNT: 'unmount' 1161 | }; 1162 | 1163 | /** 1164 | * @class ReactDelayed 1165 | * @extends {Component} 1166 | */ 1167 | 1168 | var ReactDelayed = function (_Component) { 1169 | _inherits(ReactDelayed, _Component); 1170 | 1171 | function ReactDelayed() { 1172 | var _ref; 1173 | 1174 | var _temp, _this, _ret; 1175 | 1176 | _classCallCheck(this, ReactDelayed); 1177 | 1178 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 1179 | args[_key] = arguments[_key]; 1180 | } 1181 | 1182 | return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ReactDelayed.__proto__ || Object.getPrototypeOf(ReactDelayed)).call.apply(_ref, [this].concat(args))), _this), _this.state = { mounted: typeof window === 'undefined' ? _this.props.mounted : false, deferred: null }, _temp), _possibleConstructorReturn(_this, _ret); 1183 | } 1184 | 1185 | /** 1186 | * @constant state 1187 | * @type {{mounted: boolean}} 1188 | */ 1189 | 1190 | 1191 | /** 1192 | * @constant propTypes 1193 | * @type {{mountAfter: function, unmountAfter: function}} 1194 | */ 1195 | 1196 | 1197 | /** 1198 | * @constant defaultProps 1199 | * @type {{mountAfter: number, unmountAfter: number}} 1200 | */ 1201 | 1202 | 1203 | _createClass(ReactDelayed, [{ 1204 | key: 'componentDidMount', 1205 | 1206 | 1207 | /** 1208 | * @method componentDidMount 1209 | * @return {void} 1210 | */ 1211 | value: function componentDidMount() { 1212 | this.isComponentMounted = true; 1213 | this.props.mounted === true && this.handleVisibility(types.MOUNT); 1214 | } 1215 | 1216 | /** 1217 | * @method componentWillUnmount 1218 | * @return {void} 1219 | */ 1220 | 1221 | }, { 1222 | key: 'componentWillUnmount', 1223 | value: function componentWillUnmount() { 1224 | this.isComponentMounted = false; 1225 | } 1226 | 1227 | /** 1228 | * @method componentWillReceiveProps 1229 | * @param {Object} nextProps 1230 | * @return {void} 1231 | */ 1232 | 1233 | }, { 1234 | key: 'componentWillReceiveProps', 1235 | value: function componentWillReceiveProps(nextProps) { 1236 | this.props.mounted === false && nextProps.mounted === true && this.handleVisibility(types.MOUNT); 1237 | this.props.mounted === true && nextProps.mounted === false && this.handleVisibility(types.UNMOUNT); 1238 | } 1239 | 1240 | /** 1241 | * @method handleVisibility 1242 | * @param {String} type 1243 | * @return {void} 1244 | */ 1245 | 1246 | }, { 1247 | key: 'handleVisibility', 1248 | value: function handleVisibility(type) { 1249 | var _this2 = this; 1250 | 1251 | var mounted = type === types.MOUNT; 1252 | var timeout = this.props[type + 'After']; 1253 | var invoker = timeout === 0 ? function (fn) { 1254 | return fn(); 1255 | } : setTimeout; 1256 | 1257 | clearTimeout(this.state.deferred); 1258 | var deferred = invoker(function () { 1259 | return _this2.isComponentMounted && _this2.setState({ mounted: mounted }); 1260 | }, timeout); 1261 | this.setState({ deferred: deferred }); 1262 | } 1263 | 1264 | /** 1265 | * @method render 1266 | * @return {XML} 1267 | */ 1268 | 1269 | }, { 1270 | key: 'render', 1271 | value: function render() { 1272 | var isFunction = typeof this.props.children === 'function'; 1273 | return this.state.mounted ? isFunction ? this.props.children() : this.props.children : _react2.default.createElement(this.props.nodeName, null); 1274 | } 1275 | }]); 1276 | 1277 | return ReactDelayed; 1278 | }(_react.Component); 1279 | 1280 | ReactDelayed.propTypes = { 1281 | mounted: _propTypes2.default.bool.isRequired, 1282 | mountAfter: _propTypes2.default.number.isRequired, 1283 | unmountAfter: _propTypes2.default.number.isRequired, 1284 | children: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.func]).isRequired, 1285 | nodeName: _propTypes2.default.string.isRequired 1286 | }; 1287 | ReactDelayed.defaultProps = { 1288 | mounted: false, 1289 | mountAfter: 0, 1290 | unmountAfter: 0, 1291 | children: _react2.default.createElement('span', null), 1292 | nodeName: 'span' 1293 | }; 1294 | exports.default = ReactDelayed; 1295 | 1296 | /***/ }) 1297 | /******/ ]); -------------------------------------------------------------------------------- /example/css/default.scss: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | font-family: Lato, Arial, Tahoma, Helvetica, sans-serif; 6 | } 7 | 8 | main { 9 | @import './modal'; 10 | 11 | > h1 { 12 | display: flex; 13 | align-items: center; 14 | width: 100vw; 15 | text-transform: uppercase; 16 | font-size: 9px; 17 | padding: 5px 20px; 18 | font-weight: normal; 19 | height: 50px; 20 | border-bottom: 1px solid rgba(0, 0, 0, .05); 21 | } 22 | 23 | > section.buttons { 24 | display: flex; 25 | align-items: center; 26 | justify-content: center; 27 | width: 100vw; 28 | height: calc(100vh - 50px); 29 | 30 | @media (max-width: 480px) { 31 | flex-direction: column; 32 | justify-content: flex-start; 33 | padding-top: 10px; 34 | } 35 | 36 | > button { 37 | border: 0; 38 | outline: none; 39 | color: white; 40 | padding: 30px 45px; 41 | margin: 0 10px; 42 | font-size: 12px; 43 | text-transform: uppercase; 44 | cursor: pointer; 45 | transition: background-color .25s; 46 | 47 | @media (max-width: 480px) { 48 | margin: 10px 0; 49 | width: 90vw; 50 | } 51 | 52 | &:first-of-type { 53 | background-color: rebeccapurple; 54 | border-bottom: 1px solid darken(rebeccapurple, 5); 55 | 56 | &:hover { 57 | background-color: darken(rebeccapurple, 5); 58 | } 59 | } 60 | 61 | &:nth-of-type(2) { 62 | background-color: darkolivegreen; 63 | border-bottom: 1px solid darken(darkolivegreen, 5); 64 | 65 | &:hover { 66 | background-color: darken(darkolivegreen, 5); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /example/css/modal.scss: -------------------------------------------------------------------------------- 1 | span.modal-container { 2 | 3 | > a { 4 | position: relative; 5 | z-index: 101; 6 | } 7 | 8 | > section.modal { 9 | position: fixed; 10 | top: 0; 11 | left: 0; 12 | width: 100%; 13 | height: 100%; 14 | display: inline-flex; 15 | justify-content: center; 16 | align-items: center; 17 | z-index: 1001; 18 | background-color: rgba(0, 0, 0, .05); 19 | transition: opacity .35s, visibility .35s; 20 | visibility: visible; 21 | 22 | &.closed { 23 | opacity: 0; 24 | pointer-events: none; 25 | visibility: hidden; 26 | } 27 | 28 | &.open > section.dialog { 29 | transform: scale(1); 30 | } 31 | 32 | > section.dialog { 33 | background-color: white; 34 | box-shadow: 0 0 50px rgba(0, 0, 0, .35); 35 | min-width: 200px; 36 | text-align: left; 37 | transition: all .4s cubic-bezier(0.175, 0.885, 0.32, 1.275); 38 | transform: scale(0.65); 39 | overflow: hidden; 40 | 41 | > header { 42 | $height: 40px; 43 | position: relative; 44 | height: $height; 45 | line-height: $height; 46 | 47 | > h5 { 48 | width: calc(70% - #{$height}); 49 | white-space: nowrap; 50 | text-overflow: ellipsis; 51 | overflow: hidden; 52 | padding-left: 15px; 53 | color: black; 54 | text-transform: uppercase; 55 | font-size: 12px; 56 | } 57 | 58 | > a.close { 59 | cursor: pointer; 60 | height: $height; 61 | line-height: $height; 62 | width: $height; 63 | position: absolute; 64 | text-align: center; 65 | top: 0; 66 | right: 0; 67 | text-decoration: none; 68 | font-size: 20px; 69 | border-left: 1px solid rgba(0, 0, 0, .1); 70 | transition: background-color .15s; 71 | user-select: none; 72 | color: black; 73 | 74 | &:hover { 75 | background-color: white; 76 | } 77 | } 78 | } 79 | 80 | > div.content { 81 | display: flex; 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /example/images/nyan.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wildhoney/ReactDelayed/73272c53cbef1c4b7ccc75f0fb224d941e006c31/example/images/nyan.gif -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | React Delayed 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/js/default.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { render } from 'react-dom'; 3 | import Symbol from 'es6-symbol'; 4 | import Modal from './modal'; 5 | import Delayed from '../../src/react-delayed'; 6 | 7 | /** 8 | * @constant modalTypes 9 | * @type {{without: *, with: *}} 10 | */ 11 | const modalTypes = { 12 | without: Symbol('without'), 13 | with: Symbol('with') 14 | }; 15 | 16 | /** 17 | * @class Example 18 | * @extends {Component} 19 | */ 20 | class Example extends Component { 21 | 22 | /** 23 | * @constant state 24 | * @type {{modal: null}} 25 | */ 26 | state = { modal: null }; 27 | 28 | /** 29 | * @method render 30 | * @return {XML} 31 | */ 32 | render() { 33 | 34 | const isWithoutOpen = this.state.modal === modalTypes.without; 35 | const isWithOpen = this.state.modal === modalTypes.with; 36 | 37 | return ( 38 |
39 | 40 |

<Delayed />

41 | 42 |
43 | 44 | 45 |
46 | 47 | this.setState({ modal: null })} 51 | > 52 | {isWithoutOpen && Nyan} 53 | 54 | 55 | this.setState({ modal: null })} 59 | > 60 | 61 | Nyan 62 | 63 | 64 | 65 |
66 | ); 67 | 68 | } 69 | 70 | } 71 | 72 | document.addEventListener('DOMContentLoaded', () => { 73 | const mountNode = document.querySelector('section.app'); 74 | render(, mountNode); 75 | }); 76 | -------------------------------------------------------------------------------- /example/js/modal.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export default class Modal extends PureComponent { 5 | 6 | /** 7 | * @constant propTypes 8 | * @type {Object} 9 | */ 10 | static propTypes = { 11 | className: PropTypes.string, 12 | title: PropTypes.string.isRequired, 13 | children: PropTypes.node.isRequired, 14 | isOpen: PropTypes.bool.isRequired, 15 | onOpen: PropTypes.func.isRequired, 16 | onClose: PropTypes.func.isRequired, 17 | stopPropagation: PropTypes.func.isRequired 18 | }; 19 | 20 | /** 21 | * @constant defaultProps 22 | * @type {Object} 23 | */ 24 | static defaultProps = { 25 | isOpen: false, 26 | className: '', 27 | onOpen: () => {}, 28 | onClose: () => {}, 29 | stopPropagation: event => event.stopPropagation() 30 | }; 31 | 32 | /** 33 | * @method componentWillReceiveProps 34 | * @param {Object} nextProps 35 | * @return {void} 36 | */ 37 | componentWillReceiveProps(nextProps) { 38 | !this.props.isOpen && nextProps.isOpen && this.props.onOpen(); 39 | } 40 | 41 | /** 42 | * @method render 43 | * @return {XML} 44 | */ 45 | render() { 46 | 47 | const { children, isOpen, className, onClose, stopPropagation } = this.props; 48 | const modalClassName = `modal ${isOpen ? 'open' : 'closed'} ${className}`.trim(); 49 | 50 | return ( 51 | 52 | 53 |
54 | 55 |
56 | 57 |
58 |
{this.props.title}
59 | × 60 |
61 | 62 |
63 | {children} 64 |
65 | 66 |
67 | 68 |
69 | 70 |
71 | ); 72 | 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /example/server/default.js: -------------------------------------------------------------------------------- 1 | import http from 'http'; 2 | import express from 'express'; 3 | 4 | const app = express(); 5 | const server = http.createServer(app); 6 | const port = process.env.PORT || 5000; 7 | 8 | app.use(express.static(`${__dirname}/..`)); 9 | server.listen(port); 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-delayed", 3 | "version": "0.2.3", 4 | "description": "Small component for delaying the mounting and unmounting of a child component for CSS animation purposes.", 5 | "main": "dist/react-delayed.js", 6 | "scripts": { 7 | "build": "webpack --config webpack.config.release.js", 8 | "sass": "node-sass ./example/css/default.scss -o ./example/css", 9 | "start": "npm run sass && webpack --config webpack.config.example.js && babel-node example/server/default.js", 10 | "watch": "webpack --config webpack.config.example.js --watch", 11 | "test": "npm run spec && npm run lint", 12 | "spec": "nyc ava && npm run report", 13 | "lint": "xo src/*.js", 14 | "report": "nyc report --reporter=html" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/Wildhoney/ReactDelayed.git" 19 | }, 20 | "keywords": [ 21 | "delayed", 22 | "deferred", 23 | "delay", 24 | "delay", 25 | "render", 26 | "mount", 27 | "unmount", 28 | "css", 29 | "animation", 30 | "transition" 31 | ], 32 | "author": "Adam Timberlake ", 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/Wildhoney/ReactDelayed/issues" 36 | }, 37 | "homepage": "https://github.com/Wildhoney/ReactDelayed#readme", 38 | "peerDependencies": { 39 | "react": ">=15.4.2", 40 | "react-dom": ">=15.4.2" 41 | }, 42 | "devDependencies": { 43 | "async-delay": "~1.0.3", 44 | "ava": "~0.18.2", 45 | "babel-cli": "~6.24.0", 46 | "babel-eslint": "~7.2.1", 47 | "babel-loader": "~6.4.1", 48 | "babel-polyfill": "~6.23.0", 49 | "babel-preset-es2015": "~6.24.0", 50 | "babel-preset-react": "~6.23.0", 51 | "babel-preset-stage-0": "~6.22.0", 52 | "coveralls": "~2.13.0", 53 | "enzyme": "~2.8.0", 54 | "es6-symbol": "~3.1.1", 55 | "eslint-config-xo-react": "~0.11.1", 56 | "eslint-plugin-react": "~6.10.3", 57 | "express": "~4.15.2", 58 | "jsdom": "~9.12.0", 59 | "node-sass": "~4.5.1", 60 | "nyc": "~10.2.0", 61 | "prop-types": "~15.5.8", 62 | "react": ">=15.4.2", 63 | "react-dom": ">=15.4.2", 64 | "react-addons-test-utils": ">=15.4.2", 65 | "sinon": "~2.1.0", 66 | "webpack": "~2.3.2", 67 | "xo": "~0.18.1" 68 | }, 69 | "ava": { 70 | "files": [ 71 | "tests/*.test.js" 72 | ], 73 | "babel": "inherit", 74 | "require": [ 75 | "babel-register", 76 | "babel-polyfill", 77 | "./tests/helpers/browser-env.js" 78 | ] 79 | }, 80 | "xo": { 81 | "space": 4, 82 | "esnext": true, 83 | "parser": "babel-eslint", 84 | "globals": [ 85 | "window", 86 | "document" 87 | ], 88 | "extends": "xo-react", 89 | "rules": { 90 | "padded-blocks": "off", 91 | "object-curly-spacing": [ 92 | 2, 93 | "always" 94 | ], 95 | "react/jsx-tag-spacing": [ 96 | 2, 97 | "never" 98 | ], 99 | "no-unused-expressions": "off", 100 | "react/no-unused-prop-types": "off", 101 | "react/jsx-space-before-closing": [ 102 | 2, 103 | "always" 104 | ], 105 | "react/jsx-filename-extension": [ 106 | 1, 107 | { 108 | "extensions": [ 109 | ".js" 110 | ] 111 | } 112 | ] 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/react-delayed.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | /** 5 | * @constant types 6 | * @type {{mount: string, unmounted: string}} 7 | */ 8 | const types = { 9 | MOUNT: 'mount', 10 | UNMOUNT: 'unmount' 11 | }; 12 | 13 | /** 14 | * @class ReactDelayed 15 | * @extends {Component} 16 | */ 17 | export default class ReactDelayed extends Component { 18 | 19 | /** 20 | * @constant state 21 | * @type {{mounted: boolean}} 22 | */ 23 | state = { mounted: typeof window === 'undefined' ? this.props.mounted : false, deferred: null }; 24 | 25 | /** 26 | * @constant propTypes 27 | * @type {{mountAfter: function, unmountAfter: function}} 28 | */ 29 | static propTypes = { 30 | mounted: PropTypes.bool.isRequired, 31 | mountAfter: PropTypes.number.isRequired, 32 | unmountAfter: PropTypes.number.isRequired, 33 | children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, 34 | nodeName: PropTypes.string.isRequired 35 | }; 36 | 37 | /** 38 | * @constant defaultProps 39 | * @type {{mountAfter: number, unmountAfter: number}} 40 | */ 41 | static defaultProps = { 42 | mounted: false, 43 | mountAfter: 0, 44 | unmountAfter: 0, 45 | children: , 46 | nodeName: 'span' 47 | }; 48 | 49 | /** 50 | * @method componentDidMount 51 | * @return {void} 52 | */ 53 | componentDidMount() { 54 | this.isComponentMounted = true; 55 | this.props.mounted === true && this.handleVisibility(types.MOUNT); 56 | } 57 | 58 | /** 59 | * @method componentWillUnmount 60 | * @return {void} 61 | */ 62 | componentWillUnmount() { 63 | this.isComponentMounted = false; 64 | } 65 | 66 | /** 67 | * @method componentWillReceiveProps 68 | * @param {Object} nextProps 69 | * @return {void} 70 | */ 71 | componentWillReceiveProps(nextProps) { 72 | this.props.mounted === false && nextProps.mounted === true && this.handleVisibility(types.MOUNT); 73 | this.props.mounted === true && nextProps.mounted === false && this.handleVisibility(types.UNMOUNT); 74 | } 75 | 76 | /** 77 | * @method handleVisibility 78 | * @param {String} type 79 | * @return {void} 80 | */ 81 | handleVisibility(type) { 82 | 83 | const mounted = type === types.MOUNT; 84 | const timeout = this.props[`${type}After`]; 85 | const invoker = timeout === 0 ? fn => fn() : setTimeout; 86 | 87 | clearTimeout(this.state.deferred); 88 | const deferred = invoker(() => this.isComponentMounted && this.setState({ mounted }), timeout); 89 | this.setState({ deferred }); 90 | 91 | } 92 | 93 | /** 94 | * @method render 95 | * @return {XML} 96 | */ 97 | render() { 98 | const isFunction = typeof this.props.children === 'function'; 99 | return this.state.mounted ? (isFunction ? this.props.children() : this.props.children) : ; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /tests/helpers/browser-env.js: -------------------------------------------------------------------------------- 1 | import { jsdom } from 'jsdom'; 2 | 3 | global.document = jsdom(''); 4 | global.window = document.defaultView; 5 | global.navigator = window.navigator; 6 | -------------------------------------------------------------------------------- /tests/react-delayed.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { mount } from 'enzyme'; 3 | import React, { Component } from 'react'; 4 | import delay from 'async-delay'; 5 | import { spy } from 'sinon'; 6 | import Delayed from '../src/react-delayed'; 7 | 8 | test.beforeEach(t => { 9 | 10 | class Nested extends Component { 11 | 12 | /** 13 | * @method componentDidMount 14 | * @return {void} 15 | */ 16 | componentDidMount() {} 17 | 18 | /** 19 | * @method componentWillUnmount 20 | * @return {void} 21 | */ 22 | componentWillUnmount() {} 23 | 24 | /** 25 | * @method render 26 | * @return {XML} 27 | */ 28 | render() { 29 | return

<Delayed />

30 | } 31 | 32 | } 33 | 34 | /** 35 | * @constant lifecycle 36 | * @type {{componentDidMount: *}} 37 | */ 38 | t.context.lifecycle = { 39 | componentDidMount: spy(Nested.prototype, 'componentDidMount'), 40 | componentWillUnmount: spy(Nested.prototype, 'componentWillUnmount') 41 | }; 42 | 43 | /** 44 | * @method createComponent 45 | * @param {Object} props 46 | * @return {XML} 47 | */ 48 | t.context.createComponent = props => ; 49 | 50 | }); 51 | 52 | test('It should be able to delay mounting;', async t => { 53 | 54 | mount(t.context.createComponent({ mounted: true, mountAfter: 100 })); 55 | t.is(t.context.lifecycle.componentDidMount.callCount, 0); 56 | await delay(200); 57 | t.is(t.context.lifecycle.componentDidMount.callCount, 1); 58 | t.context.lifecycle.componentDidMount.reset(); 59 | 60 | const wrapper = mount(t.context.createComponent({ mounted: false, mountAfter: 100 })); 61 | t.is(t.context.lifecycle.componentDidMount.callCount, 0); 62 | wrapper.setProps({ mounted: true }); 63 | t.is(t.context.lifecycle.componentDidMount.callCount, 0); 64 | await delay(200); 65 | t.is(t.context.lifecycle.componentDidMount.callCount, 1); 66 | 67 | }); 68 | 69 | test('It should be able to delay unmounting;', async t => { 70 | 71 | const wrapper = mount(t.context.createComponent({ mounted: true, unmountAfter: 100 })); 72 | 73 | t.is(t.context.lifecycle.componentWillUnmount.callCount, 0); 74 | wrapper.setProps({ mounted: false }); 75 | t.is(t.context.lifecycle.componentWillUnmount.callCount, 0); 76 | await delay(200); 77 | t.is(t.context.lifecycle.componentWillUnmount.callCount, 1); 78 | 79 | }); 80 | -------------------------------------------------------------------------------- /webpack.config.example.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: ['babel-polyfill', './example/js/default.js'], 3 | output: { 4 | path: __dirname + '/example/js', 5 | filename: 'build.js', 6 | libraryTarget: 'var' 7 | }, 8 | module: { 9 | loaders: [ 10 | { 11 | test: /\.js$/, 12 | loader: 'babel-loader' 13 | } 14 | ] 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /webpack.config.release.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/react-delayed.js', 3 | output: { 4 | path: __dirname + '/dist', 5 | filename: 'react-delayed.js', 6 | libraryTarget: 'commonjs2' 7 | }, 8 | externals: { 9 | 'react': { 10 | commonjs2: 'react', 11 | }, 12 | 'react-dom':{ 13 | commonjs2: 'react-dom', 14 | } 15 | }, 16 | module: { 17 | loaders: [ 18 | { 19 | test: /\.js$/, 20 | loader: 'babel-loader' 21 | } 22 | ] 23 | } 24 | }; 25 | --------------------------------------------------------------------------------