├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── build ├── 1.0.0 │ ├── build.js │ └── build.js.map └── index.html ├── package.json ├── src ├── components │ ├── app.jsx │ ├── constants │ │ └── pages.js │ ├── items.jsx │ ├── page-about.jsx │ ├── page-account.jsx │ ├── page-home.jsx │ └── site-header.jsx ├── index.html ├── index.js ├── selectors │ ├── items │ │ └── items.js │ ├── selectors.js │ └── site │ │ ├── routing.js │ │ ├── selected-page.js │ │ └── site-header.js └── state │ ├── items │ └── reducers │ │ ├── items.js │ │ └── selected-item-id.js │ ├── site │ ├── actions │ │ └── update-url.js │ ├── constants │ │ ├── paths.js │ │ └── sections.js │ └── reducers │ │ ├── selected-section.js │ │ └── url.js │ └── store.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Baz 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # State-driven routing with react, redux, selectors 2 | See the related post: [State-Driven Routing with React, Redux, Selectors](http://www.thinkloop.com/article/state-driven-routing-react-redux-selectors/) 3 | 4 | ## Install 5 | 6 | Download `/build` folder and run a webserver in its root. 7 | 8 | ## License 9 | 10 | Released under an MIT license. 11 | 12 | ## Related 13 | - [link-react](https://github.com/thinkloop/link-react): A generalized link component that allows client-side navigation while taking into account exceptions. 14 | - [spa-webserver](https://github.com/thinkloop/spa-webserver): A development webserver that redirects to the nearest index.html for client-side SPA navigation. 15 | 16 | 17 | ## Other 18 | - [extreme decoupling todo app](https://github.com/thinkloop/todo-app/): Example todo app of extreme decoupling of react, redux and selectors 19 | - [memoizerific](https://github.com/thinkloop/memoizerific/): Fast, small, efficient JavaScript memoization to memoize JS functions 20 | 21 | Like it? Star It 22 | -------------------------------------------------------------------------------- /build/1.0.0/build.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o { 54 | Object.defineProperty(p, selectorKey, { 55 | get: function() { return selectors[selectorKey](getState(), ...args) }, 56 | enumerable: true 57 | }); 58 | return p; 59 | }, {}); 60 | }; 61 | 62 | },{}],3:[function(require,module,exports){ 63 | module.exports = React.createClass({ 64 | propTypes: { 65 | className: React.PropTypes.string, 66 | href: React.PropTypes.string, 67 | target: React.PropTypes.string, 68 | onClick: React.PropTypes.func 69 | }, 70 | 71 | handleClick: function(e) { 72 | 73 | // if target is set (e.g. to "_blank"), let the browser handle it 74 | if (this.props.target || (this.props.href && this.props.href.indexOf('mailto:') === 0)) { 75 | return; 76 | } 77 | 78 | // if keyboard click, or not a left click, let the browser handle it 79 | if (!e.button === 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { 80 | return; 81 | } 82 | 83 | // otherwise intercept the browser 84 | e.preventDefault(); 85 | 86 | // if a handler was provided, run it 87 | if (this.props.onClick) { 88 | this.props.onClick(this.props.href); 89 | } 90 | }, 91 | 92 | render: function() { 93 | return React.createElement('a', Object.assign({}, this.props, { 94 | href: this.props.href, 95 | className: 'link ' + this.props.className, 96 | onClick: this.handleClick 97 | })); 98 | } 99 | }); 100 | 101 | },{}],4:[function(require,module,exports){ 102 | var overArg = require('./_overArg'); 103 | 104 | /** Built-in value references. */ 105 | var getPrototype = overArg(Object.getPrototypeOf, Object); 106 | 107 | module.exports = getPrototype; 108 | 109 | },{"./_overArg":5}],5:[function(require,module,exports){ 110 | /** 111 | * Creates a unary function that invokes `func` with its argument transformed. 112 | * 113 | * @private 114 | * @param {Function} func The function to wrap. 115 | * @param {Function} transform The argument transform. 116 | * @returns {Function} Returns the new function. 117 | */ 118 | function overArg(func, transform) { 119 | return function(arg) { 120 | return func(transform(arg)); 121 | }; 122 | } 123 | 124 | module.exports = overArg; 125 | 126 | },{}],6:[function(require,module,exports){ 127 | /** 128 | * Checks if `value` is object-like. A value is object-like if it's not `null` 129 | * and has a `typeof` result of "object". 130 | * 131 | * @static 132 | * @memberOf _ 133 | * @since 4.0.0 134 | * @category Lang 135 | * @param {*} value The value to check. 136 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 137 | * @example 138 | * 139 | * _.isObjectLike({}); 140 | * // => true 141 | * 142 | * _.isObjectLike([1, 2, 3]); 143 | * // => true 144 | * 145 | * _.isObjectLike(_.noop); 146 | * // => false 147 | * 148 | * _.isObjectLike(null); 149 | * // => false 150 | */ 151 | function isObjectLike(value) { 152 | return value != null && typeof value == 'object'; 153 | } 154 | 155 | module.exports = isObjectLike; 156 | 157 | },{}],7:[function(require,module,exports){ 158 | var getPrototype = require('./_getPrototype'), 159 | isObjectLike = require('./isObjectLike'); 160 | 161 | /** `Object#toString` result references. */ 162 | var objectTag = '[object Object]'; 163 | 164 | /** Used for built-in method references. */ 165 | var funcProto = Function.prototype, 166 | objectProto = Object.prototype; 167 | 168 | /** Used to resolve the decompiled source of functions. */ 169 | var funcToString = funcProto.toString; 170 | 171 | /** Used to check objects for own properties. */ 172 | var hasOwnProperty = objectProto.hasOwnProperty; 173 | 174 | /** Used to infer the `Object` constructor. */ 175 | var objectCtorString = funcToString.call(Object); 176 | 177 | /** 178 | * Used to resolve the 179 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 180 | * of values. 181 | */ 182 | var objectToString = objectProto.toString; 183 | 184 | /** 185 | * Checks if `value` is a plain object, that is, an object created by the 186 | * `Object` constructor or one with a `[[Prototype]]` of `null`. 187 | * 188 | * @static 189 | * @memberOf _ 190 | * @since 0.8.0 191 | * @category Lang 192 | * @param {*} value The value to check. 193 | * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. 194 | * @example 195 | * 196 | * function Foo() { 197 | * this.a = 1; 198 | * } 199 | * 200 | * _.isPlainObject(new Foo); 201 | * // => false 202 | * 203 | * _.isPlainObject([1, 2, 3]); 204 | * // => false 205 | * 206 | * _.isPlainObject({ 'x': 0, 'y': 0 }); 207 | * // => true 208 | * 209 | * _.isPlainObject(Object.create(null)); 210 | * // => true 211 | */ 212 | function isPlainObject(value) { 213 | if (!isObjectLike(value) || objectToString.call(value) != objectTag) { 214 | return false; 215 | } 216 | var proto = getPrototype(value); 217 | if (proto === null) { 218 | return true; 219 | } 220 | var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; 221 | return (typeof Ctor == 'function' && 222 | Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); 223 | } 224 | 225 | module.exports = isPlainObject; 226 | 227 | },{"./_getPrototype":4,"./isObjectLike":6}],8:[function(require,module,exports){ 228 | (function (process){ 229 | if (typeof Map !== 'function' || (process && process.env && process.env.TEST_MAPORSIMILAR === 'true')) { 230 | module.exports = require('./similar'); 231 | } 232 | else { 233 | module.exports = Map; 234 | } 235 | }).call(this,require('_process')) 236 | 237 | },{"./similar":9,"_process":11}],9:[function(require,module,exports){ 238 | function Similar() { 239 | this.list = []; 240 | this.lastItem = undefined; 241 | this.size = 0; 242 | 243 | return this; 244 | } 245 | 246 | Similar.prototype.get = function(key) { 247 | var index; 248 | 249 | if (this.lastItem && this.isEqual(this.lastItem.key, key)) { 250 | return this.lastItem.val; 251 | } 252 | 253 | index = this.indexOf(key); 254 | if (index >= 0) { 255 | this.lastItem = this.list[index]; 256 | return this.list[index].val; 257 | } 258 | 259 | return undefined; 260 | }; 261 | 262 | Similar.prototype.set = function(key, val) { 263 | var index; 264 | 265 | if (this.lastItem && this.isEqual(this.lastItem.key, key)) { 266 | this.lastItem.val = val; 267 | return this; 268 | } 269 | 270 | index = this.indexOf(key); 271 | if (index >= 0) { 272 | this.lastItem = this.list[index]; 273 | this.list[index].val = val; 274 | return this; 275 | } 276 | 277 | this.lastItem = { key: key, val: val }; 278 | this.list.push(this.lastItem); 279 | this.size++; 280 | 281 | return this; 282 | }; 283 | 284 | Similar.prototype.delete = function(key) { 285 | var index; 286 | 287 | if (this.lastItem && this.isEqual(this.lastItem.key, key)) { 288 | this.lastItem = undefined; 289 | } 290 | 291 | index = this.indexOf(key); 292 | if (index >= 0) { 293 | this.size--; 294 | return this.list.splice(index, 1)[0]; 295 | } 296 | 297 | return undefined; 298 | }; 299 | 300 | 301 | // important that has() doesn't use get() in case an existing key has a falsy value, in which case has() would return false 302 | Similar.prototype.has = function(key) { 303 | var index; 304 | 305 | if (this.lastItem && this.isEqual(this.lastItem.key, key)) { 306 | return true; 307 | } 308 | 309 | index = this.indexOf(key); 310 | if (index >= 0) { 311 | this.lastItem = this.list[index]; 312 | return true; 313 | } 314 | 315 | return false; 316 | }; 317 | 318 | Similar.prototype.forEach = function(callback, thisArg) { 319 | var i; 320 | for (i = 0; i < this.size; i++) { 321 | callback.call(thisArg || this, this.list[i].val, this.list[i].key, this); 322 | } 323 | }; 324 | 325 | Similar.prototype.indexOf = function(key) { 326 | var i; 327 | for (i = 0; i < this.size; i++) { 328 | if (this.isEqual(this.list[i].key, key)) { 329 | return i; 330 | } 331 | } 332 | return -1; 333 | }; 334 | 335 | // check if the numbers are equal, or whether they are both precisely NaN (isNaN returns true for all non-numbers) 336 | Similar.prototype.isEqual = function(val1, val2) { 337 | return val1 === val2 || (val1 !== val1 && val2 !== val2); 338 | }; 339 | 340 | module.exports = Similar; 341 | },{}],10:[function(require,module,exports){ 342 | var MapOrSimilar = require('map-or-similar'); 343 | 344 | module.exports = function (limit) { 345 | var cache = new MapOrSimilar(), 346 | lru = []; 347 | 348 | return function (fn) { 349 | var memoizerific = function () { 350 | var currentCache = cache, 351 | newMap, 352 | fnResult, 353 | argsLengthMinusOne = arguments.length - 1, 354 | lruPath = Array(argsLengthMinusOne + 1), 355 | isMemoized = true, 356 | i; 357 | 358 | if ((memoizerific.numArgs || memoizerific.numArgs === 0) && memoizerific.numArgs !== argsLengthMinusOne + 1) { 359 | throw new Error('Memoizerific functions should always be called with the same number of arguments'); 360 | } 361 | 362 | // loop through each argument to traverse the map tree 363 | for (i = 0; i < argsLengthMinusOne; i++) { 364 | lruPath[i] = { 365 | cacheItem: currentCache, 366 | arg: arguments[i] 367 | }; 368 | 369 | // climb through the hierarchical map tree until the second-last argument has been found, or an argument is missing. 370 | // if all arguments up to the second-last have been found, this will potentially be a cache hit (determined below) 371 | if (currentCache.has(arguments[i])) { 372 | currentCache = currentCache.get(arguments[i]); 373 | continue; 374 | } 375 | 376 | isMemoized = false; 377 | 378 | // make maps until last value 379 | newMap = new MapOrSimilar(); 380 | currentCache.set(arguments[i], newMap); 381 | currentCache = newMap; 382 | } 383 | 384 | // we are at the last arg, check if it is really memoized 385 | if (isMemoized) { 386 | if (currentCache.has(arguments[argsLengthMinusOne])) { 387 | fnResult = currentCache.get(arguments[argsLengthMinusOne]); 388 | } 389 | else { 390 | isMemoized = false; 391 | } 392 | } 393 | 394 | if (!isMemoized) { 395 | fnResult = fn.apply(null, arguments); 396 | currentCache.set(arguments[argsLengthMinusOne], fnResult); 397 | } 398 | 399 | if (limit > 0) { 400 | lruPath[argsLengthMinusOne] = { 401 | cacheItem: currentCache, 402 | arg: arguments[argsLengthMinusOne] 403 | }; 404 | 405 | if (isMemoized) { 406 | moveToMostRecentLru(lru, lruPath); 407 | } 408 | else { 409 | lru.push(lruPath); 410 | } 411 | 412 | if (lru.length > limit) { 413 | removeCachedResult(lru.shift()); 414 | } 415 | } 416 | 417 | memoizerific.wasMemoized = isMemoized; 418 | memoizerific.numArgs = argsLengthMinusOne + 1; 419 | 420 | return fnResult; 421 | }; 422 | 423 | memoizerific.limit = limit; 424 | memoizerific.wasMemoized = false; 425 | memoizerific.cache = cache; 426 | memoizerific.lru = lru; 427 | 428 | return memoizerific; 429 | }; 430 | }; 431 | 432 | // move current args to most recent position 433 | function moveToMostRecentLru(lru, lruPath) { 434 | var lruLen = lru.length, 435 | lruPathLen = lruPath.length, 436 | isMatch, 437 | i, ii; 438 | 439 | for (i = 0; i < lruLen; i++) { 440 | isMatch = true; 441 | for (ii = 0; ii < lruPathLen; ii++) { 442 | if (!isEqual(lru[i][ii].arg, lruPath[ii].arg)) { 443 | isMatch = false; 444 | break; 445 | } 446 | } 447 | if (isMatch) { 448 | break; 449 | } 450 | } 451 | 452 | lru.push(lru.splice(i, 1)[0]); 453 | } 454 | 455 | // remove least recently used cache item and all dead branches 456 | function removeCachedResult(removedLru) { 457 | var removedLruLen = removedLru.length, 458 | currentLru = removedLru[removedLruLen - 1], 459 | tmp, 460 | i; 461 | 462 | currentLru.cacheItem.delete(currentLru.arg); 463 | 464 | // walk down the tree removing dead branches (size 0) along the way 465 | for (i = removedLruLen - 2; i >= 0; i--) { 466 | currentLru = removedLru[i]; 467 | tmp = currentLru.cacheItem.get(currentLru.arg); 468 | 469 | if (!tmp || !tmp.size) { 470 | currentLru.cacheItem.delete(currentLru.arg); 471 | } else { 472 | break; 473 | } 474 | } 475 | } 476 | 477 | // check if the numbers are equal, or whether they are both precisely NaN (isNaN returns true for all non-numbers) 478 | function isEqual(val1, val2) { 479 | return val1 === val2 || (val1 !== val1 && val2 !== val2); 480 | } 481 | },{"map-or-similar":8}],11:[function(require,module,exports){ 482 | // shim for using process in browser 483 | var process = module.exports = {}; 484 | 485 | // cached from whatever global is present so that test runners that stub it 486 | // don't break things. But we need to wrap it in a try catch in case it is 487 | // wrapped in strict mode code which doesn't define any globals. It's inside a 488 | // function because try/catches deoptimize in certain engines. 489 | 490 | var cachedSetTimeout; 491 | var cachedClearTimeout; 492 | 493 | function defaultSetTimout() { 494 | throw new Error('setTimeout has not been defined'); 495 | } 496 | function defaultClearTimeout () { 497 | throw new Error('clearTimeout has not been defined'); 498 | } 499 | (function () { 500 | try { 501 | if (typeof setTimeout === 'function') { 502 | cachedSetTimeout = setTimeout; 503 | } else { 504 | cachedSetTimeout = defaultSetTimout; 505 | } 506 | } catch (e) { 507 | cachedSetTimeout = defaultSetTimout; 508 | } 509 | try { 510 | if (typeof clearTimeout === 'function') { 511 | cachedClearTimeout = clearTimeout; 512 | } else { 513 | cachedClearTimeout = defaultClearTimeout; 514 | } 515 | } catch (e) { 516 | cachedClearTimeout = defaultClearTimeout; 517 | } 518 | } ()) 519 | function runTimeout(fun) { 520 | if (cachedSetTimeout === setTimeout) { 521 | //normal enviroments in sane situations 522 | return setTimeout(fun, 0); 523 | } 524 | // if setTimeout wasn't available but was latter defined 525 | if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { 526 | cachedSetTimeout = setTimeout; 527 | return setTimeout(fun, 0); 528 | } 529 | try { 530 | // when when somebody has screwed with setTimeout but no I.E. maddness 531 | return cachedSetTimeout(fun, 0); 532 | } catch(e){ 533 | try { 534 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 535 | return cachedSetTimeout.call(null, fun, 0); 536 | } catch(e){ 537 | // 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 538 | return cachedSetTimeout.call(this, fun, 0); 539 | } 540 | } 541 | 542 | 543 | } 544 | function runClearTimeout(marker) { 545 | if (cachedClearTimeout === clearTimeout) { 546 | //normal enviroments in sane situations 547 | return clearTimeout(marker); 548 | } 549 | // if clearTimeout wasn't available but was latter defined 550 | if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { 551 | cachedClearTimeout = clearTimeout; 552 | return clearTimeout(marker); 553 | } 554 | try { 555 | // when when somebody has screwed with setTimeout but no I.E. maddness 556 | return cachedClearTimeout(marker); 557 | } catch (e){ 558 | try { 559 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 560 | return cachedClearTimeout.call(null, marker); 561 | } catch (e){ 562 | // 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. 563 | // Some versions of I.E. have different rules for clearTimeout vs setTimeout 564 | return cachedClearTimeout.call(this, marker); 565 | } 566 | } 567 | 568 | 569 | 570 | } 571 | var queue = []; 572 | var draining = false; 573 | var currentQueue; 574 | var queueIndex = -1; 575 | 576 | function cleanUpNextTick() { 577 | if (!draining || !currentQueue) { 578 | return; 579 | } 580 | draining = false; 581 | if (currentQueue.length) { 582 | queue = currentQueue.concat(queue); 583 | } else { 584 | queueIndex = -1; 585 | } 586 | if (queue.length) { 587 | drainQueue(); 588 | } 589 | } 590 | 591 | function drainQueue() { 592 | if (draining) { 593 | return; 594 | } 595 | var timeout = runTimeout(cleanUpNextTick); 596 | draining = true; 597 | 598 | var len = queue.length; 599 | while(len) { 600 | currentQueue = queue; 601 | queue = []; 602 | while (++queueIndex < len) { 603 | if (currentQueue) { 604 | currentQueue[queueIndex].run(); 605 | } 606 | } 607 | queueIndex = -1; 608 | len = queue.length; 609 | } 610 | currentQueue = null; 611 | draining = false; 612 | runClearTimeout(timeout); 613 | } 614 | 615 | process.nextTick = function (fun) { 616 | var args = new Array(arguments.length - 1); 617 | if (arguments.length > 1) { 618 | for (var i = 1; i < arguments.length; i++) { 619 | args[i - 1] = arguments[i]; 620 | } 621 | } 622 | queue.push(new Item(fun, args)); 623 | if (queue.length === 1 && !draining) { 624 | runTimeout(drainQueue); 625 | } 626 | }; 627 | 628 | // v8 likes predictible objects 629 | function Item(fun, array) { 630 | this.fun = fun; 631 | this.array = array; 632 | } 633 | Item.prototype.run = function () { 634 | this.fun.apply(null, this.array); 635 | }; 636 | process.title = 'browser'; 637 | process.browser = true; 638 | process.env = {}; 639 | process.argv = []; 640 | process.version = ''; // empty string to avoid regexp issues 641 | process.versions = {}; 642 | 643 | function noop() {} 644 | 645 | process.on = noop; 646 | process.addListener = noop; 647 | process.once = noop; 648 | process.off = noop; 649 | process.removeListener = noop; 650 | process.removeAllListeners = noop; 651 | process.emit = noop; 652 | 653 | process.binding = function (name) { 654 | throw new Error('process.binding is not supported'); 655 | }; 656 | 657 | process.cwd = function () { return '/' }; 658 | process.chdir = function (dir) { 659 | throw new Error('process.chdir is not supported'); 660 | }; 661 | process.umask = function() { return 0; }; 662 | 663 | },{}],12:[function(require,module,exports){ 664 | 'use strict'; 665 | 666 | exports.__esModule = true; 667 | function createThunkMiddleware(extraArgument) { 668 | return function (_ref) { 669 | var dispatch = _ref.dispatch; 670 | var getState = _ref.getState; 671 | return function (next) { 672 | return function (action) { 673 | if (typeof action === 'function') { 674 | return action(dispatch, getState, extraArgument); 675 | } 676 | 677 | return next(action); 678 | }; 679 | }; 680 | }; 681 | } 682 | 683 | var thunk = createThunkMiddleware(); 684 | thunk.withExtraArgument = createThunkMiddleware; 685 | 686 | exports['default'] = thunk; 687 | },{}],13:[function(require,module,exports){ 688 | 'use strict'; 689 | 690 | exports.__esModule = true; 691 | 692 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 693 | 694 | exports['default'] = applyMiddleware; 695 | 696 | var _compose = require('./compose'); 697 | 698 | var _compose2 = _interopRequireDefault(_compose); 699 | 700 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 701 | 702 | /** 703 | * Creates a store enhancer that applies middleware to the dispatch method 704 | * of the Redux store. This is handy for a variety of tasks, such as expressing 705 | * asynchronous actions in a concise manner, or logging every action payload. 706 | * 707 | * See `redux-thunk` package as an example of the Redux middleware. 708 | * 709 | * Because middleware is potentially asynchronous, this should be the first 710 | * store enhancer in the composition chain. 711 | * 712 | * Note that each middleware will be given the `dispatch` and `getState` functions 713 | * as named arguments. 714 | * 715 | * @param {...Function} middlewares The middleware chain to be applied. 716 | * @returns {Function} A store enhancer applying the middleware. 717 | */ 718 | function applyMiddleware() { 719 | for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) { 720 | middlewares[_key] = arguments[_key]; 721 | } 722 | 723 | return function (createStore) { 724 | return function (reducer, preloadedState, enhancer) { 725 | var store = createStore(reducer, preloadedState, enhancer); 726 | var _dispatch = store.dispatch; 727 | var chain = []; 728 | 729 | var middlewareAPI = { 730 | getState: store.getState, 731 | dispatch: function dispatch(action) { 732 | return _dispatch(action); 733 | } 734 | }; 735 | chain = middlewares.map(function (middleware) { 736 | return middleware(middlewareAPI); 737 | }); 738 | _dispatch = _compose2['default'].apply(undefined, chain)(store.dispatch); 739 | 740 | return _extends({}, store, { 741 | dispatch: _dispatch 742 | }); 743 | }; 744 | }; 745 | } 746 | },{"./compose":16}],14:[function(require,module,exports){ 747 | 'use strict'; 748 | 749 | exports.__esModule = true; 750 | exports['default'] = bindActionCreators; 751 | function bindActionCreator(actionCreator, dispatch) { 752 | return function () { 753 | return dispatch(actionCreator.apply(undefined, arguments)); 754 | }; 755 | } 756 | 757 | /** 758 | * Turns an object whose values are action creators, into an object with the 759 | * same keys, but with every function wrapped into a `dispatch` call so they 760 | * may be invoked directly. This is just a convenience method, as you can call 761 | * `store.dispatch(MyActionCreators.doSomething())` yourself just fine. 762 | * 763 | * For convenience, you can also pass a single function as the first argument, 764 | * and get a function in return. 765 | * 766 | * @param {Function|Object} actionCreators An object whose values are action 767 | * creator functions. One handy way to obtain it is to use ES6 `import * as` 768 | * syntax. You may also pass a single function. 769 | * 770 | * @param {Function} dispatch The `dispatch` function available on your Redux 771 | * store. 772 | * 773 | * @returns {Function|Object} The object mimicking the original object, but with 774 | * every action creator wrapped into the `dispatch` call. If you passed a 775 | * function as `actionCreators`, the return value will also be a single 776 | * function. 777 | */ 778 | function bindActionCreators(actionCreators, dispatch) { 779 | if (typeof actionCreators === 'function') { 780 | return bindActionCreator(actionCreators, dispatch); 781 | } 782 | 783 | if (typeof actionCreators !== 'object' || actionCreators === null) { 784 | throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?'); 785 | } 786 | 787 | var keys = Object.keys(actionCreators); 788 | var boundActionCreators = {}; 789 | for (var i = 0; i < keys.length; i++) { 790 | var key = keys[i]; 791 | var actionCreator = actionCreators[key]; 792 | if (typeof actionCreator === 'function') { 793 | boundActionCreators[key] = bindActionCreator(actionCreator, dispatch); 794 | } 795 | } 796 | return boundActionCreators; 797 | } 798 | },{}],15:[function(require,module,exports){ 799 | 'use strict'; 800 | 801 | exports.__esModule = true; 802 | exports['default'] = combineReducers; 803 | 804 | var _createStore = require('./createStore'); 805 | 806 | var _isPlainObject = require('lodash/isPlainObject'); 807 | 808 | var _isPlainObject2 = _interopRequireDefault(_isPlainObject); 809 | 810 | var _warning = require('./utils/warning'); 811 | 812 | var _warning2 = _interopRequireDefault(_warning); 813 | 814 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 815 | 816 | function getUndefinedStateErrorMessage(key, action) { 817 | var actionType = action && action.type; 818 | var actionName = actionType && '"' + actionType.toString() + '"' || 'an action'; 819 | 820 | return 'Given action ' + actionName + ', reducer "' + key + '" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state.'; 821 | } 822 | 823 | function getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) { 824 | var reducerKeys = Object.keys(reducers); 825 | var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer'; 826 | 827 | if (reducerKeys.length === 0) { 828 | return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.'; 829 | } 830 | 831 | if (!(0, _isPlainObject2['default'])(inputState)) { 832 | return 'The ' + argumentName + ' has unexpected type of "' + {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"'); 833 | } 834 | 835 | var unexpectedKeys = Object.keys(inputState).filter(function (key) { 836 | return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key]; 837 | }); 838 | 839 | unexpectedKeys.forEach(function (key) { 840 | unexpectedKeyCache[key] = true; 841 | }); 842 | 843 | if (unexpectedKeys.length > 0) { 844 | return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.'); 845 | } 846 | } 847 | 848 | function assertReducerSanity(reducers) { 849 | Object.keys(reducers).forEach(function (key) { 850 | var reducer = reducers[key]; 851 | var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT }); 852 | 853 | if (typeof initialState === 'undefined') { 854 | throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); 855 | } 856 | 857 | var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.'); 858 | if (typeof reducer(undefined, { type: type }) === 'undefined') { 859 | throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); 860 | } 861 | }); 862 | } 863 | 864 | /** 865 | * Turns an object whose values are different reducer functions, into a single 866 | * reducer function. It will call every child reducer, and gather their results 867 | * into a single state object, whose keys correspond to the keys of the passed 868 | * reducer functions. 869 | * 870 | * @param {Object} reducers An object whose values correspond to different 871 | * reducer functions that need to be combined into one. One handy way to obtain 872 | * it is to use ES6 `import * as reducers` syntax. The reducers may never return 873 | * undefined for any action. Instead, they should return their initial state 874 | * if the state passed to them was undefined, and the current state for any 875 | * unrecognized action. 876 | * 877 | * @returns {Function} A reducer function that invokes every reducer inside the 878 | * passed object, and builds a state object with the same shape. 879 | */ 880 | function combineReducers(reducers) { 881 | var reducerKeys = Object.keys(reducers); 882 | var finalReducers = {}; 883 | for (var i = 0; i < reducerKeys.length; i++) { 884 | var key = reducerKeys[i]; 885 | 886 | if ("development" !== 'production') { 887 | if (typeof reducers[key] === 'undefined') { 888 | (0, _warning2['default'])('No reducer provided for key "' + key + '"'); 889 | } 890 | } 891 | 892 | if (typeof reducers[key] === 'function') { 893 | finalReducers[key] = reducers[key]; 894 | } 895 | } 896 | var finalReducerKeys = Object.keys(finalReducers); 897 | 898 | if ("development" !== 'production') { 899 | var unexpectedKeyCache = {}; 900 | } 901 | 902 | var sanityError; 903 | try { 904 | assertReducerSanity(finalReducers); 905 | } catch (e) { 906 | sanityError = e; 907 | } 908 | 909 | return function combination() { 910 | var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 911 | var action = arguments[1]; 912 | 913 | if (sanityError) { 914 | throw sanityError; 915 | } 916 | 917 | if ("development" !== 'production') { 918 | var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache); 919 | if (warningMessage) { 920 | (0, _warning2['default'])(warningMessage); 921 | } 922 | } 923 | 924 | var hasChanged = false; 925 | var nextState = {}; 926 | for (var i = 0; i < finalReducerKeys.length; i++) { 927 | var key = finalReducerKeys[i]; 928 | var reducer = finalReducers[key]; 929 | var previousStateForKey = state[key]; 930 | var nextStateForKey = reducer(previousStateForKey, action); 931 | if (typeof nextStateForKey === 'undefined') { 932 | var errorMessage = getUndefinedStateErrorMessage(key, action); 933 | throw new Error(errorMessage); 934 | } 935 | nextState[key] = nextStateForKey; 936 | hasChanged = hasChanged || nextStateForKey !== previousStateForKey; 937 | } 938 | return hasChanged ? nextState : state; 939 | }; 940 | } 941 | },{"./createStore":17,"./utils/warning":19,"lodash/isPlainObject":7}],16:[function(require,module,exports){ 942 | "use strict"; 943 | 944 | exports.__esModule = true; 945 | exports["default"] = compose; 946 | /** 947 | * Composes single-argument functions from right to left. The rightmost 948 | * function can take multiple arguments as it provides the signature for 949 | * the resulting composite function. 950 | * 951 | * @param {...Function} funcs The functions to compose. 952 | * @returns {Function} A function obtained by composing the argument functions 953 | * from right to left. For example, compose(f, g, h) is identical to doing 954 | * (...args) => f(g(h(...args))). 955 | */ 956 | 957 | function compose() { 958 | for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) { 959 | funcs[_key] = arguments[_key]; 960 | } 961 | 962 | if (funcs.length === 0) { 963 | return function (arg) { 964 | return arg; 965 | }; 966 | } 967 | 968 | if (funcs.length === 1) { 969 | return funcs[0]; 970 | } 971 | 972 | var last = funcs[funcs.length - 1]; 973 | var rest = funcs.slice(0, -1); 974 | return function () { 975 | return rest.reduceRight(function (composed, f) { 976 | return f(composed); 977 | }, last.apply(undefined, arguments)); 978 | }; 979 | } 980 | },{}],17:[function(require,module,exports){ 981 | 'use strict'; 982 | 983 | exports.__esModule = true; 984 | exports.ActionTypes = undefined; 985 | exports['default'] = createStore; 986 | 987 | var _isPlainObject = require('lodash/isPlainObject'); 988 | 989 | var _isPlainObject2 = _interopRequireDefault(_isPlainObject); 990 | 991 | var _symbolObservable = require('symbol-observable'); 992 | 993 | var _symbolObservable2 = _interopRequireDefault(_symbolObservable); 994 | 995 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 996 | 997 | /** 998 | * These are private action types reserved by Redux. 999 | * For any unknown actions, you must return the current state. 1000 | * If the current state is undefined, you must return the initial state. 1001 | * Do not reference these action types directly in your code. 1002 | */ 1003 | var ActionTypes = exports.ActionTypes = { 1004 | INIT: '@@redux/INIT' 1005 | }; 1006 | 1007 | /** 1008 | * Creates a Redux store that holds the state tree. 1009 | * The only way to change the data in the store is to call `dispatch()` on it. 1010 | * 1011 | * There should only be a single store in your app. To specify how different 1012 | * parts of the state tree respond to actions, you may combine several reducers 1013 | * into a single reducer function by using `combineReducers`. 1014 | * 1015 | * @param {Function} reducer A function that returns the next state tree, given 1016 | * the current state tree and the action to handle. 1017 | * 1018 | * @param {any} [preloadedState] The initial state. You may optionally specify it 1019 | * to hydrate the state from the server in universal apps, or to restore a 1020 | * previously serialized user session. 1021 | * If you use `combineReducers` to produce the root reducer function, this must be 1022 | * an object with the same shape as `combineReducers` keys. 1023 | * 1024 | * @param {Function} enhancer The store enhancer. You may optionally specify it 1025 | * to enhance the store with third-party capabilities such as middleware, 1026 | * time travel, persistence, etc. The only store enhancer that ships with Redux 1027 | * is `applyMiddleware()`. 1028 | * 1029 | * @returns {Store} A Redux store that lets you read the state, dispatch actions 1030 | * and subscribe to changes. 1031 | */ 1032 | function createStore(reducer, preloadedState, enhancer) { 1033 | var _ref2; 1034 | 1035 | if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { 1036 | enhancer = preloadedState; 1037 | preloadedState = undefined; 1038 | } 1039 | 1040 | if (typeof enhancer !== 'undefined') { 1041 | if (typeof enhancer !== 'function') { 1042 | throw new Error('Expected the enhancer to be a function.'); 1043 | } 1044 | 1045 | return enhancer(createStore)(reducer, preloadedState); 1046 | } 1047 | 1048 | if (typeof reducer !== 'function') { 1049 | throw new Error('Expected the reducer to be a function.'); 1050 | } 1051 | 1052 | var currentReducer = reducer; 1053 | var currentState = preloadedState; 1054 | var currentListeners = []; 1055 | var nextListeners = currentListeners; 1056 | var isDispatching = false; 1057 | 1058 | function ensureCanMutateNextListeners() { 1059 | if (nextListeners === currentListeners) { 1060 | nextListeners = currentListeners.slice(); 1061 | } 1062 | } 1063 | 1064 | /** 1065 | * Reads the state tree managed by the store. 1066 | * 1067 | * @returns {any} The current state tree of your application. 1068 | */ 1069 | function getState() { 1070 | return currentState; 1071 | } 1072 | 1073 | /** 1074 | * Adds a change listener. It will be called any time an action is dispatched, 1075 | * and some part of the state tree may potentially have changed. You may then 1076 | * call `getState()` to read the current state tree inside the callback. 1077 | * 1078 | * You may call `dispatch()` from a change listener, with the following 1079 | * caveats: 1080 | * 1081 | * 1. The subscriptions are snapshotted just before every `dispatch()` call. 1082 | * If you subscribe or unsubscribe while the listeners are being invoked, this 1083 | * will not have any effect on the `dispatch()` that is currently in progress. 1084 | * However, the next `dispatch()` call, whether nested or not, will use a more 1085 | * recent snapshot of the subscription list. 1086 | * 1087 | * 2. The listener should not expect to see all state changes, as the state 1088 | * might have been updated multiple times during a nested `dispatch()` before 1089 | * the listener is called. It is, however, guaranteed that all subscribers 1090 | * registered before the `dispatch()` started will be called with the latest 1091 | * state by the time it exits. 1092 | * 1093 | * @param {Function} listener A callback to be invoked on every dispatch. 1094 | * @returns {Function} A function to remove this change listener. 1095 | */ 1096 | function subscribe(listener) { 1097 | if (typeof listener !== 'function') { 1098 | throw new Error('Expected listener to be a function.'); 1099 | } 1100 | 1101 | var isSubscribed = true; 1102 | 1103 | ensureCanMutateNextListeners(); 1104 | nextListeners.push(listener); 1105 | 1106 | return function unsubscribe() { 1107 | if (!isSubscribed) { 1108 | return; 1109 | } 1110 | 1111 | isSubscribed = false; 1112 | 1113 | ensureCanMutateNextListeners(); 1114 | var index = nextListeners.indexOf(listener); 1115 | nextListeners.splice(index, 1); 1116 | }; 1117 | } 1118 | 1119 | /** 1120 | * Dispatches an action. It is the only way to trigger a state change. 1121 | * 1122 | * The `reducer` function, used to create the store, will be called with the 1123 | * current state tree and the given `action`. Its return value will 1124 | * be considered the **next** state of the tree, and the change listeners 1125 | * will be notified. 1126 | * 1127 | * The base implementation only supports plain object actions. If you want to 1128 | * dispatch a Promise, an Observable, a thunk, or something else, you need to 1129 | * wrap your store creating function into the corresponding middleware. For 1130 | * example, see the documentation for the `redux-thunk` package. Even the 1131 | * middleware will eventually dispatch plain object actions using this method. 1132 | * 1133 | * @param {Object} action A plain object representing “what changed”. It is 1134 | * a good idea to keep actions serializable so you can record and replay user 1135 | * sessions, or use the time travelling `redux-devtools`. An action must have 1136 | * a `type` property which may not be `undefined`. It is a good idea to use 1137 | * string constants for action types. 1138 | * 1139 | * @returns {Object} For convenience, the same action object you dispatched. 1140 | * 1141 | * Note that, if you use a custom middleware, it may wrap `dispatch()` to 1142 | * return something else (for example, a Promise you can await). 1143 | */ 1144 | function dispatch(action) { 1145 | if (!(0, _isPlainObject2['default'])(action)) { 1146 | throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.'); 1147 | } 1148 | 1149 | if (typeof action.type === 'undefined') { 1150 | throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?'); 1151 | } 1152 | 1153 | if (isDispatching) { 1154 | throw new Error('Reducers may not dispatch actions.'); 1155 | } 1156 | 1157 | try { 1158 | isDispatching = true; 1159 | currentState = currentReducer(currentState, action); 1160 | } finally { 1161 | isDispatching = false; 1162 | } 1163 | 1164 | var listeners = currentListeners = nextListeners; 1165 | for (var i = 0; i < listeners.length; i++) { 1166 | listeners[i](); 1167 | } 1168 | 1169 | return action; 1170 | } 1171 | 1172 | /** 1173 | * Replaces the reducer currently used by the store to calculate the state. 1174 | * 1175 | * You might need this if your app implements code splitting and you want to 1176 | * load some of the reducers dynamically. You might also need this if you 1177 | * implement a hot reloading mechanism for Redux. 1178 | * 1179 | * @param {Function} nextReducer The reducer for the store to use instead. 1180 | * @returns {void} 1181 | */ 1182 | function replaceReducer(nextReducer) { 1183 | if (typeof nextReducer !== 'function') { 1184 | throw new Error('Expected the nextReducer to be a function.'); 1185 | } 1186 | 1187 | currentReducer = nextReducer; 1188 | dispatch({ type: ActionTypes.INIT }); 1189 | } 1190 | 1191 | /** 1192 | * Interoperability point for observable/reactive libraries. 1193 | * @returns {observable} A minimal observable of state changes. 1194 | * For more information, see the observable proposal: 1195 | * https://github.com/zenparsing/es-observable 1196 | */ 1197 | function observable() { 1198 | var _ref; 1199 | 1200 | var outerSubscribe = subscribe; 1201 | return _ref = { 1202 | /** 1203 | * The minimal observable subscription method. 1204 | * @param {Object} observer Any object that can be used as an observer. 1205 | * The observer object should have a `next` method. 1206 | * @returns {subscription} An object with an `unsubscribe` method that can 1207 | * be used to unsubscribe the observable from the store, and prevent further 1208 | * emission of values from the observable. 1209 | */ 1210 | subscribe: function subscribe(observer) { 1211 | if (typeof observer !== 'object') { 1212 | throw new TypeError('Expected the observer to be an object.'); 1213 | } 1214 | 1215 | function observeState() { 1216 | if (observer.next) { 1217 | observer.next(getState()); 1218 | } 1219 | } 1220 | 1221 | observeState(); 1222 | var unsubscribe = outerSubscribe(observeState); 1223 | return { unsubscribe: unsubscribe }; 1224 | } 1225 | }, _ref[_symbolObservable2['default']] = function () { 1226 | return this; 1227 | }, _ref; 1228 | } 1229 | 1230 | // When a store is created, an "INIT" action is dispatched so that every 1231 | // reducer returns their initial state. This effectively populates 1232 | // the initial state tree. 1233 | dispatch({ type: ActionTypes.INIT }); 1234 | 1235 | return _ref2 = { 1236 | dispatch: dispatch, 1237 | subscribe: subscribe, 1238 | getState: getState, 1239 | replaceReducer: replaceReducer 1240 | }, _ref2[_symbolObservable2['default']] = observable, _ref2; 1241 | } 1242 | },{"lodash/isPlainObject":7,"symbol-observable":20}],18:[function(require,module,exports){ 1243 | 'use strict'; 1244 | 1245 | exports.__esModule = true; 1246 | exports.compose = exports.applyMiddleware = exports.bindActionCreators = exports.combineReducers = exports.createStore = undefined; 1247 | 1248 | var _createStore = require('./createStore'); 1249 | 1250 | var _createStore2 = _interopRequireDefault(_createStore); 1251 | 1252 | var _combineReducers = require('./combineReducers'); 1253 | 1254 | var _combineReducers2 = _interopRequireDefault(_combineReducers); 1255 | 1256 | var _bindActionCreators = require('./bindActionCreators'); 1257 | 1258 | var _bindActionCreators2 = _interopRequireDefault(_bindActionCreators); 1259 | 1260 | var _applyMiddleware = require('./applyMiddleware'); 1261 | 1262 | var _applyMiddleware2 = _interopRequireDefault(_applyMiddleware); 1263 | 1264 | var _compose = require('./compose'); 1265 | 1266 | var _compose2 = _interopRequireDefault(_compose); 1267 | 1268 | var _warning = require('./utils/warning'); 1269 | 1270 | var _warning2 = _interopRequireDefault(_warning); 1271 | 1272 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 1273 | 1274 | /* 1275 | * This is a dummy function to check if the function name has been altered by minification. 1276 | * If the function has been minified and NODE_ENV !== 'production', warn the user. 1277 | */ 1278 | function isCrushed() {} 1279 | 1280 | if ("development" !== 'production' && typeof isCrushed.name === 'string' && isCrushed.name !== 'isCrushed') { 1281 | (0, _warning2['default'])('You are currently using minified code outside of NODE_ENV === \'production\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.'); 1282 | } 1283 | 1284 | exports.createStore = _createStore2['default']; 1285 | exports.combineReducers = _combineReducers2['default']; 1286 | exports.bindActionCreators = _bindActionCreators2['default']; 1287 | exports.applyMiddleware = _applyMiddleware2['default']; 1288 | exports.compose = _compose2['default']; 1289 | },{"./applyMiddleware":13,"./bindActionCreators":14,"./combineReducers":15,"./compose":16,"./createStore":17,"./utils/warning":19}],19:[function(require,module,exports){ 1290 | 'use strict'; 1291 | 1292 | exports.__esModule = true; 1293 | exports['default'] = warning; 1294 | /** 1295 | * Prints a warning in the console if it exists. 1296 | * 1297 | * @param {String} message The warning message. 1298 | * @returns {void} 1299 | */ 1300 | function warning(message) { 1301 | /* eslint-disable no-console */ 1302 | if (typeof console !== 'undefined' && typeof console.error === 'function') { 1303 | console.error(message); 1304 | } 1305 | /* eslint-enable no-console */ 1306 | try { 1307 | // This error was thrown as a convenience so that if you enable 1308 | // "break on all exceptions" in your console, 1309 | // it would pause the execution at this line. 1310 | throw new Error(message); 1311 | /* eslint-disable no-empty */ 1312 | } catch (e) {} 1313 | /* eslint-enable no-empty */ 1314 | } 1315 | },{}],20:[function(require,module,exports){ 1316 | module.exports = require('./lib/index'); 1317 | 1318 | },{"./lib/index":21}],21:[function(require,module,exports){ 1319 | (function (global){ 1320 | 'use strict'; 1321 | 1322 | Object.defineProperty(exports, "__esModule", { 1323 | value: true 1324 | }); 1325 | 1326 | var _ponyfill = require('./ponyfill'); 1327 | 1328 | var _ponyfill2 = _interopRequireDefault(_ponyfill); 1329 | 1330 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 1331 | 1332 | var root; /* global window */ 1333 | 1334 | 1335 | if (typeof self !== 'undefined') { 1336 | root = self; 1337 | } else if (typeof window !== 'undefined') { 1338 | root = window; 1339 | } else if (typeof global !== 'undefined') { 1340 | root = global; 1341 | } else if (typeof module !== 'undefined') { 1342 | root = module; 1343 | } else { 1344 | root = Function('return this')(); 1345 | } 1346 | 1347 | var result = (0, _ponyfill2['default'])(root); 1348 | exports['default'] = result; 1349 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1350 | 1351 | },{"./ponyfill":22}],22:[function(require,module,exports){ 1352 | 'use strict'; 1353 | 1354 | Object.defineProperty(exports, "__esModule", { 1355 | value: true 1356 | }); 1357 | exports['default'] = symbolObservablePonyfill; 1358 | function symbolObservablePonyfill(root) { 1359 | var result; 1360 | var _Symbol = root.Symbol; 1361 | 1362 | if (typeof _Symbol === 'function') { 1363 | if (_Symbol.observable) { 1364 | result = _Symbol.observable; 1365 | } else { 1366 | result = _Symbol('observable'); 1367 | _Symbol.observable = result; 1368 | } 1369 | } else { 1370 | result = '@@observable'; 1371 | } 1372 | 1373 | return result; 1374 | }; 1375 | },{}],23:[function(require,module,exports){ 1376 | (function (global){ 1377 | 'use strict'; 1378 | 1379 | Object.defineProperty(exports, "__esModule", { 1380 | value: true 1381 | }); 1382 | 1383 | exports.default = function (data, domElement) { 1384 | var page = void 0; 1385 | 1386 | if (data.routing.url !== window.location.pathname + window.location.search) { 1387 | window.history.pushState(null, null, data.routing.url); 1388 | } 1389 | document.title = data.routing.title; 1390 | 1391 | switch (data.selectedPage) { 1392 | case _pages.ABOUT: 1393 | page = _react2.default.createElement(_pageAbout2.default, { 1394 | className: 'about-page', 1395 | siteHeader: data.siteHeader 1396 | }); 1397 | break; 1398 | 1399 | case _pages.ACCOUNT: 1400 | page = _react2.default.createElement(_pageAccount2.default, { 1401 | className: 'account-page', 1402 | siteHeader: data.siteHeader 1403 | }); 1404 | break; 1405 | 1406 | default: 1407 | page = _react2.default.createElement(_pageHome2.default, { 1408 | className: 'home-page', 1409 | siteHeader: data.siteHeader, 1410 | items: data.items 1411 | }); 1412 | break; 1413 | } 1414 | 1415 | (0, _reactDom.render)(page, domElement); 1416 | }; 1417 | 1418 | var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); 1419 | 1420 | var _react2 = _interopRequireDefault(_react); 1421 | 1422 | var _reactDom = (typeof window !== "undefined" ? window['ReactDOM'] : typeof global !== "undefined" ? global['ReactDOM'] : null); 1423 | 1424 | var _pages = require('./constants/pages'); 1425 | 1426 | var _pageHome = require('./page-home'); 1427 | 1428 | var _pageHome2 = _interopRequireDefault(_pageHome); 1429 | 1430 | var _pageAbout = require('./page-about'); 1431 | 1432 | var _pageAbout2 = _interopRequireDefault(_pageAbout); 1433 | 1434 | var _pageAccount = require('./page-account'); 1435 | 1436 | var _pageAccount2 = _interopRequireDefault(_pageAccount); 1437 | 1438 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1439 | 1440 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1441 | 1442 | },{"./constants/pages":24,"./page-about":26,"./page-account":27,"./page-home":28}],24:[function(require,module,exports){ 1443 | 'use strict'; 1444 | 1445 | Object.defineProperty(exports, "__esModule", { 1446 | value: true 1447 | }); 1448 | var HOME = exports.HOME = 'HOME'; 1449 | var ABOUT = exports.ABOUT = 'ABOUT'; 1450 | var ACCOUNT = exports.ACCOUNT = 'ACCOUNT'; 1451 | 1452 | },{}],25:[function(require,module,exports){ 1453 | (function (global){ 1454 | 'use strict'; 1455 | 1456 | Object.defineProperty(exports, "__esModule", { 1457 | value: true 1458 | }); 1459 | 1460 | var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); 1461 | 1462 | var _react2 = _interopRequireDefault(_react); 1463 | 1464 | var _classnames = require('classnames'); 1465 | 1466 | var _classnames2 = _interopRequireDefault(_classnames); 1467 | 1468 | var _linkReact = require('link-react'); 1469 | 1470 | var _linkReact2 = _interopRequireDefault(_linkReact); 1471 | 1472 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1473 | 1474 | var Items = function Items(p) { 1475 | return _react2.default.createElement( 1476 | 'ul', 1477 | { className: (0, _classnames2.default)('items', p.className) }, 1478 | !!p.items && p.items.map(function (item) { 1479 | return _react2.default.createElement( 1480 | 'li', 1481 | { key: item.id }, 1482 | _react2.default.createElement( 1483 | _linkReact2.default, 1484 | { 1485 | className: (0, _classnames2.default)({ selected: item.isSelected }), 1486 | href: item.href, 1487 | onClick: item.onClick }, 1488 | item.label 1489 | ) 1490 | ); 1491 | }) 1492 | ); 1493 | }; 1494 | 1495 | Items.propTypes = { 1496 | className: _react2.default.PropTypes.string, 1497 | items: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.shape({ 1498 | id: _react2.default.PropTypes.string, 1499 | label: _react2.default.PropTypes.string, 1500 | href: _react2.default.PropTypes.string, 1501 | isSelected: _react2.default.PropTypes.bool, 1502 | onClick: _react2.default.PropTypes.func 1503 | })) 1504 | }; 1505 | 1506 | exports.default = Items; 1507 | 1508 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1509 | 1510 | },{"classnames":1,"link-react":3}],26:[function(require,module,exports){ 1511 | (function (global){ 1512 | 'use strict'; 1513 | 1514 | Object.defineProperty(exports, "__esModule", { 1515 | value: true 1516 | }); 1517 | 1518 | var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); 1519 | 1520 | var _react2 = _interopRequireDefault(_react); 1521 | 1522 | var _classnames = require('classnames'); 1523 | 1524 | var _classnames2 = _interopRequireDefault(_classnames); 1525 | 1526 | var _siteHeader = require('./site-header'); 1527 | 1528 | var _siteHeader2 = _interopRequireDefault(_siteHeader); 1529 | 1530 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1531 | 1532 | var AboutPage = function AboutPage(p) { 1533 | return _react2.default.createElement( 1534 | 'div', 1535 | { className: (0, _classnames2.default)('page', p.className) }, 1536 | _react2.default.createElement(_siteHeader2.default, p.siteHeader), 1537 | _react2.default.createElement( 1538 | 'main', 1539 | { className: 'page-content' }, 1540 | _react2.default.createElement( 1541 | 'p', 1542 | null, 1543 | 'About' 1544 | ) 1545 | ) 1546 | ); 1547 | }; 1548 | 1549 | AboutPage.propTypes = { 1550 | className: _react2.default.PropTypes.string, 1551 | siteHeader: _react2.default.PropTypes.object 1552 | }; 1553 | 1554 | exports.default = AboutPage; 1555 | 1556 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1557 | 1558 | },{"./site-header":29,"classnames":1}],27:[function(require,module,exports){ 1559 | (function (global){ 1560 | 'use strict'; 1561 | 1562 | Object.defineProperty(exports, "__esModule", { 1563 | value: true 1564 | }); 1565 | 1566 | var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); 1567 | 1568 | var _react2 = _interopRequireDefault(_react); 1569 | 1570 | var _classnames = require('classnames'); 1571 | 1572 | var _classnames2 = _interopRequireDefault(_classnames); 1573 | 1574 | var _siteHeader = require('./site-header'); 1575 | 1576 | var _siteHeader2 = _interopRequireDefault(_siteHeader); 1577 | 1578 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1579 | 1580 | var AccountPage = function AccountPage(p) { 1581 | return _react2.default.createElement( 1582 | 'div', 1583 | { className: (0, _classnames2.default)('page', p.className) }, 1584 | _react2.default.createElement(_siteHeader2.default, p.siteHeader), 1585 | _react2.default.createElement( 1586 | 'main', 1587 | { className: 'page-content' }, 1588 | _react2.default.createElement( 1589 | 'p', 1590 | null, 1591 | 'Account' 1592 | ) 1593 | ) 1594 | ); 1595 | }; 1596 | 1597 | AccountPage.propTypes = { 1598 | className: _react2.default.PropTypes.string, 1599 | siteHeader: _react2.default.PropTypes.object 1600 | }; 1601 | 1602 | exports.default = AccountPage; 1603 | 1604 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1605 | 1606 | },{"./site-header":29,"classnames":1}],28:[function(require,module,exports){ 1607 | (function (global){ 1608 | 'use strict'; 1609 | 1610 | Object.defineProperty(exports, "__esModule", { 1611 | value: true 1612 | }); 1613 | 1614 | var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); 1615 | 1616 | var _react2 = _interopRequireDefault(_react); 1617 | 1618 | var _classnames = require('classnames'); 1619 | 1620 | var _classnames2 = _interopRequireDefault(_classnames); 1621 | 1622 | var _siteHeader = require('./site-header'); 1623 | 1624 | var _siteHeader2 = _interopRequireDefault(_siteHeader); 1625 | 1626 | var _items = require('./items'); 1627 | 1628 | var _items2 = _interopRequireDefault(_items); 1629 | 1630 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1631 | 1632 | var HomePage = function HomePage(p) { 1633 | return _react2.default.createElement( 1634 | 'div', 1635 | { className: (0, _classnames2.default)('page', p.className) }, 1636 | _react2.default.createElement(_siteHeader2.default, p.siteHeader), 1637 | _react2.default.createElement( 1638 | 'main', 1639 | { className: 'page-content' }, 1640 | _react2.default.createElement(_items2.default, { items: p.items }) 1641 | ), 1642 | _react2.default.createElement( 1643 | 'footer', 1644 | null, 1645 | _react2.default.createElement( 1646 | 'em', 1647 | null, 1648 | 'open the console while clicking' 1649 | ) 1650 | ) 1651 | ); 1652 | }; 1653 | 1654 | HomePage.propTypes = { 1655 | className: _react2.default.PropTypes.string, 1656 | siteHeader: _react2.default.PropTypes.object, 1657 | items: _react2.default.PropTypes.array 1658 | }; 1659 | 1660 | exports.default = HomePage; 1661 | 1662 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1663 | 1664 | },{"./items":25,"./site-header":29,"classnames":1}],29:[function(require,module,exports){ 1665 | (function (global){ 1666 | 'use strict'; 1667 | 1668 | Object.defineProperty(exports, "__esModule", { 1669 | value: true 1670 | }); 1671 | 1672 | var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); 1673 | 1674 | var _react2 = _interopRequireDefault(_react); 1675 | 1676 | var _classnames = require('classnames'); 1677 | 1678 | var _classnames2 = _interopRequireDefault(_classnames); 1679 | 1680 | var _linkReact = require('link-react'); 1681 | 1682 | var _linkReact2 = _interopRequireDefault(_linkReact); 1683 | 1684 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1685 | 1686 | var SiteHeader = function SiteHeader(p) { 1687 | return _react2.default.createElement( 1688 | 'header', 1689 | { className: (0, _classnames2.default)('site-header', p.className) }, 1690 | _react2.default.createElement( 1691 | 'nav', 1692 | null, 1693 | !!p.links && p.links.map(function (link) { 1694 | return _react2.default.createElement( 1695 | _linkReact2.default, 1696 | { 1697 | key: link.label, 1698 | className: (0, _classnames2.default)({ 'selected': link.isSelected }), 1699 | href: link.href, 1700 | onClick: link.onClick }, 1701 | link.label 1702 | ); 1703 | }) 1704 | ) 1705 | ); 1706 | }; 1707 | 1708 | SiteHeader.propTypes = { 1709 | className: _react2.default.PropTypes.string, 1710 | links: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.shape({ 1711 | label: _react2.default.PropTypes.string, 1712 | href: _react2.default.PropTypes.string, 1713 | isSelected: _react2.default.PropTypes.bool, 1714 | onClick: _react2.default.PropTypes.func 1715 | })) 1716 | }; 1717 | 1718 | exports.default = SiteHeader; 1719 | 1720 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1721 | 1722 | },{"classnames":1,"link-react":3}],30:[function(require,module,exports){ 1723 | 'use strict'; 1724 | 1725 | var _store = require('./state/store'); 1726 | 1727 | var _store2 = _interopRequireDefault(_store); 1728 | 1729 | var _app = require('./components/app'); 1730 | 1731 | var _app2 = _interopRequireDefault(_app); 1732 | 1733 | var _selectors = require('./selectors/selectors'); 1734 | 1735 | var _selectors2 = _interopRequireDefault(_selectors); 1736 | 1737 | var _updateUrl = require('./state/site/actions/update-url'); 1738 | 1739 | var _updateUrl2 = _interopRequireDefault(_updateUrl); 1740 | 1741 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1742 | 1743 | // import selectors from './selectors'; 1744 | 1745 | // debug stuff 1746 | Object.defineProperty(window, "state", { get: _store2.default.getState }); 1747 | window.selectors = _selectors2.default; 1748 | 1749 | console.log('********************************************* \n DEVELOPMENT MODE \n window.state available \n window.selectors available \n ********************************************* \n'); 1750 | 1751 | // subscribe to state changes and re-render view on every change 1752 | var domElement = document.getElementById('app'); 1753 | _store2.default.subscribe(function () { 1754 | return (0, _app2.default)(_selectors2.default, domElement); 1755 | }); 1756 | 1757 | // listen for back button, forward button, etc 1758 | window.onpopstate = function (e) { 1759 | _store2.default.dispatch((0, _updateUrl2.default)(window.location.pathname + window.location.search)); 1760 | }; 1761 | 1762 | // read the url and navigate to the right page 1763 | _store2.default.dispatch((0, _updateUrl2.default)(window.location.pathname + window.location.search)); 1764 | 1765 | },{"./components/app":23,"./selectors/selectors":32,"./state/site/actions/update-url":38,"./state/store":43}],31:[function(require,module,exports){ 1766 | 'use strict'; 1767 | 1768 | Object.defineProperty(exports, "__esModule", { 1769 | value: true 1770 | }); 1771 | exports.selectItem = exports.selectItems = undefined; 1772 | 1773 | exports.default = function () { 1774 | var _store$getState = _store2.default.getState(); 1775 | 1776 | var items = _store$getState.items; 1777 | var selectedItemID = _store$getState.selectedItemID; 1778 | 1779 | return selectItems(items, selectedItemID); 1780 | }; 1781 | 1782 | var _memoizerific = require('memoizerific'); 1783 | 1784 | var _memoizerific2 = _interopRequireDefault(_memoizerific); 1785 | 1786 | var _store = require('../../state/store'); 1787 | 1788 | var _store2 = _interopRequireDefault(_store); 1789 | 1790 | var _paths = require('../../state/site/constants/paths'); 1791 | 1792 | var _sections = require('../../state/site/constants/sections'); 1793 | 1794 | var _updateUrl = require('../../state/site/actions/update-url'); 1795 | 1796 | var _updateUrl2 = _interopRequireDefault(_updateUrl); 1797 | 1798 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1799 | 1800 | var selectItems = exports.selectItems = (0, _memoizerific2.default)(10)(function (items, selectedItemID) { 1801 | return Object.keys(items).map(function (key) { 1802 | return selectItem(key, items[key].name, _paths.SECTIONS_PATHS[_sections.ITEM] + '/' + key, selectedItemID === key); 1803 | }); 1804 | }); 1805 | 1806 | var selectItem = exports.selectItem = (0, _memoizerific2.default)(20)(function (id, label, href, isSelected) { 1807 | return { 1808 | id: id, 1809 | label: label, 1810 | href: href, 1811 | isSelected: isSelected, 1812 | onClick: function onClick() { 1813 | return _store2.default.dispatch((0, _updateUrl2.default)(href)); 1814 | } 1815 | }; 1816 | }); 1817 | 1818 | },{"../../state/site/actions/update-url":38,"../../state/site/constants/paths":39,"../../state/site/constants/sections":40,"../../state/store":43,"memoizerific":10}],32:[function(require,module,exports){ 1819 | 'use strict'; 1820 | 1821 | Object.defineProperty(exports, "__esModule", { 1822 | value: true 1823 | }); 1824 | 1825 | var _combineSelectors = require('combine-selectors'); 1826 | 1827 | var _combineSelectors2 = _interopRequireDefault(_combineSelectors); 1828 | 1829 | var _store = require('../state/store'); 1830 | 1831 | var _store2 = _interopRequireDefault(_store); 1832 | 1833 | var _selectedPage = require('./site/selected-page'); 1834 | 1835 | var _selectedPage2 = _interopRequireDefault(_selectedPage); 1836 | 1837 | var _routing = require('./site/routing'); 1838 | 1839 | var _routing2 = _interopRequireDefault(_routing); 1840 | 1841 | var _siteHeader = require('./site/site-header'); 1842 | 1843 | var _siteHeader2 = _interopRequireDefault(_siteHeader); 1844 | 1845 | var _items = require('./items/items'); 1846 | 1847 | var _items2 = _interopRequireDefault(_items); 1848 | 1849 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1850 | 1851 | var selectors = { 1852 | selectedPage: _selectedPage2.default, 1853 | routing: _routing2.default, 1854 | siteHeader: _siteHeader2.default, 1855 | items: _items2.default 1856 | }; 1857 | 1858 | exports.default = (0, _combineSelectors2.default)(selectors, _store2.default.getState); 1859 | 1860 | },{"../state/store":43,"./items/items":31,"./site/routing":33,"./site/selected-page":34,"./site/site-header":35,"combine-selectors":2}],33:[function(require,module,exports){ 1861 | 'use strict'; 1862 | 1863 | Object.defineProperty(exports, "__esModule", { 1864 | value: true 1865 | }); 1866 | exports.selectTitle = exports.selectRouting = undefined; 1867 | 1868 | exports.default = function () { 1869 | var _store$getState = _store2.default.getState(); 1870 | 1871 | var url = _store$getState.url; 1872 | var selectedSection = _store$getState.selectedSection; 1873 | 1874 | return selectRouting(url, selectedSection); 1875 | }; 1876 | 1877 | var _memoizerific = require('memoizerific'); 1878 | 1879 | var _memoizerific2 = _interopRequireDefault(_memoizerific); 1880 | 1881 | var _store = require('../../state/store'); 1882 | 1883 | var _store2 = _interopRequireDefault(_store); 1884 | 1885 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1886 | 1887 | var selectRouting = exports.selectRouting = (0, _memoizerific2.default)(1)(function (url, selectedSection) { 1888 | return { 1889 | url: url, 1890 | title: selectTitle(selectedSection) 1891 | }; 1892 | }); 1893 | 1894 | var selectTitle = exports.selectTitle = (0, _memoizerific2.default)(1)(function (selectedSection) { 1895 | return selectedSection + ' - State-Driven Routing'; 1896 | }); 1897 | 1898 | },{"../../state/store":43,"memoizerific":10}],34:[function(require,module,exports){ 1899 | 'use strict'; 1900 | 1901 | Object.defineProperty(exports, "__esModule", { 1902 | value: true 1903 | }); 1904 | exports.selectSelectedPage = undefined; 1905 | 1906 | exports.default = function () { 1907 | var _store$getState = _store2.default.getState(); 1908 | 1909 | var selectedSection = _store$getState.selectedSection; 1910 | 1911 | return selectSelectedPage(selectedSection); 1912 | }; 1913 | 1914 | var _memoizerific = require('memoizerific'); 1915 | 1916 | var _memoizerific2 = _interopRequireDefault(_memoizerific); 1917 | 1918 | var _store = require('../../state/store'); 1919 | 1920 | var _store2 = _interopRequireDefault(_store); 1921 | 1922 | var _pages = require('../../components/constants/pages'); 1923 | 1924 | var PAGES = _interopRequireWildcard(_pages); 1925 | 1926 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 1927 | 1928 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1929 | 1930 | var selectSelectedPage = exports.selectSelectedPage = (0, _memoizerific2.default)(1)(function (selectedSection) { 1931 | return PAGES[selectedSection]; 1932 | }); 1933 | 1934 | },{"../../components/constants/pages":24,"../../state/store":43,"memoizerific":10}],35:[function(require,module,exports){ 1935 | 'use strict'; 1936 | 1937 | Object.defineProperty(exports, "__esModule", { 1938 | value: true 1939 | }); 1940 | exports.selectSiteHeaderLink = exports.selectSiteHeader = undefined; 1941 | 1942 | exports.default = function () { 1943 | var _store$getState = _store2.default.getState(); 1944 | 1945 | var selectedSection = _store$getState.selectedSection; 1946 | 1947 | return selectSiteHeader(selectedSection); 1948 | }; 1949 | 1950 | var _memoizerific = require('memoizerific'); 1951 | 1952 | var _memoizerific2 = _interopRequireDefault(_memoizerific); 1953 | 1954 | var _store = require('../../state/store'); 1955 | 1956 | var _store2 = _interopRequireDefault(_store); 1957 | 1958 | var _paths = require('../../state/site/constants/paths'); 1959 | 1960 | var _sections = require('../../state/site/constants/sections'); 1961 | 1962 | var _updateUrl = require('../../state/site/actions/update-url'); 1963 | 1964 | var _updateUrl2 = _interopRequireDefault(_updateUrl); 1965 | 1966 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1967 | 1968 | var selectSiteHeader = exports.selectSiteHeader = (0, _memoizerific2.default)(10)(function (selectedSection) { 1969 | return { 1970 | links: [selectSiteHeaderLink('Home', _paths.SECTIONS_PATHS[_sections.HOME], selectedSection === _sections.HOME), selectSiteHeaderLink('About', _paths.SECTIONS_PATHS[_sections.ABOUT], selectedSection === _sections.ABOUT), selectSiteHeaderLink('Account', _paths.SECTIONS_PATHS[_sections.ACCOUNT], selectedSection === _sections.ACCOUNT)] 1971 | }; 1972 | }); 1973 | 1974 | var selectSiteHeaderLink = exports.selectSiteHeaderLink = (0, _memoizerific2.default)(20)(function (label, href, isSelected) { 1975 | return { 1976 | label: label, 1977 | href: href, 1978 | isSelected: isSelected, 1979 | onClick: function onClick() { 1980 | return _store2.default.dispatch((0, _updateUrl2.default)(href)); 1981 | } 1982 | }; 1983 | }); 1984 | 1985 | },{"../../state/site/actions/update-url":38,"../../state/site/constants/paths":39,"../../state/site/constants/sections":40,"../../state/store":43,"memoizerific":10}],36:[function(require,module,exports){ 1986 | 'use strict'; 1987 | 1988 | Object.defineProperty(exports, "__esModule", { 1989 | value: true 1990 | }); 1991 | 1992 | exports.default = function () { 1993 | var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultItems; 1994 | var action = arguments[1]; 1995 | 1996 | switch (action.type) { 1997 | 1998 | default: 1999 | return items; 2000 | } 2001 | }; 2002 | 2003 | var _updateUrl = require('../../site/actions/update-url'); 2004 | 2005 | var _sections = require('../../site/constants/sections'); 2006 | 2007 | var _paths = require('../../site/constants/paths'); 2008 | 2009 | var defaultItems = { 2010 | 'id1': { 2011 | name: 'Item #1' 2012 | }, 2013 | 'id2': { 2014 | name: 'Item #2' 2015 | }, 2016 | 'id3': { 2017 | name: 'Item #3' 2018 | } 2019 | }; 2020 | 2021 | },{"../../site/actions/update-url":38,"../../site/constants/paths":39,"../../site/constants/sections":40}],37:[function(require,module,exports){ 2022 | 'use strict'; 2023 | 2024 | Object.defineProperty(exports, "__esModule", { 2025 | value: true 2026 | }); 2027 | 2028 | exports.default = function () { 2029 | var selectedItem = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; 2030 | var action = arguments[1]; 2031 | 2032 | switch (action.type) { 2033 | 2034 | case _updateUrl.UPDATE_URL: 2035 | var parsedItemID = action.parsedURL.path.replace(_paths.SECTIONS_PATHS.ITEM + '/', ''); 2036 | return parsedItemID !== action.parsedURL.path ? parsedItemID || null : null; 2037 | 2038 | default: 2039 | return selectedItem; 2040 | } 2041 | }; 2042 | 2043 | var _updateUrl = require('../../site/actions/update-url'); 2044 | 2045 | var _paths = require('../../site/constants/paths'); 2046 | 2047 | },{"../../site/actions/update-url":38,"../../site/constants/paths":39}],38:[function(require,module,exports){ 2048 | 'use strict'; 2049 | 2050 | Object.defineProperty(exports, "__esModule", { 2051 | value: true 2052 | }); 2053 | 2054 | exports.default = function (newURL) { 2055 | return function (dispatch, getState) { 2056 | var _getState = getState(); 2057 | 2058 | var url = _getState.url; 2059 | 2060 | if (newURL === url) { 2061 | return; 2062 | } 2063 | 2064 | dispatch({ 2065 | type: UPDATE_URL, 2066 | parsedURL: parseURL(newURL) 2067 | }); 2068 | }; 2069 | }; 2070 | 2071 | var UPDATE_URL = exports.UPDATE_URL = 'UPDATE_URL'; 2072 | 2073 | function parseURL(url) { 2074 | var splitURL = url.split('?'); 2075 | var path = splitURL[0].replace(/[/]+/g, '/'); 2076 | var searchParams = {}; 2077 | 2078 | // make sure there isn't a trailing slash, except for home being a single slash: '/' 2079 | if (path.length >= 2) { 2080 | path = path.replace(/\/$/, ''); 2081 | } else { 2082 | path = '/'; 2083 | } 2084 | 2085 | if (splitURL.length >= 2) { 2086 | searchParams = parseSearchParams(splitURL[1]); 2087 | } 2088 | 2089 | var finalURL = path + joinSearchParams(searchParams); 2090 | 2091 | return { 2092 | path: path, 2093 | searchParams: searchParams, 2094 | url: finalURL 2095 | }; 2096 | } 2097 | 2098 | function parseSearchParams(searchString) { 2099 | var pairSplit = void 0; 2100 | return (searchString || '').replace(/^\?/, '').split('&').reduce(function (p, pair) { 2101 | pairSplit = pair.split('='); 2102 | if (pairSplit.length >= 1 && pairSplit[0].length >= 1) { 2103 | p[decodeURIComponent(pairSplit[0])] = decodeURIComponent(pairSplit[1]) || ''; 2104 | } 2105 | return p; 2106 | }, {}); 2107 | } 2108 | 2109 | function joinSearchParams(searchParams) { 2110 | var searchString = Object.keys(searchParams).reduce(function (p, paramKey) { 2111 | return p += '&' + paramKey + '=' + searchParams[paramKey]; 2112 | }, '?'); 2113 | 2114 | if (searchString.length <= 1) { 2115 | return ''; 2116 | } 2117 | 2118 | return searchString.replace('?&', '?'); 2119 | } 2120 | 2121 | },{}],39:[function(require,module,exports){ 2122 | 'use strict'; 2123 | 2124 | Object.defineProperty(exports, "__esModule", { 2125 | value: true 2126 | }); 2127 | exports.DEFAULT_PATH = exports.SECTIONS_PATHS = exports.PATHS_SECTIONS = undefined; 2128 | 2129 | var _sections = require('../../site/constants/sections'); 2130 | 2131 | var PATHS_SECTIONS = exports.PATHS_SECTIONS = { 2132 | '/': _sections.HOME, 2133 | '/about': _sections.ABOUT, 2134 | '/account': _sections.ACCOUNT, 2135 | '/item': _sections.ITEM 2136 | }; 2137 | var SECTIONS_PATHS = exports.SECTIONS_PATHS = Object.keys(PATHS_SECTIONS).reduce(function (p, key) { 2138 | p[PATHS_SECTIONS[key]] = key;return p; 2139 | }, {}); 2140 | 2141 | var DEFAULT_PATH = exports.DEFAULT_PATH = '/'; 2142 | 2143 | },{"../../site/constants/sections":40}],40:[function(require,module,exports){ 2144 | 'use strict'; 2145 | 2146 | Object.defineProperty(exports, "__esModule", { 2147 | value: true 2148 | }); 2149 | var HOME = exports.HOME = 'HOME'; 2150 | var ABOUT = exports.ABOUT = 'ABOUT'; 2151 | var ACCOUNT = exports.ACCOUNT = 'ACCOUNT'; 2152 | var ITEM = exports.ITEM = 'ITEM'; 2153 | 2154 | },{}],41:[function(require,module,exports){ 2155 | 'use strict'; 2156 | 2157 | Object.defineProperty(exports, "__esModule", { 2158 | value: true 2159 | }); 2160 | 2161 | exports.default = function () { 2162 | var selectedSection = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _sections.HOME; 2163 | var action = arguments[1]; 2164 | 2165 | switch (action.type) { 2166 | 2167 | case _updateUrl.UPDATE_URL: 2168 | return _paths.PATHS_SECTIONS[action.parsedURL.path] || _sections.HOME; 2169 | 2170 | default: 2171 | return selectedSection; 2172 | } 2173 | }; 2174 | 2175 | var _updateUrl = require('../../site/actions/update-url'); 2176 | 2177 | var _sections = require('../../site/constants/sections'); 2178 | 2179 | var _paths = require('../../site/constants/paths'); 2180 | 2181 | },{"../../site/actions/update-url":38,"../../site/constants/paths":39,"../../site/constants/sections":40}],42:[function(require,module,exports){ 2182 | 'use strict'; 2183 | 2184 | Object.defineProperty(exports, "__esModule", { 2185 | value: true 2186 | }); 2187 | 2188 | exports.default = function () { 2189 | var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; 2190 | var action = arguments[1]; 2191 | 2192 | switch (action.type) { 2193 | 2194 | case _updateUrl.UPDATE_URL: 2195 | return action.parsedURL.url; 2196 | 2197 | default: 2198 | return url; 2199 | } 2200 | }; 2201 | 2202 | var _updateUrl = require('../../site/actions/update-url'); 2203 | 2204 | var _paths = require('../../site/constants/paths'); 2205 | 2206 | },{"../../site/actions/update-url":38,"../../site/constants/paths":39}],43:[function(require,module,exports){ 2207 | (function (process){ 2208 | 'use strict'; 2209 | 2210 | Object.defineProperty(exports, "__esModule", { 2211 | value: true 2212 | }); 2213 | 2214 | var _redux = require('redux'); 2215 | 2216 | var _reduxThunk = require('redux-thunk'); 2217 | 2218 | var _reduxThunk2 = _interopRequireDefault(_reduxThunk); 2219 | 2220 | var _url = require('./site/reducers/url'); 2221 | 2222 | var _url2 = _interopRequireDefault(_url); 2223 | 2224 | var _selectedSection = require('./site/reducers/selected-section'); 2225 | 2226 | var _selectedSection2 = _interopRequireDefault(_selectedSection); 2227 | 2228 | var _items = require('./items/reducers/items'); 2229 | 2230 | var _items2 = _interopRequireDefault(_items); 2231 | 2232 | var _selectedItemId = require('./items/reducers/selected-item-id'); 2233 | 2234 | var _selectedItemId2 = _interopRequireDefault(_selectedItemId); 2235 | 2236 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 2237 | 2238 | // reducers 2239 | var reducers = { 2240 | url: _url2.default, 2241 | selectedSection: _selectedSection2.default, 2242 | items: _items2.default, 2243 | selectedItemID: _selectedItemId2.default 2244 | }; 2245 | 2246 | // console log middleware that logs all actions to console 2247 | var consoleLog = function consoleLog(store) { 2248 | return function (next) { 2249 | return function (action) { 2250 | if (typeof action !== 'function') { 2251 | console.log(action); 2252 | } 2253 | return next(action); 2254 | }; 2255 | }; 2256 | }; 2257 | 2258 | // conditionally set middleware based on dev or prod env 2259 | var middleWare = void 0; 2260 | if (process.env.NODE_ENV !== 'production') { 2261 | middleWare = (0, _redux.applyMiddleware)(consoleLog, _reduxThunk2.default); 2262 | } else { 2263 | middleWare = (0, _redux.applyMiddleware)(_reduxThunk2.default); 2264 | } 2265 | 2266 | // create store 2267 | exports.default = (0, _redux.createStore)((0, _redux.combineReducers)(reducers), middleWare); 2268 | 2269 | }).call(this,require('_process')) 2270 | 2271 | },{"./items/reducers/items":36,"./items/reducers/selected-item-id":37,"./site/reducers/selected-section":41,"./site/reducers/url":42,"_process":11,"redux":18,"redux-thunk":12}]},{},[30]) 2272 | //# sourceMappingURL=build.js.map 2273 | -------------------------------------------------------------------------------- /build/1.0.0/build.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [ 4 | "node_modules/browser-pack/_prelude.js", 5 | "node_modules/classnames/index.js", 6 | "node_modules/combine-selectors/src/combine-selectors.js", 7 | "node_modules/link-react/link.jsx", 8 | "node_modules/lodash/_getPrototype.js", 9 | "node_modules/lodash/_overArg.js", 10 | "node_modules/lodash/isObjectLike.js", 11 | "node_modules/lodash/isPlainObject.js", 12 | "node_modules/map-or-similar/src/map-or-similar.js", 13 | "node_modules/map-or-similar/src/similar.js", 14 | "node_modules/memoizerific/src/memoizerific.js", 15 | "node_modules/process/browser.js", 16 | "node_modules/redux-thunk/lib/index.js", 17 | "node_modules/redux/lib/applyMiddleware.js", 18 | "node_modules/redux/lib/bindActionCreators.js", 19 | "node_modules/redux/lib/combineReducers.js", 20 | "node_modules/redux/lib/compose.js", 21 | "node_modules/redux/lib/createStore.js", 22 | "node_modules/redux/lib/index.js", 23 | "node_modules/redux/lib/utils/warning.js", 24 | "node_modules/symbol-observable/index.js", 25 | "node_modules/symbol-observable/lib/index.js", 26 | "node_modules/symbol-observable/lib/ponyfill.js", 27 | "src/components/app.jsx", 28 | "src/components/constants/pages.js", 29 | "src/components/items.jsx", 30 | "src/components/page-about.jsx", 31 | "src/components/page-account.jsx", 32 | "src/components/page-home.jsx", 33 | "src/components/site-header.jsx", 34 | "src/index.js", 35 | "src/selectors/items/items.js", 36 | "src/selectors/selectors.js", 37 | "src/selectors/site/routing.js", 38 | "src/selectors/site/selected-page.js", 39 | "src/selectors/site/site-header.js", 40 | "src/state/items/reducers/items.js", 41 | "src/state/items/reducers/selected-item-id.js", 42 | "src/state/site/actions/update-url.js", 43 | "src/state/site/constants/paths.js", 44 | "src/state/site/constants/sections.js", 45 | "src/state/site/reducers/selected-section.js", 46 | "src/state/site/reducers/url.js", 47 | "src/state/store.js" 48 | ], 49 | "names": [], 50 | "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACpEA;AACA;AACA;AACA;AACA;AACA;;;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;kBCbe,UAAU,IAAV,EAAgB,UAAhB,EAA4B;AAC1C,KAAI,aAAJ;;AAEA,KAAI,KAAK,OAAL,CAAa,GAAb,KAAqB,OAAO,QAAP,CAAgB,QAAhB,GAA2B,OAAO,QAAP,CAAgB,MAApE,EAA4E;AAC3E,SAAO,OAAP,CAAe,SAAf,CAAyB,IAAzB,EAA+B,IAA/B,EAAqC,KAAK,OAAL,CAAa,GAAlD;AACA;AACD,UAAS,KAAT,GAAiB,KAAK,OAAL,CAAa,KAA9B;;AAEA,SAAO,KAAK,YAAZ;AACA;AACC,UAAO;AACN,eAAU,YADJ;AAEN,gBAAa,KAAK;AAFZ,KAAP;AAIA;;AAED;AACC,UAAO;AACN,eAAU,cADJ;AAEN,gBAAa,KAAK;AAFZ,KAAP;AAIA;;AA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", 51 | "file": "generated.js", 52 | "sourceRoot": "", 53 | "sourcesContent": [ 54 | "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o {\n\t\tObject.defineProperty(p, selectorKey, {\n\t\t\tget: function() { return selectors[selectorKey](getState(), ...args) },\n\t\t\tenumerable: true\n\t\t});\n\t\treturn p;\n\t}, {});\n};\n", 57 | "module.exports = React.createClass({\n\tpropTypes: {\n\t\tclassName: React.PropTypes.string,\n\t\thref: React.PropTypes.string,\n\t\ttarget: React.PropTypes.string,\n\t\tonClick: React.PropTypes.func\n\t},\n\n\thandleClick: function(e) {\n\n\t\t// if target is set (e.g. to \"_blank\"), let the browser handle it\n\t\tif (this.props.target || (this.props.href && this.props.href.indexOf('mailto:') === 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if keyboard click, or not a left click, let the browser handle it\n\t\tif (!e.button === 0 || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) {\n\t\t\treturn;\n\t\t}\n\n\t\t// otherwise intercept the browser\n\t\te.preventDefault();\n\n\t\t// if a handler was provided, run it\n\t\tif (this.props.onClick) {\n\t\t\tthis.props.onClick(this.props.href);\n\t\t}\n\t},\n\n\trender: function() {\n\t\treturn React.createElement('a', Object.assign({}, this.props, {\n\t\t\thref: this.props.href,\n\t\t\tclassName: 'link ' + this.props.className,\n\t\t\tonClick: this.handleClick\n\t\t}));\n\t}\n});\n", 58 | "var overArg = require('./_overArg');\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nmodule.exports = getPrototype;\n", 59 | "/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nmodule.exports = overArg;\n", 60 | "/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n", 61 | "var getPrototype = require('./_getPrototype'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n if (!isObjectLike(value) || objectToString.call(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return (typeof Ctor == 'function' &&\n Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);\n}\n\nmodule.exports = isPlainObject;\n", 62 | "if (typeof Map !== 'function' || (process && process.env && process.env.TEST_MAPORSIMILAR === 'true')) {\n\tmodule.exports = require('./similar');\n}\nelse {\n\tmodule.exports = Map;\n}", 63 | "function Similar() {\n\tthis.list = [];\n\tthis.lastItem = undefined;\n\tthis.size = 0;\n\n\treturn this;\n}\n\nSimilar.prototype.get = function(key) {\n\tvar index;\n\n\tif (this.lastItem && this.isEqual(this.lastItem.key, key)) {\n\t\treturn this.lastItem.val;\n\t}\n\n\tindex = this.indexOf(key);\n\tif (index >= 0) {\n\t\tthis.lastItem = this.list[index];\n\t\treturn this.list[index].val;\n\t}\n\n\treturn undefined;\n};\n\nSimilar.prototype.set = function(key, val) {\n\tvar index;\n\n\tif (this.lastItem && this.isEqual(this.lastItem.key, key)) {\n\t\tthis.lastItem.val = val;\n\t\treturn this;\n\t}\n\n\tindex = this.indexOf(key);\n\tif (index >= 0) {\n\t\tthis.lastItem = this.list[index];\n\t\tthis.list[index].val = val;\n\t\treturn this;\n\t}\n\n\tthis.lastItem = { key: key, val: val };\n\tthis.list.push(this.lastItem);\n\tthis.size++;\n\n\treturn this;\n};\n\nSimilar.prototype.delete = function(key) {\n\tvar index;\n\n\tif (this.lastItem && this.isEqual(this.lastItem.key, key)) {\n\t\tthis.lastItem = undefined;\n\t}\n\n\tindex = this.indexOf(key);\n\tif (index >= 0) {\n\t\tthis.size--;\n\t\treturn this.list.splice(index, 1)[0];\n\t}\n\n\treturn undefined;\n};\n\n\n// important that has() doesn't use get() in case an existing key has a falsy value, in which case has() would return false\nSimilar.prototype.has = function(key) {\n\tvar index;\n\n\tif (this.lastItem && this.isEqual(this.lastItem.key, key)) {\n\t\treturn true;\n\t}\n\n\tindex = this.indexOf(key);\n\tif (index >= 0) {\n\t\tthis.lastItem = this.list[index];\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\nSimilar.prototype.forEach = function(callback, thisArg) {\n\tvar i;\n\tfor (i = 0; i < this.size; i++) {\n\t\tcallback.call(thisArg || this, this.list[i].val, this.list[i].key, this);\n\t}\n};\n\nSimilar.prototype.indexOf = function(key) {\n\tvar i;\n\tfor (i = 0; i < this.size; i++) {\n\t\tif (this.isEqual(this.list[i].key, key)) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n};\n\n// check if the numbers are equal, or whether they are both precisely NaN (isNaN returns true for all non-numbers)\nSimilar.prototype.isEqual = function(val1, val2) {\n\treturn val1 === val2 || (val1 !== val1 && val2 !== val2);\n};\n\nmodule.exports = Similar;", 64 | "var MapOrSimilar = require('map-or-similar');\n\nmodule.exports = function (limit) {\n\tvar cache = new MapOrSimilar(),\n\t\tlru = [];\n\n\treturn function (fn) {\n\t\tvar memoizerific = function () {\n\t\t\tvar currentCache = cache,\n\t\t\t\tnewMap,\n\t\t\t\tfnResult,\n\t\t\t\targsLengthMinusOne = arguments.length - 1,\n\t\t\t\tlruPath = Array(argsLengthMinusOne + 1),\n\t\t\t\tisMemoized = true,\n\t\t\t\ti;\n\n\t\t\tif ((memoizerific.numArgs || memoizerific.numArgs === 0) && memoizerific.numArgs !== argsLengthMinusOne + 1) {\n\t\t\t\tthrow new Error('Memoizerific functions should always be called with the same number of arguments');\n\t\t\t}\n\n\t\t\t// loop through each argument to traverse the map tree\n\t\t\tfor (i = 0; i < argsLengthMinusOne; i++) {\n\t\t\t\tlruPath[i] = {\n\t\t\t\t\tcacheItem: currentCache,\n\t\t\t\t\targ: arguments[i]\n\t\t\t\t};\n\n\t\t\t\t// climb through the hierarchical map tree until the second-last argument has been found, or an argument is missing.\n\t\t\t\t// if all arguments up to the second-last have been found, this will potentially be a cache hit (determined below)\n\t\t\t\tif (currentCache.has(arguments[i])) {\n\t\t\t\t\tcurrentCache = currentCache.get(arguments[i]);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tisMemoized = false;\n\n\t\t\t\t// make maps until last value\n\t\t\t\tnewMap = new MapOrSimilar();\n\t\t\t\tcurrentCache.set(arguments[i], newMap);\n\t\t\t\tcurrentCache = newMap;\n\t\t\t}\n\n\t\t\t// we are at the last arg, check if it is really memoized\n\t\t\tif (isMemoized) {\n\t\t\t\tif (currentCache.has(arguments[argsLengthMinusOne])) {\n\t\t\t\t\tfnResult = currentCache.get(arguments[argsLengthMinusOne]);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tisMemoized = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!isMemoized) {\n\t\t\t\tfnResult = fn.apply(null, arguments);\n\t\t\t\tcurrentCache.set(arguments[argsLengthMinusOne], fnResult);\n\t\t\t}\n\n\t\t\tif (limit > 0) {\n\t\t\t\tlruPath[argsLengthMinusOne] = {\n\t\t\t\t\tcacheItem: currentCache,\n\t\t\t\t\targ: arguments[argsLengthMinusOne]\n\t\t\t\t};\n\n\t\t\t\tif (isMemoized) {\n\t\t\t\t\tmoveToMostRecentLru(lru, lruPath);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlru.push(lruPath);\n\t\t\t\t}\n\n\t\t\t\tif (lru.length > limit) {\n\t\t\t\t\tremoveCachedResult(lru.shift());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmemoizerific.wasMemoized = isMemoized;\n\t\t\tmemoizerific.numArgs = argsLengthMinusOne + 1;\n\n\t\t\treturn fnResult;\n\t\t};\n\n\t\tmemoizerific.limit = limit;\n\t\tmemoizerific.wasMemoized = false;\n\t\tmemoizerific.cache = cache;\n\t\tmemoizerific.lru = lru;\n\n\t\treturn memoizerific;\n\t};\n};\n\n// move current args to most recent position\nfunction moveToMostRecentLru(lru, lruPath) {\n\tvar lruLen = lru.length,\n\t\tlruPathLen = lruPath.length,\n\t\tisMatch,\n\t\ti, ii;\n\n\tfor (i = 0; i < lruLen; i++) {\n\t\tisMatch = true;\n\t\tfor (ii = 0; ii < lruPathLen; ii++) {\n\t\t\tif (!isEqual(lru[i][ii].arg, lruPath[ii].arg)) {\n\t\t\t\tisMatch = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (isMatch) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlru.push(lru.splice(i, 1)[0]);\n}\n\n// remove least recently used cache item and all dead branches\nfunction removeCachedResult(removedLru) {\n\tvar removedLruLen = removedLru.length,\n\t\tcurrentLru = removedLru[removedLruLen - 1],\n\t\ttmp,\n\t\ti;\n\n\tcurrentLru.cacheItem.delete(currentLru.arg);\n\n\t// walk down the tree removing dead branches (size 0) along the way\n\tfor (i = removedLruLen - 2; i >= 0; i--) {\n\t\tcurrentLru = removedLru[i];\n\t\ttmp = currentLru.cacheItem.get(currentLru.arg);\n\n\t\tif (!tmp || !tmp.size) {\n\t\t\tcurrentLru.cacheItem.delete(currentLru.arg);\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n// check if the numbers are equal, or whether they are both precisely NaN (isNaN returns true for all non-numbers)\nfunction isEqual(val1, val2) {\n\treturn val1 === val2 || (val1 !== val1 && val2 !== val2);\n}", 65 | "// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // 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\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // 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.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n", 66 | "'use strict';\n\nexports.__esModule = true;\nfunction createThunkMiddleware(extraArgument) {\n return function (_ref) {\n var dispatch = _ref.dispatch;\n var getState = _ref.getState;\n return function (next) {\n return function (action) {\n if (typeof action === 'function') {\n return action(dispatch, getState, extraArgument);\n }\n\n return next(action);\n };\n };\n };\n}\n\nvar thunk = createThunkMiddleware();\nthunk.withExtraArgument = createThunkMiddleware;\n\nexports['default'] = thunk;", 67 | "'use strict';\n\nexports.__esModule = true;\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nexports['default'] = applyMiddleware;\n\nvar _compose = require('./compose');\n\nvar _compose2 = _interopRequireDefault(_compose);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\n/**\n * Creates a store enhancer that applies middleware to the dispatch method\n * of the Redux store. This is handy for a variety of tasks, such as expressing\n * asynchronous actions in a concise manner, or logging every action payload.\n *\n * See `redux-thunk` package as an example of the Redux middleware.\n *\n * Because middleware is potentially asynchronous, this should be the first\n * store enhancer in the composition chain.\n *\n * Note that each middleware will be given the `dispatch` and `getState` functions\n * as named arguments.\n *\n * @param {...Function} middlewares The middleware chain to be applied.\n * @returns {Function} A store enhancer applying the middleware.\n */\nfunction applyMiddleware() {\n for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {\n middlewares[_key] = arguments[_key];\n }\n\n return function (createStore) {\n return function (reducer, preloadedState, enhancer) {\n var store = createStore(reducer, preloadedState, enhancer);\n var _dispatch = store.dispatch;\n var chain = [];\n\n var middlewareAPI = {\n getState: store.getState,\n dispatch: function dispatch(action) {\n return _dispatch(action);\n }\n };\n chain = middlewares.map(function (middleware) {\n return middleware(middlewareAPI);\n });\n _dispatch = _compose2['default'].apply(undefined, chain)(store.dispatch);\n\n return _extends({}, store, {\n dispatch: _dispatch\n });\n };\n };\n}", 68 | "'use strict';\n\nexports.__esModule = true;\nexports['default'] = bindActionCreators;\nfunction bindActionCreator(actionCreator, dispatch) {\n return function () {\n return dispatch(actionCreator.apply(undefined, arguments));\n };\n}\n\n/**\n * Turns an object whose values are action creators, into an object with the\n * same keys, but with every function wrapped into a `dispatch` call so they\n * may be invoked directly. This is just a convenience method, as you can call\n * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.\n *\n * For convenience, you can also pass a single function as the first argument,\n * and get a function in return.\n *\n * @param {Function|Object} actionCreators An object whose values are action\n * creator functions. One handy way to obtain it is to use ES6 `import * as`\n * syntax. You may also pass a single function.\n *\n * @param {Function} dispatch The `dispatch` function available on your Redux\n * store.\n *\n * @returns {Function|Object} The object mimicking the original object, but with\n * every action creator wrapped into the `dispatch` call. If you passed a\n * function as `actionCreators`, the return value will also be a single\n * function.\n */\nfunction bindActionCreators(actionCreators, dispatch) {\n if (typeof actionCreators === 'function') {\n return bindActionCreator(actionCreators, dispatch);\n }\n\n if (typeof actionCreators !== 'object' || actionCreators === null) {\n throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write \"import ActionCreators from\" instead of \"import * as ActionCreators from\"?');\n }\n\n var keys = Object.keys(actionCreators);\n var boundActionCreators = {};\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var actionCreator = actionCreators[key];\n if (typeof actionCreator === 'function') {\n boundActionCreators[key] = bindActionCreator(actionCreator, dispatch);\n }\n }\n return boundActionCreators;\n}", 69 | "'use strict';\n\nexports.__esModule = true;\nexports['default'] = combineReducers;\n\nvar _createStore = require('./createStore');\n\nvar _isPlainObject = require('lodash/isPlainObject');\n\nvar _isPlainObject2 = _interopRequireDefault(_isPlainObject);\n\nvar _warning = require('./utils/warning');\n\nvar _warning2 = _interopRequireDefault(_warning);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nfunction getUndefinedStateErrorMessage(key, action) {\n var actionType = action && action.type;\n var actionName = actionType && '\"' + actionType.toString() + '\"' || 'an action';\n\n return 'Given action ' + actionName + ', reducer \"' + key + '\" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state.';\n}\n\nfunction getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) {\n var reducerKeys = Object.keys(reducers);\n var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer';\n\n if (reducerKeys.length === 0) {\n return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';\n }\n\n if (!(0, _isPlainObject2['default'])(inputState)) {\n return 'The ' + argumentName + ' has unexpected type of \"' + {}.toString.call(inputState).match(/\\s([a-z|A-Z]+)/)[1] + '\". Expected argument to be an object with the following ' + ('keys: \"' + reducerKeys.join('\", \"') + '\"');\n }\n\n var unexpectedKeys = Object.keys(inputState).filter(function (key) {\n return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key];\n });\n\n unexpectedKeys.forEach(function (key) {\n unexpectedKeyCache[key] = true;\n });\n\n if (unexpectedKeys.length > 0) {\n return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('\"' + unexpectedKeys.join('\", \"') + '\" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('\"' + reducerKeys.join('\", \"') + '\". Unexpected keys will be ignored.');\n }\n}\n\nfunction assertReducerSanity(reducers) {\n Object.keys(reducers).forEach(function (key) {\n var reducer = reducers[key];\n var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT });\n\n if (typeof initialState === 'undefined') {\n throw new Error('Reducer \"' + key + '\" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.');\n }\n\n var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');\n if (typeof reducer(undefined, { type: type }) === 'undefined') {\n throw new Error('Reducer \"' + key + '\" returned undefined when probed with a random type. ' + ('Don\\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in \"redux/*\" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.');\n }\n });\n}\n\n/**\n * Turns an object whose values are different reducer functions, into a single\n * reducer function. It will call every child reducer, and gather their results\n * into a single state object, whose keys correspond to the keys of the passed\n * reducer functions.\n *\n * @param {Object} reducers An object whose values correspond to different\n * reducer functions that need to be combined into one. One handy way to obtain\n * it is to use ES6 `import * as reducers` syntax. The reducers may never return\n * undefined for any action. Instead, they should return their initial state\n * if the state passed to them was undefined, and the current state for any\n * unrecognized action.\n *\n * @returns {Function} A reducer function that invokes every reducer inside the\n * passed object, and builds a state object with the same shape.\n */\nfunction combineReducers(reducers) {\n var reducerKeys = Object.keys(reducers);\n var finalReducers = {};\n for (var i = 0; i < reducerKeys.length; i++) {\n var key = reducerKeys[i];\n\n if (\"development\" !== 'production') {\n if (typeof reducers[key] === 'undefined') {\n (0, _warning2['default'])('No reducer provided for key \"' + key + '\"');\n }\n }\n\n if (typeof reducers[key] === 'function') {\n finalReducers[key] = reducers[key];\n }\n }\n var finalReducerKeys = Object.keys(finalReducers);\n\n if (\"development\" !== 'production') {\n var unexpectedKeyCache = {};\n }\n\n var sanityError;\n try {\n assertReducerSanity(finalReducers);\n } catch (e) {\n sanityError = e;\n }\n\n return function combination() {\n var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];\n var action = arguments[1];\n\n if (sanityError) {\n throw sanityError;\n }\n\n if (\"development\" !== 'production') {\n var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache);\n if (warningMessage) {\n (0, _warning2['default'])(warningMessage);\n }\n }\n\n var hasChanged = false;\n var nextState = {};\n for (var i = 0; i < finalReducerKeys.length; i++) {\n var key = finalReducerKeys[i];\n var reducer = finalReducers[key];\n var previousStateForKey = state[key];\n var nextStateForKey = reducer(previousStateForKey, action);\n if (typeof nextStateForKey === 'undefined') {\n var errorMessage = getUndefinedStateErrorMessage(key, action);\n throw new Error(errorMessage);\n }\n nextState[key] = nextStateForKey;\n hasChanged = hasChanged || nextStateForKey !== previousStateForKey;\n }\n return hasChanged ? nextState : state;\n };\n}", 70 | "\"use strict\";\n\nexports.__esModule = true;\nexports[\"default\"] = compose;\n/**\n * Composes single-argument functions from right to left. The rightmost\n * function can take multiple arguments as it provides the signature for\n * the resulting composite function.\n *\n * @param {...Function} funcs The functions to compose.\n * @returns {Function} A function obtained by composing the argument functions\n * from right to left. For example, compose(f, g, h) is identical to doing\n * (...args) => f(g(h(...args))).\n */\n\nfunction compose() {\n for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {\n funcs[_key] = arguments[_key];\n }\n\n if (funcs.length === 0) {\n return function (arg) {\n return arg;\n };\n }\n\n if (funcs.length === 1) {\n return funcs[0];\n }\n\n var last = funcs[funcs.length - 1];\n var rest = funcs.slice(0, -1);\n return function () {\n return rest.reduceRight(function (composed, f) {\n return f(composed);\n }, last.apply(undefined, arguments));\n };\n}", 71 | "'use strict';\n\nexports.__esModule = true;\nexports.ActionTypes = undefined;\nexports['default'] = createStore;\n\nvar _isPlainObject = require('lodash/isPlainObject');\n\nvar _isPlainObject2 = _interopRequireDefault(_isPlainObject);\n\nvar _symbolObservable = require('symbol-observable');\n\nvar _symbolObservable2 = _interopRequireDefault(_symbolObservable);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\n/**\n * These are private action types reserved by Redux.\n * For any unknown actions, you must return the current state.\n * If the current state is undefined, you must return the initial state.\n * Do not reference these action types directly in your code.\n */\nvar ActionTypes = exports.ActionTypes = {\n INIT: '@@redux/INIT'\n};\n\n/**\n * Creates a Redux store that holds the state tree.\n * The only way to change the data in the store is to call `dispatch()` on it.\n *\n * There should only be a single store in your app. To specify how different\n * parts of the state tree respond to actions, you may combine several reducers\n * into a single reducer function by using `combineReducers`.\n *\n * @param {Function} reducer A function that returns the next state tree, given\n * the current state tree and the action to handle.\n *\n * @param {any} [preloadedState] The initial state. You may optionally specify it\n * to hydrate the state from the server in universal apps, or to restore a\n * previously serialized user session.\n * If you use `combineReducers` to produce the root reducer function, this must be\n * an object with the same shape as `combineReducers` keys.\n *\n * @param {Function} enhancer The store enhancer. You may optionally specify it\n * to enhance the store with third-party capabilities such as middleware,\n * time travel, persistence, etc. The only store enhancer that ships with Redux\n * is `applyMiddleware()`.\n *\n * @returns {Store} A Redux store that lets you read the state, dispatch actions\n * and subscribe to changes.\n */\nfunction createStore(reducer, preloadedState, enhancer) {\n var _ref2;\n\n if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {\n enhancer = preloadedState;\n preloadedState = undefined;\n }\n\n if (typeof enhancer !== 'undefined') {\n if (typeof enhancer !== 'function') {\n throw new Error('Expected the enhancer to be a function.');\n }\n\n return enhancer(createStore)(reducer, preloadedState);\n }\n\n if (typeof reducer !== 'function') {\n throw new Error('Expected the reducer to be a function.');\n }\n\n var currentReducer = reducer;\n var currentState = preloadedState;\n var currentListeners = [];\n var nextListeners = currentListeners;\n var isDispatching = false;\n\n function ensureCanMutateNextListeners() {\n if (nextListeners === currentListeners) {\n nextListeners = currentListeners.slice();\n }\n }\n\n /**\n * Reads the state tree managed by the store.\n *\n * @returns {any} The current state tree of your application.\n */\n function getState() {\n return currentState;\n }\n\n /**\n * Adds a change listener. It will be called any time an action is dispatched,\n * and some part of the state tree may potentially have changed. You may then\n * call `getState()` to read the current state tree inside the callback.\n *\n * You may call `dispatch()` from a change listener, with the following\n * caveats:\n *\n * 1. The subscriptions are snapshotted just before every `dispatch()` call.\n * If you subscribe or unsubscribe while the listeners are being invoked, this\n * will not have any effect on the `dispatch()` that is currently in progress.\n * However, the next `dispatch()` call, whether nested or not, will use a more\n * recent snapshot of the subscription list.\n *\n * 2. The listener should not expect to see all state changes, as the state\n * might have been updated multiple times during a nested `dispatch()` before\n * the listener is called. It is, however, guaranteed that all subscribers\n * registered before the `dispatch()` started will be called with the latest\n * state by the time it exits.\n *\n * @param {Function} listener A callback to be invoked on every dispatch.\n * @returns {Function} A function to remove this change listener.\n */\n function subscribe(listener) {\n if (typeof listener !== 'function') {\n throw new Error('Expected listener to be a function.');\n }\n\n var isSubscribed = true;\n\n ensureCanMutateNextListeners();\n nextListeners.push(listener);\n\n return function unsubscribe() {\n if (!isSubscribed) {\n return;\n }\n\n isSubscribed = false;\n\n ensureCanMutateNextListeners();\n var index = nextListeners.indexOf(listener);\n nextListeners.splice(index, 1);\n };\n }\n\n /**\n * Dispatches an action. It is the only way to trigger a state change.\n *\n * The `reducer` function, used to create the store, will be called with the\n * current state tree and the given `action`. Its return value will\n * be considered the **next** state of the tree, and the change listeners\n * will be notified.\n *\n * The base implementation only supports plain object actions. If you want to\n * dispatch a Promise, an Observable, a thunk, or something else, you need to\n * wrap your store creating function into the corresponding middleware. For\n * example, see the documentation for the `redux-thunk` package. Even the\n * middleware will eventually dispatch plain object actions using this method.\n *\n * @param {Object} action A plain object representing “what changed”. It is\n * a good idea to keep actions serializable so you can record and replay user\n * sessions, or use the time travelling `redux-devtools`. An action must have\n * a `type` property which may not be `undefined`. It is a good idea to use\n * string constants for action types.\n *\n * @returns {Object} For convenience, the same action object you dispatched.\n *\n * Note that, if you use a custom middleware, it may wrap `dispatch()` to\n * return something else (for example, a Promise you can await).\n */\n function dispatch(action) {\n if (!(0, _isPlainObject2['default'])(action)) {\n throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');\n }\n\n if (typeof action.type === 'undefined') {\n throw new Error('Actions may not have an undefined \"type\" property. ' + 'Have you misspelled a constant?');\n }\n\n if (isDispatching) {\n throw new Error('Reducers may not dispatch actions.');\n }\n\n try {\n isDispatching = true;\n currentState = currentReducer(currentState, action);\n } finally {\n isDispatching = false;\n }\n\n var listeners = currentListeners = nextListeners;\n for (var i = 0; i < listeners.length; i++) {\n listeners[i]();\n }\n\n return action;\n }\n\n /**\n * Replaces the reducer currently used by the store to calculate the state.\n *\n * You might need this if your app implements code splitting and you want to\n * load some of the reducers dynamically. You might also need this if you\n * implement a hot reloading mechanism for Redux.\n *\n * @param {Function} nextReducer The reducer for the store to use instead.\n * @returns {void}\n */\n function replaceReducer(nextReducer) {\n if (typeof nextReducer !== 'function') {\n throw new Error('Expected the nextReducer to be a function.');\n }\n\n currentReducer = nextReducer;\n dispatch({ type: ActionTypes.INIT });\n }\n\n /**\n * Interoperability point for observable/reactive libraries.\n * @returns {observable} A minimal observable of state changes.\n * For more information, see the observable proposal:\n * https://github.com/zenparsing/es-observable\n */\n function observable() {\n var _ref;\n\n var outerSubscribe = subscribe;\n return _ref = {\n /**\n * The minimal observable subscription method.\n * @param {Object} observer Any object that can be used as an observer.\n * The observer object should have a `next` method.\n * @returns {subscription} An object with an `unsubscribe` method that can\n * be used to unsubscribe the observable from the store, and prevent further\n * emission of values from the observable.\n */\n subscribe: function subscribe(observer) {\n if (typeof observer !== 'object') {\n throw new TypeError('Expected the observer to be an object.');\n }\n\n function observeState() {\n if (observer.next) {\n observer.next(getState());\n }\n }\n\n observeState();\n var unsubscribe = outerSubscribe(observeState);\n return { unsubscribe: unsubscribe };\n }\n }, _ref[_symbolObservable2['default']] = function () {\n return this;\n }, _ref;\n }\n\n // When a store is created, an \"INIT\" action is dispatched so that every\n // reducer returns their initial state. This effectively populates\n // the initial state tree.\n dispatch({ type: ActionTypes.INIT });\n\n return _ref2 = {\n dispatch: dispatch,\n subscribe: subscribe,\n getState: getState,\n replaceReducer: replaceReducer\n }, _ref2[_symbolObservable2['default']] = observable, _ref2;\n}", 72 | "'use strict';\n\nexports.__esModule = true;\nexports.compose = exports.applyMiddleware = exports.bindActionCreators = exports.combineReducers = exports.createStore = undefined;\n\nvar _createStore = require('./createStore');\n\nvar _createStore2 = _interopRequireDefault(_createStore);\n\nvar _combineReducers = require('./combineReducers');\n\nvar _combineReducers2 = _interopRequireDefault(_combineReducers);\n\nvar _bindActionCreators = require('./bindActionCreators');\n\nvar _bindActionCreators2 = _interopRequireDefault(_bindActionCreators);\n\nvar _applyMiddleware = require('./applyMiddleware');\n\nvar _applyMiddleware2 = _interopRequireDefault(_applyMiddleware);\n\nvar _compose = require('./compose');\n\nvar _compose2 = _interopRequireDefault(_compose);\n\nvar _warning = require('./utils/warning');\n\nvar _warning2 = _interopRequireDefault(_warning);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\n/*\n* This is a dummy function to check if the function name has been altered by minification.\n* If the function has been minified and NODE_ENV !== 'production', warn the user.\n*/\nfunction isCrushed() {}\n\nif (\"development\" !== 'production' && typeof isCrushed.name === 'string' && isCrushed.name !== 'isCrushed') {\n (0, _warning2['default'])('You are currently using minified code outside of NODE_ENV === \\'production\\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.');\n}\n\nexports.createStore = _createStore2['default'];\nexports.combineReducers = _combineReducers2['default'];\nexports.bindActionCreators = _bindActionCreators2['default'];\nexports.applyMiddleware = _applyMiddleware2['default'];\nexports.compose = _compose2['default'];", 73 | "'use strict';\n\nexports.__esModule = true;\nexports['default'] = warning;\n/**\n * Prints a warning in the console if it exists.\n *\n * @param {String} message The warning message.\n * @returns {void}\n */\nfunction warning(message) {\n /* eslint-disable no-console */\n if (typeof console !== 'undefined' && typeof console.error === 'function') {\n console.error(message);\n }\n /* eslint-enable no-console */\n try {\n // This error was thrown as a convenience so that if you enable\n // \"break on all exceptions\" in your console,\n // it would pause the execution at this line.\n throw new Error(message);\n /* eslint-disable no-empty */\n } catch (e) {}\n /* eslint-enable no-empty */\n}", 74 | "module.exports = require('./lib/index');\n", 75 | "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;", 76 | "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n\tvalue: true\n});\nexports['default'] = symbolObservablePonyfill;\nfunction symbolObservablePonyfill(root) {\n\tvar result;\n\tvar _Symbol = root.Symbol;\n\n\tif (typeof _Symbol === 'function') {\n\t\tif (_Symbol.observable) {\n\t\t\tresult = _Symbol.observable;\n\t\t} else {\n\t\t\tresult = _Symbol('observable');\n\t\t\t_Symbol.observable = result;\n\t\t}\n\t} else {\n\t\tresult = '@@observable';\n\t}\n\n\treturn result;\n};", 77 | "import React from 'react';\nimport { render } from 'react-dom';\n\nimport { HOME, ABOUT, ACCOUNT } from './constants/pages';\n\nimport HomePage from './page-home';\nimport AboutPage from './page-about';\nimport AccountPage from './page-account';\n\nexport default function (data, domElement) {\n\tlet page;\n\n\tif (data.routing.url !== window.location.pathname + window.location.search) {\n\t\twindow.history.pushState(null, null, data.routing.url);\n\t}\n\tdocument.title = data.routing.title;\n\n\tswitch(data.selectedPage) {\n\tcase ABOUT:\n\t\tpage = ;\n\t\tbreak;\n\n\tcase ACCOUNT:\n\t\tpage = ;\n\t\tbreak;\n\n\tdefault:\n\t\tpage = ;\n\t\tbreak;\n\t}\n\n\trender(page, domElement);\n}\n\n", 78 | "export const HOME = 'HOME';\nexport const ABOUT = 'ABOUT';\nexport const ACCOUNT = 'ACCOUNT';", 79 | "import React from 'react';\nimport classnames from 'classnames';\n\nimport Link from 'link-react';\n\nconst Items = (p) => (\n\t
    \n\t\t{ !!p.items && p.items.map(item => (\n\t\t\t
  • \n\t\t\t\t\n\t\t\t\t\t\t{ item.label }\n\t\t\t\t\n\t\t\t
  • \n\t\t))}\n\t
\n);\n\nItems.propTypes = {\n\tclassName: React.PropTypes.string,\n\titems: React.PropTypes.arrayOf(React.PropTypes.shape({\n\t\tid: React.PropTypes.string,\n\t\tlabel: React.PropTypes.string,\n\t\thref: React.PropTypes.string,\n\t\tisSelected: React.PropTypes.bool,\n\t\tonClick: React.PropTypes.func\n\t}))\n};\n\nexport default Items;\n", 80 | "import React from 'react';\nimport classnames from 'classnames';\n\nimport SiteHeader from './site-header';\n\nconst AboutPage = (p) => (\n\t
\n\t\t\n\n\t\t
\n\t\t\t

\n\t\t\t\tAbout\n\t\t\t

\n\t\t
\n\t
\n);\n\nAboutPage.propTypes = {\n\tclassName: React.PropTypes.string,\n\tsiteHeader: React.PropTypes.object\n};\n\nexport default AboutPage;\n", 81 | "import React from 'react';\nimport classnames from 'classnames';\n\nimport SiteHeader from './site-header';\n\nconst AccountPage = (p) => (\n\t
\n\t\t\n\n\t\t
\n\t\t\t

\n\t\t\t\tAccount\n\t\t\t

\n\t\t
\n\t
\n);\n\nAccountPage.propTypes = {\n\tclassName: React.PropTypes.string,\n\tsiteHeader: React.PropTypes.object\n};\n\nexport default AccountPage;\n", 82 | "import React from 'react';\nimport classnames from 'classnames';\n\nimport SiteHeader from './site-header';\nimport Items from './items';\n\nconst HomePage = (p) => (\n\t
\n\t\t\n\n\t\t
\n\t\t\t\n\t\t
\n\n\t\t
\n\t\t\topen the console while clicking\n\t\t
\n\t
\n);\n\nHomePage.propTypes = {\n\tclassName: React.PropTypes.string,\n\tsiteHeader: React.PropTypes.object,\n\titems: React.PropTypes.array,\n};\n\nexport default HomePage;\n", 83 | "import React from 'react';\nimport classnames from 'classnames';\n\nimport Link from 'link-react';\n\nconst SiteHeader = (p) => (\n\t
\n\t\t\n\t
\n);\n\nSiteHeader.propTypes = {\n\tclassName: React.PropTypes.string,\n\tlinks: React.PropTypes.arrayOf(React.PropTypes.shape({\n\t\tlabel: React.PropTypes.string,\n\t\thref: React.PropTypes.string,\n\t\tisSelected: React.PropTypes.bool,\n\t\tonClick: React.PropTypes.func\n\t}))\n};\n\nexport default SiteHeader;\n", 84 | "import store from './state/store';\nimport app from './components/app';\nimport selectors from './selectors/selectors';\n\nimport updateURL from './state/site/actions/update-url';\n\n// import selectors from './selectors';\n\n// debug stuff\nObject.defineProperty(window, \"state\", { get: store.getState });\nwindow.selectors = selectors;\n\nconsole.log('********************************************* \\n DEVELOPMENT MODE \\n window.state available \\n window.selectors available \\n ********************************************* \\n');\n\n// subscribe to state changes and re-render view on every change\nconst domElement = document.getElementById('app');\nstore.subscribe(() => app(selectors, domElement));\n\n// listen for back button, forward button, etc\nwindow.onpopstate = (e) => {\n\tstore.dispatch(updateURL(window.location.pathname + window.location.search));\n};\n\n// read the url and navigate to the right page\nstore.dispatch(updateURL(window.location.pathname + window.location.search));\n", 85 | "import memoizerific from 'memoizerific';\nimport store from '../../state/store';\n\nimport { SECTIONS_PATHS } from '../../state/site/constants/paths';\nimport { HOME, ABOUT, ACCOUNT, ITEM } from '../../state/site/constants/sections';\n\nimport updateURL from '../../state/site/actions/update-url';\n\nexport default function () {\n\tconst { items, selectedItemID } = store.getState();\n\treturn selectItems(items, selectedItemID);\n}\n\nexport const selectItems = memoizerific(10)((items, selectedItemID) => {\n\treturn Object.keys(items).map(key => selectItem(key, items[key].name, `${SECTIONS_PATHS[ITEM]}/${key}`, selectedItemID === key));\n});\n\nexport const selectItem = memoizerific(20)((id, label, href, isSelected) => {\n\treturn {\n\t\tid,\n\t\tlabel,\n\t\thref,\n\t\tisSelected,\n\t\tonClick: () => store.dispatch(updateURL(href))\n\t};\n});\n", 86 | "import combineSelectors from 'combine-selectors';\nimport store from '../state/store';\n\nimport selectedPage from './site/selected-page';\nimport routing from './site/routing';\nimport siteHeader from './site/site-header';\nimport items from './items/items';\n\nconst selectors = {\n\tselectedPage,\n\trouting,\n\tsiteHeader,\n\titems\n};\n\nexport default combineSelectors(selectors, store.getState);\n", 87 | "import memoizerific from 'memoizerific';\nimport store from '../../state/store';\n\nexport default function () {\n\tconst { url, selectedSection } = store.getState();\n\treturn selectRouting(url, selectedSection);\n}\n\nexport const selectRouting = memoizerific(1)((url, selectedSection) => {\n\treturn {\n\t\turl,\n\t\ttitle: selectTitle(selectedSection)\n\t};\n});\n\nexport const selectTitle = memoizerific(1)((selectedSection) => {\n\treturn selectedSection + ' - State-Driven Routing';\n});\n", 88 | "import memoizerific from 'memoizerific';\nimport store from '../../state/store';\n\nimport * as PAGES from '../../components/constants/pages';\n\nexport default function () {\n\tconst { selectedSection } = store.getState();\n\treturn selectSelectedPage(selectedSection);\n}\n\nexport const selectSelectedPage = memoizerific(1)((selectedSection) => {\n\treturn PAGES[selectedSection];\n});\n", 89 | "import memoizerific from 'memoizerific';\nimport store from '../../state/store';\n\nimport { SECTIONS_PATHS } from '../../state/site/constants/paths';\nimport { HOME, ABOUT, ACCOUNT } from '../../state/site/constants/sections';\n\nimport updateURL from '../../state/site/actions/update-url';\n\nexport default function () {\n\tconst { selectedSection } = store.getState();\n\treturn selectSiteHeader(selectedSection);\n}\n\nexport const selectSiteHeader = memoizerific(10)((selectedSection) => {\n\treturn {\n\t\tlinks: [\n\t\t\tselectSiteHeaderLink('Home', SECTIONS_PATHS[HOME], selectedSection === HOME),\n\t\t\tselectSiteHeaderLink('About', SECTIONS_PATHS[ABOUT], selectedSection === ABOUT),\n\t\t\tselectSiteHeaderLink('Account', SECTIONS_PATHS[ACCOUNT], selectedSection === ACCOUNT)\n\t\t]\n\t};\n});\n\nexport const selectSiteHeaderLink = memoizerific(20)((label, href, isSelected) => {\n\treturn {\n\t\tlabel,\n\t\thref,\n\t\tisSelected,\n\t\tonClick: () => store.dispatch(updateURL(href))\n\t};\n});\n", 90 | "import { UPDATE_URL } from '../../site/actions/update-url';\n\nimport { HOME } from '../../site/constants/sections';\nimport { PATHS_SECTIONS } from '../../site/constants/paths';\n\nconst defaultItems = {\n\t'id1': {\n\t\tname: 'Item #1'\n\t},\n\t'id2': {\n\t\tname: 'Item #2'\n\t},\n\t'id3': {\n\t\tname: 'Item #3'\n\t}\n};\n\nexport default function (items = defaultItems, action) {\n\tswitch (action.type) {\n\n\tdefault:\n\t\treturn items;\n\t}\n}\n", 91 | "import { UPDATE_URL } from '../../site/actions/update-url';\n\nimport { SECTIONS_PATHS } from '../../site/constants/paths';\n\nexport default function (selectedItem = null, action) {\n\tswitch (action.type) {\n\n\tcase UPDATE_URL:\n\t\tlet parsedItemID = action.parsedURL.path.replace(SECTIONS_PATHS.ITEM + '/', '');\n\t\treturn parsedItemID !== action.parsedURL.path ? parsedItemID || null : null;\n\n\tdefault:\n\t\treturn selectedItem;\n\t}\n}\n", 92 | "export const UPDATE_URL = 'UPDATE_URL';\n\nexport default function (newURL) {\n\treturn (dispatch, getState) => {\n\t\tconst { url } = getState();\n\t\tif (newURL === url) {\n\t\t\treturn;\n\t\t}\n\n\t\tdispatch({\n\t\t\ttype: UPDATE_URL,\n\t\t\tparsedURL: parseURL(newURL)\n\t\t});\n\t};\n}\n\nfunction parseURL(url) {\n\tconst splitURL = url.split('?');\n\tlet path = splitURL[0].replace(/[/]+/g, '/');\n\tlet searchParams = {};\n\n\t// make sure there isn't a trailing slash, except for home being a single slash: '/'\n\tif (path.length >= 2) {\n\t\tpath = path.replace(/\\/$/, '');\n\t}\n\telse {\n\t\tpath = '/';\n\t}\n\n\tif (splitURL.length >= 2) {\n\t\tsearchParams = parseSearchParams(splitURL[1]);\n\t}\n\n\tconst finalURL = path + joinSearchParams(searchParams);\n\n\treturn {\n\t\tpath,\n\t\tsearchParams,\n\t\turl: finalURL\n\t};\n}\n\nfunction parseSearchParams(searchString) {\n\tlet pairSplit;\n\treturn (searchString || '').replace(/^\\?/, '').split('&').reduce((p, pair) => {\n\t\tpairSplit = pair.split('=');\n\t\tif (pairSplit.length >= 1 && pairSplit[0].length >= 1) {\n\t\t\tp[decodeURIComponent(pairSplit[0])] = decodeURIComponent(pairSplit[1]) || '';\n\t\t}\n\t\treturn p;\n\t}, {});\n}\n\nfunction joinSearchParams(searchParams) {\n\tlet searchString = Object.keys(searchParams).reduce((p, paramKey) => p += `&${paramKey}=${searchParams[paramKey]}`, '?');\n\n\tif (searchString.length <= 1) {\n\t\treturn '';\n\t}\n\n\treturn searchString.replace('?&', '?');\n}\n", 93 | "import { HOME, ABOUT, ACCOUNT, ITEM } from '../../site/constants/sections';\n\nexport const PATHS_SECTIONS = {\n\t'/': HOME,\n\t'/about': ABOUT,\n\t'/account': ACCOUNT,\n\t'/item': ITEM\n};\nexport const SECTIONS_PATHS = Object.keys(PATHS_SECTIONS).reduce((p, key) => { p[PATHS_SECTIONS[key]] = key; return p; }, {});\n\nexport const DEFAULT_PATH = '/';", 94 | "export const HOME = 'HOME';\nexport const ABOUT = 'ABOUT';\nexport const ACCOUNT = 'ACCOUNT';\nexport const ITEM = 'ITEM';\n", 95 | "import { UPDATE_URL } from '../../site/actions/update-url';\n\nimport { HOME } from '../../site/constants/sections';\nimport { PATHS_SECTIONS } from '../../site/constants/paths';\n\nexport default function (selectedSection = HOME, action) {\n\tswitch (action.type) {\n\n\tcase UPDATE_URL:\n\t\treturn PATHS_SECTIONS[action.parsedURL.path] || HOME;\n\n\tdefault:\n\t\treturn selectedSection;\n\t}\n}\n", 96 | "import { UPDATE_URL } from '../../site/actions/update-url';\nimport { DEFAULT_PATH } from '../../site/constants/paths';\n\nexport default function (url = null, action) {\n\tswitch (action.type) {\n\n\tcase UPDATE_URL:\n\t\treturn action.parsedURL.url;\n\n\tdefault:\n\t\treturn url;\n\t}\n}\n", 97 | "import { createStore, combineReducers, applyMiddleware } from 'redux';\nimport thunk from 'redux-thunk';\n\n// reducers\nimport url from './site/reducers/url';\nimport selectedSection from './site/reducers/selected-section';\nimport items from './items/reducers/items';\nimport selectedItemID from './items/reducers/selected-item-id';\n\nconst reducers = {\n\turl,\n\tselectedSection,\n\titems,\n\tselectedItemID\n};\n\n// console log middleware that logs all actions to console\nconst consoleLog = store => next => action => {\n\tif (typeof action !== 'function') {\n\t\tconsole.log(action);\n\t}\n\treturn next(action);\n};\n\n// conditionally set middleware based on dev or prod env\nlet middleWare;\nif (process.env.NODE_ENV !== 'production') {\n\tmiddleWare = applyMiddleware(consoleLog, thunk);\n} else {\n\tmiddleWare = applyMiddleware(thunk);\n}\n\n// create store\nexport default createStore(combineReducers(reducers), middleWare);\n" 98 | ] 99 | } -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | State Driven Routing 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "state-driven-routing", 3 | "version": "1.0.0", 4 | "description": "Implement routing without special dependencies or libraries.", 5 | "license": "MIT", 6 | "author": "Baz ", 7 | "homepage": "https://github.com/thinkloop/state-driven-routing#readme", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/thinkloop/state-driven-routing.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/thinkloop/state-driven-routing/issues" 14 | }, 15 | "keywords": [ 16 | "routing", 17 | "react-router", 18 | "spa", 19 | "redux", 20 | "react", 21 | "selectors" 22 | ], 23 | "main": "./build/state-driven-routing.js", 24 | "scripts": { 25 | "************": "", 26 | "start": "spa-webserver -d $npm_package_config_build_folder", 27 | "watch": "clear; echo '* YARN UPDATE *'; yarn upgrade; echo '* CLEAN * HTML * WATCHIFY *'; NODE_ENV=development npm run -s watch:all", 28 | "test": "clear; echo '**** TESTS ****'; jest", 29 | "***********": "", 30 | "watch:all": "npm run -s clean && (npm run -s watch:js & npm run -s watch:html)", 31 | "watch:js": "watchify $npm_package_config_js_entry_file --extension=.js --extension=.jsx -t [ babelify ] --debug -o 'exorcist $npm_package_config_build_folder/$npm_package_version/build.js.map > $npm_package_config_build_folder/$npm_package_version/build.js && echo ---------WATCHIFY--------`date +%r`'", 32 | "watch:html": "onchange $npm_package_config_html_entry_file -i -- npm run -s watch:html:do", 33 | "watch:html:do": "cat $npm_package_config_html_entry_file | npm run -s partial:replaceBuildFolderString > $npm_package_config_build_folder/index.html && echo ---------HTML-----------`date +%r`", 34 | "*********": "", 35 | "clean": "rimraf $npm_package_config_build_folder/* && mkdir -p $npm_package_config_build_folder && mkdir -p $npm_package_config_build_folder/$npm_package_version && echo ---------CLEAN----------`date +%r`", 36 | "partial:uglify": "[ $NODE_ENV = production ] && uglifyjs --compress drop_console,unused=true --mangle --screw-ie8 || cat", 37 | "partial:replaceBuildFolderString": "sed 's~${build_folder}~'$npm_package_version'~g'" 38 | }, 39 | "dependencies": { 40 | "browserify-shim": "^3.8.12", 41 | "classnames": "2.2.5", 42 | "combine-selectors": "thinkloop/combine-selectors", 43 | "link-react": "thinkloop/link-react", 44 | "memoizerific": "^1.8.4", 45 | "redux": "^3.6.0", 46 | "redux-thunk": "^2.1.0" 47 | }, 48 | "devDependencies": { 49 | "babel-jest": "^16.0.0", 50 | "babel-preset-es2015": "^6.16.0", 51 | "babel-preset-react": "6.16.0", 52 | "babel-preset-stage-0": "6.16.0", 53 | "babelify": "^7.3.0", 54 | "browserify": "13.1.0", 55 | "derequire": "^2.0.3", 56 | "exorcist": "^0.4.0", 57 | "jest": "^16.0.0", 58 | "onchange": "^3.0.2", 59 | "redux-mock-store": "^1.2.1", 60 | "rimraf": "^2.5.4", 61 | "spa-webserver": "^1.0.5", 62 | "uglifyjs": "^2.4.10", 63 | "watchify": "^3.7.0" 64 | }, 65 | "browserify": { 66 | "transform": [ 67 | "browserify-shim" 68 | ] 69 | }, 70 | "browserify-shim": { 71 | "react": "global:React", 72 | "react-dom": "global:ReactDOM" 73 | }, 74 | "config": { 75 | "js_entry_file": "./src/index.js", 76 | "html_entry_file": "./src/index.html", 77 | "build_folder": "./build" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/components/app.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | 4 | import { HOME, ABOUT, ACCOUNT } from './constants/pages'; 5 | 6 | import HomePage from './page-home'; 7 | import AboutPage from './page-about'; 8 | import AccountPage from './page-account'; 9 | 10 | export default function (data, domElement) { 11 | let page; 12 | 13 | if (data.routing.url !== window.location.pathname + window.location.search) { 14 | window.history.pushState(null, null, data.routing.url); 15 | } 16 | document.title = data.routing.title; 17 | 18 | switch(data.selectedPage) { 19 | case ABOUT: 20 | page = ; 24 | break; 25 | 26 | case ACCOUNT: 27 | page = ; 31 | break; 32 | 33 | default: 34 | page = ; 39 | break; 40 | } 41 | 42 | render(page, domElement); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/components/constants/pages.js: -------------------------------------------------------------------------------- 1 | export const HOME = 'HOME'; 2 | export const ABOUT = 'ABOUT'; 3 | export const ACCOUNT = 'ACCOUNT'; -------------------------------------------------------------------------------- /src/components/items.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | import Link from 'link-react'; 5 | 6 | const Items = (p) => ( 7 |
    8 | { !!p.items && p.items.map(item => ( 9 |
  • 10 | 14 | { item.label } 15 | 16 |
  • 17 | ))} 18 |
19 | ); 20 | 21 | Items.propTypes = { 22 | className: React.PropTypes.string, 23 | items: React.PropTypes.arrayOf(React.PropTypes.shape({ 24 | id: React.PropTypes.string, 25 | label: React.PropTypes.string, 26 | href: React.PropTypes.string, 27 | isSelected: React.PropTypes.bool, 28 | onClick: React.PropTypes.func 29 | })) 30 | }; 31 | 32 | export default Items; 33 | -------------------------------------------------------------------------------- /src/components/page-about.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | import SiteHeader from './site-header'; 5 | 6 | const AboutPage = (p) => ( 7 |
8 | 9 | 10 |
11 |

12 | About 13 |

14 |
15 |
16 | ); 17 | 18 | AboutPage.propTypes = { 19 | className: React.PropTypes.string, 20 | siteHeader: React.PropTypes.object 21 | }; 22 | 23 | export default AboutPage; 24 | -------------------------------------------------------------------------------- /src/components/page-account.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | import SiteHeader from './site-header'; 5 | 6 | const AccountPage = (p) => ( 7 |
8 | 9 | 10 |
11 |

12 | Account 13 |

14 |
15 |
16 | ); 17 | 18 | AccountPage.propTypes = { 19 | className: React.PropTypes.string, 20 | siteHeader: React.PropTypes.object 21 | }; 22 | 23 | export default AccountPage; 24 | -------------------------------------------------------------------------------- /src/components/page-home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | import SiteHeader from './site-header'; 5 | import Items from './items'; 6 | 7 | const HomePage = (p) => ( 8 |
9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 | open the console while clicking 17 |
18 |
19 | ); 20 | 21 | HomePage.propTypes = { 22 | className: React.PropTypes.string, 23 | siteHeader: React.PropTypes.object, 24 | items: React.PropTypes.array, 25 | }; 26 | 27 | export default HomePage; 28 | -------------------------------------------------------------------------------- /src/components/site-header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | 4 | import Link from 'link-react'; 5 | 6 | const SiteHeader = (p) => ( 7 |
8 | 19 |
20 | ); 21 | 22 | SiteHeader.propTypes = { 23 | className: React.PropTypes.string, 24 | links: React.PropTypes.arrayOf(React.PropTypes.shape({ 25 | label: React.PropTypes.string, 26 | href: React.PropTypes.string, 27 | isSelected: React.PropTypes.bool, 28 | onClick: React.PropTypes.func 29 | })) 30 | }; 31 | 32 | export default SiteHeader; 33 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | State Driven Routing 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import store from './state/store'; 2 | import app from './components/app'; 3 | import selectors from './selectors/selectors'; 4 | 5 | import updateURL from './state/site/actions/update-url'; 6 | 7 | // import selectors from './selectors'; 8 | 9 | // debug stuff 10 | Object.defineProperty(window, "state", { get: store.getState }); 11 | window.selectors = selectors; 12 | 13 | console.log('********************************************* \n DEVELOPMENT MODE \n window.state available \n window.selectors available \n ********************************************* \n'); 14 | 15 | // subscribe to state changes and re-render view on every change 16 | const domElement = document.getElementById('app'); 17 | store.subscribe(() => app(selectors, domElement)); 18 | 19 | // listen for back button, forward button, etc 20 | window.onpopstate = (e) => { 21 | store.dispatch(updateURL(window.location.pathname + window.location.search)); 22 | }; 23 | 24 | // read the url and navigate to the right page 25 | store.dispatch(updateURL(window.location.pathname + window.location.search)); 26 | -------------------------------------------------------------------------------- /src/selectors/items/items.js: -------------------------------------------------------------------------------- 1 | import memoizerific from 'memoizerific'; 2 | import store from '../../state/store'; 3 | 4 | import { SECTIONS_PATHS } from '../../state/site/constants/paths'; 5 | import { HOME, ABOUT, ACCOUNT, ITEM } from '../../state/site/constants/sections'; 6 | 7 | import updateURL from '../../state/site/actions/update-url'; 8 | 9 | export default function () { 10 | const { items, selectedItemID } = store.getState(); 11 | return selectItems(items, selectedItemID); 12 | } 13 | 14 | export const selectItems = memoizerific(10)((items, selectedItemID) => { 15 | return Object.keys(items).map(key => selectItem(key, items[key].name, `${SECTIONS_PATHS[ITEM]}/${key}`, selectedItemID === key)); 16 | }); 17 | 18 | export const selectItem = memoizerific(20)((id, label, href, isSelected) => { 19 | return { 20 | id, 21 | label, 22 | href, 23 | isSelected, 24 | onClick: () => store.dispatch(updateURL(href)) 25 | }; 26 | }); 27 | -------------------------------------------------------------------------------- /src/selectors/selectors.js: -------------------------------------------------------------------------------- 1 | import combineSelectors from 'combine-selectors'; 2 | import store from '../state/store'; 3 | 4 | import selectedPage from './site/selected-page'; 5 | import routing from './site/routing'; 6 | import siteHeader from './site/site-header'; 7 | import items from './items/items'; 8 | 9 | const selectors = { 10 | selectedPage, 11 | routing, 12 | siteHeader, 13 | items 14 | }; 15 | 16 | export default combineSelectors(selectors, store.getState); 17 | -------------------------------------------------------------------------------- /src/selectors/site/routing.js: -------------------------------------------------------------------------------- 1 | import memoizerific from 'memoizerific'; 2 | import store from '../../state/store'; 3 | 4 | export default function () { 5 | const { url, selectedSection } = store.getState(); 6 | return selectRouting(url, selectedSection); 7 | } 8 | 9 | export const selectRouting = memoizerific(1)((url, selectedSection) => { 10 | return { 11 | url, 12 | title: selectTitle(selectedSection) 13 | }; 14 | }); 15 | 16 | export const selectTitle = memoizerific(1)((selectedSection) => { 17 | return selectedSection + ' - State-Driven Routing'; 18 | }); 19 | -------------------------------------------------------------------------------- /src/selectors/site/selected-page.js: -------------------------------------------------------------------------------- 1 | import memoizerific from 'memoizerific'; 2 | import store from '../../state/store'; 3 | 4 | import * as PAGES from '../../components/constants/pages'; 5 | 6 | export default function () { 7 | const { selectedSection } = store.getState(); 8 | return selectSelectedPage(selectedSection); 9 | } 10 | 11 | export const selectSelectedPage = memoizerific(1)((selectedSection) => { 12 | return PAGES[selectedSection]; 13 | }); 14 | -------------------------------------------------------------------------------- /src/selectors/site/site-header.js: -------------------------------------------------------------------------------- 1 | import memoizerific from 'memoizerific'; 2 | import store from '../../state/store'; 3 | 4 | import { SECTIONS_PATHS } from '../../state/site/constants/paths'; 5 | import { HOME, ABOUT, ACCOUNT } from '../../state/site/constants/sections'; 6 | 7 | import updateURL from '../../state/site/actions/update-url'; 8 | 9 | export default function () { 10 | const { selectedSection } = store.getState(); 11 | return selectSiteHeader(selectedSection); 12 | } 13 | 14 | export const selectSiteHeader = memoizerific(10)((selectedSection) => { 15 | return { 16 | links: [ 17 | selectSiteHeaderLink('Home', SECTIONS_PATHS[HOME], selectedSection === HOME), 18 | selectSiteHeaderLink('About', SECTIONS_PATHS[ABOUT], selectedSection === ABOUT), 19 | selectSiteHeaderLink('Account', SECTIONS_PATHS[ACCOUNT], selectedSection === ACCOUNT) 20 | ] 21 | }; 22 | }); 23 | 24 | export const selectSiteHeaderLink = memoizerific(20)((label, href, isSelected) => { 25 | return { 26 | label, 27 | href, 28 | isSelected, 29 | onClick: () => store.dispatch(updateURL(href)) 30 | }; 31 | }); 32 | -------------------------------------------------------------------------------- /src/state/items/reducers/items.js: -------------------------------------------------------------------------------- 1 | import { UPDATE_URL } from '../../site/actions/update-url'; 2 | 3 | import { HOME } from '../../site/constants/sections'; 4 | import { PATHS_SECTIONS } from '../../site/constants/paths'; 5 | 6 | const defaultItems = { 7 | 'id1': { 8 | name: 'Item #1' 9 | }, 10 | 'id2': { 11 | name: 'Item #2' 12 | }, 13 | 'id3': { 14 | name: 'Item #3' 15 | } 16 | }; 17 | 18 | export default function (items = defaultItems, action) { 19 | switch (action.type) { 20 | 21 | default: 22 | return items; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/state/items/reducers/selected-item-id.js: -------------------------------------------------------------------------------- 1 | import { UPDATE_URL } from '../../site/actions/update-url'; 2 | 3 | import { SECTIONS_PATHS } from '../../site/constants/paths'; 4 | 5 | export default function (selectedItem = null, action) { 6 | switch (action.type) { 7 | 8 | case UPDATE_URL: 9 | let parsedItemID = action.parsedURL.path.replace(SECTIONS_PATHS.ITEM + '/', ''); 10 | return parsedItemID !== action.parsedURL.path ? parsedItemID || null : null; 11 | 12 | default: 13 | return selectedItem; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/state/site/actions/update-url.js: -------------------------------------------------------------------------------- 1 | export const UPDATE_URL = 'UPDATE_URL'; 2 | 3 | export default function (newURL) { 4 | return (dispatch, getState) => { 5 | const { url } = getState(); 6 | if (newURL === url) { 7 | return; 8 | } 9 | 10 | dispatch({ 11 | type: UPDATE_URL, 12 | parsedURL: parseURL(newURL) 13 | }); 14 | }; 15 | } 16 | 17 | function parseURL(url) { 18 | const splitURL = url.split('?'); 19 | let path = splitURL[0].replace(/[/]+/g, '/'); 20 | let searchParams = {}; 21 | 22 | // make sure there isn't a trailing slash, except for home being a single slash: '/' 23 | if (path.length >= 2) { 24 | path = path.replace(/\/$/, ''); 25 | } 26 | else { 27 | path = '/'; 28 | } 29 | 30 | if (splitURL.length >= 2) { 31 | searchParams = parseSearchParams(splitURL[1]); 32 | } 33 | 34 | const finalURL = path + joinSearchParams(searchParams); 35 | 36 | return { 37 | path, 38 | searchParams, 39 | url: finalURL 40 | }; 41 | } 42 | 43 | function parseSearchParams(searchString) { 44 | let pairSplit; 45 | return (searchString || '').replace(/^\?/, '').split('&').reduce((p, pair) => { 46 | pairSplit = pair.split('='); 47 | if (pairSplit.length >= 1 && pairSplit[0].length >= 1) { 48 | p[decodeURIComponent(pairSplit[0])] = decodeURIComponent(pairSplit[1]) || ''; 49 | } 50 | return p; 51 | }, {}); 52 | } 53 | 54 | function joinSearchParams(searchParams) { 55 | let searchString = Object.keys(searchParams).reduce((p, paramKey) => p += `&${paramKey}=${searchParams[paramKey]}`, '?'); 56 | 57 | if (searchString.length <= 1) { 58 | return ''; 59 | } 60 | 61 | return searchString.replace('?&', '?'); 62 | } 63 | -------------------------------------------------------------------------------- /src/state/site/constants/paths.js: -------------------------------------------------------------------------------- 1 | import { HOME, ABOUT, ACCOUNT, ITEM } from '../../site/constants/sections'; 2 | 3 | export const PATHS_SECTIONS = { 4 | '/': HOME, 5 | '/about': ABOUT, 6 | '/account': ACCOUNT, 7 | '/item': ITEM 8 | }; 9 | export const SECTIONS_PATHS = Object.keys(PATHS_SECTIONS).reduce((p, key) => { p[PATHS_SECTIONS[key]] = key; return p; }, {}); 10 | 11 | export const DEFAULT_PATH = '/'; -------------------------------------------------------------------------------- /src/state/site/constants/sections.js: -------------------------------------------------------------------------------- 1 | export const HOME = 'HOME'; 2 | export const ABOUT = 'ABOUT'; 3 | export const ACCOUNT = 'ACCOUNT'; 4 | export const ITEM = 'ITEM'; 5 | -------------------------------------------------------------------------------- /src/state/site/reducers/selected-section.js: -------------------------------------------------------------------------------- 1 | import { UPDATE_URL } from '../../site/actions/update-url'; 2 | 3 | import { HOME } from '../../site/constants/sections'; 4 | import { PATHS_SECTIONS } from '../../site/constants/paths'; 5 | 6 | export default function (selectedSection = HOME, action) { 7 | switch (action.type) { 8 | 9 | case UPDATE_URL: 10 | return PATHS_SECTIONS[action.parsedURL.path] || HOME; 11 | 12 | default: 13 | return selectedSection; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/state/site/reducers/url.js: -------------------------------------------------------------------------------- 1 | import { UPDATE_URL } from '../../site/actions/update-url'; 2 | import { DEFAULT_PATH } from '../../site/constants/paths'; 3 | 4 | export default function (url = null, action) { 5 | switch (action.type) { 6 | 7 | case UPDATE_URL: 8 | return action.parsedURL.url; 9 | 10 | default: 11 | return url; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/state/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, combineReducers, applyMiddleware } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | 4 | // reducers 5 | import url from './site/reducers/url'; 6 | import selectedSection from './site/reducers/selected-section'; 7 | import items from './items/reducers/items'; 8 | import selectedItemID from './items/reducers/selected-item-id'; 9 | 10 | const reducers = { 11 | url, 12 | selectedSection, 13 | items, 14 | selectedItemID 15 | }; 16 | 17 | // console log middleware that logs all actions to console 18 | const consoleLog = store => next => action => { 19 | if (typeof action !== 'function') { 20 | console.log(action); 21 | } 22 | return next(action); 23 | }; 24 | 25 | // conditionally set middleware based on dev or prod env 26 | let middleWare; 27 | if (process.env.NODE_ENV !== 'production') { 28 | middleWare = applyMiddleware(consoleLog, thunk); 29 | } else { 30 | middleWare = applyMiddleware(thunk); 31 | } 32 | 33 | // create store 34 | export default createStore(combineReducers(reducers), middleWare); 35 | --------------------------------------------------------------------------------