From 229b5114311bd18a5dcf6178952abdf03bad003f Mon Sep 17 00:00:00 2001 From: Dan Delany Date: Tue, 8 Aug 2017 04:47:54 -0400 Subject: [PATCH] rebuild --- docs/build/assets/favicon.png | Bin 0 -> 3646 bytes docs/build/bundle.d8f206e4cd5f89e778eb.js | 173386 +++++++++++++++ docs/build/bundle.d8f206e4cd5f89e778eb.js.map | 1 + docs/build/index.html | 35 + docs/src/docs/XTicks/propDocs.json | 52 +- lib/AreaBarChart.js | 11 + lib/AreaBarChart.js.map | 2 +- lib/AreaChart.js | 10 + lib/AreaChart.js.map | 2 +- lib/AreaHeatmap.js | 10 + lib/AreaHeatmap.js.map | 2 +- lib/BarChart.js | 10 + lib/BarChart.js.map | 2 +- lib/ColorHeatmap.js | 10 + lib/ColorHeatmap.js.map | 2 +- lib/FunnelChart.js | 10 + lib/FunnelChart.js.map | 2 +- lib/Histogram.js | 10 + lib/Histogram.js.map | 2 +- lib/KernelDensityEstimation.js | 10 + lib/KernelDensityEstimation.js.map | 2 +- lib/LineChart.js | 4 +- lib/LineChart.js.map | 2 +- lib/MarkerLineChart.js | 10 + lib/MarkerLineChart.js.map | 2 +- lib/RangeBarChart.js | 10 + lib/RangeBarChart.js.map | 2 +- lib/ScatterPlot.js | 10 + lib/ScatterPlot.js.map | 2 +- lib/XTicks.js | 6 +- lib/XTicks.js.map | 2 +- lib/XYPlot.js | 2 +- lib/XYPlot.js.map | 2 +- lib/index.js | 28 + lib/index.js.map | 2 +- lib/utils/resolveXYScales.js | 15 +- lib/utils/resolveXYScales.js.map | 2 +- lib/utils/xyPropsEqual.js | 13 +- lib/utils/xyPropsEqual.js.map | 2 +- package.json | 4 +- 40 files changed, 173655 insertions(+), 36 deletions(-) create mode 100644 docs/build/assets/favicon.png create mode 100644 docs/build/bundle.d8f206e4cd5f89e778eb.js create mode 100644 docs/build/bundle.d8f206e4cd5f89e778eb.js.map create mode 100644 docs/build/index.html diff --git a/docs/build/assets/favicon.png b/docs/build/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..00aac0758a6e4d5a608478fcc03546052c81a968 GIT binary patch literal 3646 zcma)9XH-+!7QP8lLICNAA`(K8mP#Nb0~kVrpaMz}5G*0NU?c=cfuJCv3d$gDPzJ?d z!5Kh7%76ty5tPngMd{+8qcmj(5XBc9oi{(;n)U8l_nve1{l2}wv(Mh^uA9EYeTy<; zJpup#Wmgxvr)-q0-0;=1XR`ydLpH1vGW>*I;laXaCLaVG+2KJT(lv}30(yc>c1&a& zXa@jtGaPR}p`Y7!3M)Je!(72 U_NeI_jVL6CZIAM` zcEhZ|{M>dRox=Gb(i($9vv4+eqzw^+C*sINvL%v$!{e}c0v1O?<8c&g5(S4x ze!Wn#Xnb}s#gp#*HI{5;k2)X}Mo_TW=;&xnv=t_tAA-e`$z&{!fF%&nG6Y%>!xJ*a zXr93En+G~5VDUK-LQXgjx#E!-6fP3lqhw0|+Co@_o7>-xd4jKrlBEnQW=3G~7#ub% zY-L|x&;p?+_+J_S6D{zLi2$*lpdehtXUWbZ*zg-!mb-rs^bN>n{f&zd@ws32$!1|e zE*J*#gaVl;{1-(sQjR9v}SkwC~_F(aLvkfv@-7KbMc z7aTBKIm)kMK|Uu6WIOZ2!;oLjg2MS95fT z)4Hm7Lsb1 z-R(AE4$QZy)o*GcMYc8u8zDCxP;31`Ub4dh_ran1Y-PF|bjyhaOR|JY6OS!lutdfrZ17FXGen_vLKd)*+b11Ox>lkg+O7a>)K0$oTM-wZiSW zPVVg$B)F|v;}CM>!pB2NlH7N1loPGxNc`>X^Qf@c`QoRS#hXx7s59V}4%~Ox<3ftdFxKp0{7+|&gTYF z0y^+Z(dmEOTc;(RYQF}|8dE>+PH4HoN|}j$xRAMzAmv>>_}G%>bo|mYfC~FVZ{!{JUhE)-_ApdwQ4$(@PQYe7EOBH z%bHr~fU*nasKlM>08<0au+p|@LiZfmK@fK6Tz@*Qs)~HZeO6}*qgvKL2Z9Dv(w!0b;zht@E&>`h-huE1tA*4#V*`pk!0_d8<}W1ztPDb0P4B-wc{;CyDpzC zVsunC5Bx!Wc7OMHOuBS1XRWKt;v#INMnoS;0?j^=pek$V_wZCvD6QI-_o9 zL7`>Fs`UzRaZ%{UxyQRUcFp_yTUbn;?E#u-zslb%pJb>(QmF?&5KXeB3->ofE0Mf^ zj1DRG0X9@YFVa`Bn~wbU*~@#*N;`ad*oW8Rsu&}8JuzQ+)E@|}6rZ$n(uh!Vg5B+{ z>7e>XfQj-y0Sj9VPFq88rwh5t0XY?rw!wNi351@lS*>&lJg+2|9G7!tpBK$ceF>#< zYXQKJJi3N*(ta-AF2q2nw}u;Cbg5Y6rYlP0%dg!gsQ4<8PlBmvlT_ zye+r{8Ri}Cy3J_4s$W^I025DXT)Y{oGZuFpptc{x_zkVv1!=;;Uk}xvpVHU;<-R_K zUHi_|09gdgD=M7X(^Jc*+tlj_d`o*Zrg6DZ==4t zAyjlAB=}@&LLzw|E_lf43TlCwgkMuL36Gfv5K3#xs!iIiS-&)JnWOJoJU#m3GBaw) z=eB3{Fvrx4OUDR`W1sVlH52u!C+tZ)sNvTMH zHn2Xw>a}yHu1%Om00k@~#^s&$cuJfM6kU71{!i*+&$bgP71~K9osJ*0sI@aoYUpCh%i<4%1DOpRbDBaMesKIA$J{(cW>dLh^ z)v4Fwy=8ud7DG5eYtRbumY>Cq6klZSu*gHz>MxoX4+A zyN!MO>yq+bMD19p=3?+DVp-#gl#z_{OQ=mJF_x*9Ts5h8Q6r`wLzTa8grX*?e39s^}XE^oZ)rMqvaGG^k`CW%`?K#-l$9&Png zlZU|^yS=te(7iyc)Z?Z!t8u!2DwjP7HO&VeuUUpzs>1n;OPd4#a2vaFc1;f)2&G!2 zSDQ43T>liSs*PkROMe*ZL81JP zJ1qIC_mU2@=^(DA7j<+0s8BO$-I~F>sl}vQnHvGc0hm&MaCcOqYgpLkW1rY_uOO98 zw3?@%-lvM(5w4ox@Q9@ct8lbdjtX(lUPbq;b$%Q(9uHX!r11UcTcsp$<&Vyl;ZDCo H+n@L!%^U)F literal 0 HcmV?d00001 diff --git a/docs/build/bundle.d8f206e4cd5f89e778eb.js b/docs/build/bundle.d8f206e4cd5f89e778eb.js new file mode 100644 index 00000000..3ffb8635 --- /dev/null +++ b/docs/build/bundle.d8f206e4cd5f89e778eb.js @@ -0,0 +1,173386 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 376); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(9) + , core = __webpack_require__(49) + , hide = __webpack_require__(28) + , redefine = __webpack_require__(29) + , ctx = __webpack_require__(50) + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE] + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}) + , key, own, out, exp; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + // export native or passed + out = (own ? target : source)[key]; + // bind timers to global for call from export context + exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // extend global + if(target)redefine(target, key, out, type & $export.U); + // export + if(exports[key] != out)hide(exports, key, exp); + if(IS_PROTO && expProto[key] != out)expProto[key] = out; + } +}; +global.core = core; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {//! moment.js +//! version : 2.18.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +;(function (global, factory) { + true ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() +}(this, (function () { 'use strict'; + +var hookCallback; + +function hooks () { + return hookCallback.apply(null, arguments); +} + +// This is done to register the method called with moment() +// without creating circular dependencies. +function setHookCallback (callback) { + hookCallback = callback; +} + +function isArray(input) { + return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; +} + +function isObject(input) { + // IE8 will treat undefined and null as object if it wasn't for + // input != null + return input != null && Object.prototype.toString.call(input) === '[object Object]'; +} + +function isObjectEmpty(obj) { + var k; + for (k in obj) { + // even if its not own property I'd still call it non-empty + return false; + } + return true; +} + +function isUndefined(input) { + return input === void 0; +} + +function isNumber(input) { + return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]'; +} + +function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; +} + +function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; +} + +function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); +} + +function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; +} + +function createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); +} + +function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false, + parsedDateParts : [], + meridiem : null, + rfc2822 : false, + weekdayMismatch : false + }; +} + +function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; +} + +var some; +if (Array.prototype.some) { + some = Array.prototype.some; +} else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; +} + +var some$1 = some; + +function isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + var parsedParts = some$1.call(flags.parsedDateParts, function (i) { + return i != null; + }); + var isNowValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.invalidWeekday && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); + + if (m._strict) { + isNowValid = isNowValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + + if (Object.isFrozen == null || !Object.isFrozen(m)) { + m._isValid = isNowValid; + } + else { + return isNowValid; + } + } + return m._isValid; +} + +function createInvalid (flags) { + var m = createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; +} + +// Plugins that add properties should also add the key here (null value), +// so we can properly clone ourselves. +var momentProperties = hooks.momentProperties = []; + +function copyConfig(to, from) { + var i, prop, val; + + if (!isUndefined(from._isAMomentObject)) { + to._isAMomentObject = from._isAMomentObject; + } + if (!isUndefined(from._i)) { + to._i = from._i; + } + if (!isUndefined(from._f)) { + to._f = from._f; + } + if (!isUndefined(from._l)) { + to._l = from._l; + } + if (!isUndefined(from._strict)) { + to._strict = from._strict; + } + if (!isUndefined(from._tzm)) { + to._tzm = from._tzm; + } + if (!isUndefined(from._isUTC)) { + to._isUTC = from._isUTC; + } + if (!isUndefined(from._offset)) { + to._offset = from._offset; + } + if (!isUndefined(from._pf)) { + to._pf = getParsingFlags(from); + } + if (!isUndefined(from._locale)) { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i = 0; i < momentProperties.length; i++) { + prop = momentProperties[i]; + val = from[prop]; + if (!isUndefined(val)) { + to[prop] = val; + } + } + } + + return to; +} + +var updateInProgress = false; + +// Moment prototype object +function Moment(config) { + copyConfig(this, config); + this._d = new Date(config._d != null ? config._d.getTime() : NaN); + if (!this.isValid()) { + this._d = new Date(NaN); + } + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + hooks.updateOffset(this); + updateInProgress = false; + } +} + +function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); +} + +function absFloor (number) { + if (number < 0) { + // -0 -> 0 + return Math.ceil(number) || 0; + } else { + return Math.floor(number); + } +} + +function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + value = absFloor(coercedNumber); + } + + return value; +} + +// compare two arrays, return the number of differences +function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; +} + +function warn(msg) { + if (hooks.suppressDeprecationWarnings === false && + (typeof console !== 'undefined') && console.warn) { + console.warn('Deprecation warning: ' + msg); + } +} + +function deprecate(msg, fn) { + var firstTime = true; + + return extend(function () { + if (hooks.deprecationHandler != null) { + hooks.deprecationHandler(null, msg); + } + if (firstTime) { + var args = []; + var arg; + for (var i = 0; i < arguments.length; i++) { + arg = ''; + if (typeof arguments[i] === 'object') { + arg += '\n[' + i + '] '; + for (var key in arguments[0]) { + arg += key + ': ' + arguments[0][key] + ', '; + } + arg = arg.slice(0, -2); // Remove trailing comma and space + } else { + arg = arguments[i]; + } + args.push(arg); + } + warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); +} + +var deprecations = {}; + +function deprecateSimple(name, msg) { + if (hooks.deprecationHandler != null) { + hooks.deprecationHandler(name, msg); + } + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } +} + +hooks.suppressDeprecationWarnings = false; +hooks.deprecationHandler = null; + +function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; +} + +function set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (isFunction(prop)) { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + this._config = config; + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _dayOfMonthOrdinalParse. + // TODO: Remove "ordinalParse" fallback in next major release. + this._dayOfMonthOrdinalParseLenient = new RegExp( + (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + + '|' + (/\d{1,2}/).source); +} + +function mergeConfigs(parentConfig, childConfig) { + var res = extend({}, parentConfig), prop; + for (prop in childConfig) { + if (hasOwnProp(childConfig, prop)) { + if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { + res[prop] = {}; + extend(res[prop], parentConfig[prop]); + extend(res[prop], childConfig[prop]); + } else if (childConfig[prop] != null) { + res[prop] = childConfig[prop]; + } else { + delete res[prop]; + } + } + } + for (prop in parentConfig) { + if (hasOwnProp(parentConfig, prop) && + !hasOwnProp(childConfig, prop) && + isObject(parentConfig[prop])) { + // make sure changes to properties don't modify parent config + res[prop] = extend({}, res[prop]); + } + } + return res; +} + +function Locale(config) { + if (config != null) { + this.set(config); + } +} + +var keys; + +if (Object.keys) { + keys = Object.keys; +} else { + keys = function (obj) { + var i, res = []; + for (i in obj) { + if (hasOwnProp(obj, i)) { + res.push(i); + } + } + return res; + }; +} + +var keys$1 = keys; + +var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' +}; + +function calendar (key, mom, now) { + var output = this._calendar[key] || this._calendar['sameElse']; + return isFunction(output) ? output.call(mom, now) : output; +} + +var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' +}; + +function longDateFormat (key) { + var format = this._longDateFormat[key], + formatUpper = this._longDateFormat[key.toUpperCase()]; + + if (format || !formatUpper) { + return format; + } + + this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + + return this._longDateFormat[key]; +} + +var defaultInvalidDate = 'Invalid date'; + +function invalidDate () { + return this._invalidDate; +} + +var defaultOrdinal = '%d'; +var defaultDayOfMonthOrdinalParse = /\d{1,2}/; + +function ordinal (number) { + return this._ordinal.replace('%d', number); +} + +var defaultRelativeTime = { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + ss : '%d seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' +}; + +function relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (isFunction(output)) ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); +} + +function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return isFunction(format) ? format(output) : format.replace(/%s/i, output); +} + +var aliases = {}; + +function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; +} + +function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; +} + +function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; +} + +var priorities = {}; + +function addUnitPriority(unit, priority) { + priorities[unit] = priority; +} + +function getPrioritizedUnits(unitsObj) { + var units = []; + for (var u in unitsObj) { + units.push({unit: u, priority: priorities[u]}); + } + units.sort(function (a, b) { + return a.priority - b.priority; + }); + return units; +} + +function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + set$1(this, unit, value); + hooks.updateOffset(this, keepTime); + return this; + } else { + return get(this, unit); + } + }; +} + +function get (mom, unit) { + return mom.isValid() ? + mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; +} + +function set$1 (mom, unit, value) { + if (mom.isValid()) { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } +} + +// MOMENTS + +function stringGet (units) { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](); + } + return this; +} + + +function stringSet (units, value) { + if (typeof units === 'object') { + units = normalizeObjectUnits(units); + var prioritized = getPrioritizedUnits(units); + for (var i = 0; i < prioritized.length; i++) { + this[prioritized[i].unit](units[prioritized[i].unit]); + } + } else { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](value); + } + } + return this; +} + +function zeroFill(number, targetLength, forceSign) { + var absNumber = '' + Math.abs(number), + zerosToFill = targetLength - absNumber.length, + sign = number >= 0; + return (sign ? (forceSign ? '+' : '') : '-') + + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; +} + +var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + +var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + +var formatFunctions = {}; + +var formatTokenFunctions = {}; + +// token: 'M' +// padded: ['MM', 2] +// ordinal: 'Mo' +// callback: function () { this.month() + 1 } +function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } +} + +function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); +} + +function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = '', i; + for (i = 0; i < length; i++) { + output += isFunction(array[i]) ? array[i].call(mom, format) : array[i]; + } + return output; + }; +} + +// format date using native date object +function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + return formatFunctions[format](m); +} + +function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; +} + +var match1 = /\d/; // 0 - 9 +var match2 = /\d\d/; // 00 - 99 +var match3 = /\d{3}/; // 000 - 999 +var match4 = /\d{4}/; // 0000 - 9999 +var match6 = /[+-]?\d{6}/; // -999999 - 999999 +var match1to2 = /\d\d?/; // 0 - 99 +var match3to4 = /\d\d\d\d?/; // 999 - 9999 +var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 +var match1to3 = /\d{1,3}/; // 0 - 999 +var match1to4 = /\d{1,4}/; // 0 - 9999 +var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + +var matchUnsigned = /\d+/; // 0 - inf +var matchSigned = /[+-]?\d+/; // -inf - inf + +var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z +var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z + +var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + +// any word (or two) characters or numbers including two/three word month in arabic. +// includes scottish gaelic two word and hyphenated months +var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + +var regexes = {}; + +function addRegexToken (token, regex, strictRegex) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; +} + +function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); +} + +// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript +function unescapeFormat(s) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + })); +} + +function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); +} + +var tokens = {}; + +function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (isNumber(callback)) { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } +} + +function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); +} + +function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } +} + +var YEAR = 0; +var MONTH = 1; +var DATE = 2; +var HOUR = 3; +var MINUTE = 4; +var SECOND = 5; +var MILLISECOND = 6; +var WEEK = 7; +var WEEKDAY = 8; + +var indexOf; + +if (Array.prototype.indexOf) { + indexOf = Array.prototype.indexOf; +} else { + indexOf = function (o) { + // I know + var i; + for (i = 0; i < this.length; ++i) { + if (this[i] === o) { + return i; + } + } + return -1; + }; +} + +var indexOf$1 = indexOf; + +function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); +} + +// FORMATTING + +addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; +}); + +addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); +}); + +addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); +}); + +// ALIASES + +addUnitAlias('month', 'M'); + +// PRIORITY + +addUnitPriority('month', 8); + +// PARSING + +addRegexToken('M', match1to2); +addRegexToken('MM', match1to2, match2); +addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); +}); +addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); +}); + +addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; +}); + +addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } +}); + +// LOCALES + +var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/; +var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); +function localeMonths (m, format) { + if (!m) { + return isArray(this._months) ? this._months : + this._months['standalone']; + } + return isArray(this._months) ? this._months[m.month()] : + this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; +} + +var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); +function localeMonthsShort (m, format) { + if (!m) { + return isArray(this._monthsShort) ? this._monthsShort : + this._monthsShort['standalone']; + } + return isArray(this._monthsShort) ? this._monthsShort[m.month()] : + this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; +} + +function handleStrictParse(monthName, format, strict) { + var i, ii, mom, llc = monthName.toLocaleLowerCase(); + if (!this._monthsParse) { + // this is not used + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + for (i = 0; i < 12; ++i) { + mom = createUTC([2000, i]); + this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); + this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'MMM') { + ii = indexOf$1.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf$1.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'MMM') { + ii = indexOf$1.call(this._shortMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf$1.call(this._longMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } +} + +function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (this._monthsParseExact) { + return handleStrictParse.call(this, monthName, format, strict); + } + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + // TODO: add sorting + // Sorting makes sure if one month (or abbr) is a prefix of another + // see sorting in computeMonthsParse + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } +} + +// MOMENTS + +function setMonth (mom, value) { + var dayOfMonth; + + if (!mom.isValid()) { + // No op + return mom; + } + + if (typeof value === 'string') { + if (/^\d+$/.test(value)) { + value = toInt(value); + } else { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (!isNumber(value)) { + return mom; + } + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; +} + +function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + hooks.updateOffset(this, true); + return this; + } else { + return get(this, 'Month'); + } +} + +function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); +} + +var defaultMonthsShortRegex = matchWord; +function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + if (!hasOwnProp(this, '_monthsShortRegex')) { + this._monthsShortRegex = defaultMonthsShortRegex; + } + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } +} + +var defaultMonthsRegex = matchWord; +function monthsRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + if (!hasOwnProp(this, '_monthsRegex')) { + this._monthsRegex = defaultMonthsRegex; + } + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } +} + +function computeMonthsParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var shortPieces = [], longPieces = [], mixedPieces = [], + i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + shortPieces.push(this.monthsShort(mom, '')); + longPieces.push(this.months(mom, '')); + mixedPieces.push(this.months(mom, '')); + mixedPieces.push(this.monthsShort(mom, '')); + } + // Sorting makes sure if one month (or abbr) is a prefix of another it + // will match the longer piece. + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 12; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + } + for (i = 0; i < 24; i++) { + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); +} + +// FORMATTING + +addFormatToken('Y', 0, 0, function () { + var y = this.year(); + return y <= 9999 ? '' + y : '+' + y; +}); + +addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; +}); + +addFormatToken(0, ['YYYY', 4], 0, 'year'); +addFormatToken(0, ['YYYYY', 5], 0, 'year'); +addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + +// ALIASES + +addUnitAlias('year', 'y'); + +// PRIORITIES + +addUnitPriority('year', 1); + +// PARSING + +addRegexToken('Y', matchSigned); +addRegexToken('YY', match1to2, match2); +addRegexToken('YYYY', match1to4, match4); +addRegexToken('YYYYY', match1to6, match6); +addRegexToken('YYYYYY', match1to6, match6); + +addParseToken(['YYYYY', 'YYYYYY'], YEAR); +addParseToken('YYYY', function (input, array) { + array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); +}); +addParseToken('YY', function (input, array) { + array[YEAR] = hooks.parseTwoDigitYear(input); +}); +addParseToken('Y', function (input, array) { + array[YEAR] = parseInt(input, 10); +}); + +// HELPERS + +function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; +} + +function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; +} + +// HOOKS + +hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); +}; + +// MOMENTS + +var getSetYear = makeGetSet('FullYear', true); + +function getIsLeapYear () { + return isLeapYear(this.year()); +} + +function createDate (y, m, d, h, M, s, ms) { + // can't just apply() to create a date: + // https://stackoverflow.com/q/181348 + var date = new Date(y, m, d, h, M, s, ms); + + // the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { + date.setFullYear(y); + } + return date; +} + +function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + + // the Date.UTC function remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { + date.setUTCFullYear(y); + } + return date; +} + +// start-of-first-week - start-of-year +function firstWeekOffset(year, dow, doy) { + var // first-week day -- which january is always in the first week (4 for iso, 1 for other) + fwd = 7 + dow - doy, + // first-week day local weekday -- which local weekday is fwd + fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; + + return -fwdlw + fwd - 1; +} + +// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday +function dayOfYearFromWeeks(year, week, weekday, dow, doy) { + var localWeekday = (7 + weekday - dow) % 7, + weekOffset = firstWeekOffset(year, dow, doy), + dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, + resYear, resDayOfYear; + + if (dayOfYear <= 0) { + resYear = year - 1; + resDayOfYear = daysInYear(resYear) + dayOfYear; + } else if (dayOfYear > daysInYear(year)) { + resYear = year + 1; + resDayOfYear = dayOfYear - daysInYear(year); + } else { + resYear = year; + resDayOfYear = dayOfYear; + } + + return { + year: resYear, + dayOfYear: resDayOfYear + }; +} + +function weekOfYear(mom, dow, doy) { + var weekOffset = firstWeekOffset(mom.year(), dow, doy), + week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, + resWeek, resYear; + + if (week < 1) { + resYear = mom.year() - 1; + resWeek = week + weeksInYear(resYear, dow, doy); + } else if (week > weeksInYear(mom.year(), dow, doy)) { + resWeek = week - weeksInYear(mom.year(), dow, doy); + resYear = mom.year() + 1; + } else { + resYear = mom.year(); + resWeek = week; + } + + return { + week: resWeek, + year: resYear + }; +} + +function weeksInYear(year, dow, doy) { + var weekOffset = firstWeekOffset(year, dow, doy), + weekOffsetNext = firstWeekOffset(year + 1, dow, doy); + return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; +} + +// FORMATTING + +addFormatToken('w', ['ww', 2], 'wo', 'week'); +addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + +// ALIASES + +addUnitAlias('week', 'w'); +addUnitAlias('isoWeek', 'W'); + +// PRIORITIES + +addUnitPriority('week', 5); +addUnitPriority('isoWeek', 5); + +// PARSING + +addRegexToken('w', match1to2); +addRegexToken('ww', match1to2, match2); +addRegexToken('W', match1to2); +addRegexToken('WW', match1to2, match2); + +addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); +}); + +// HELPERS + +// LOCALES + +function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; +} + +var defaultLocaleWeek = { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. +}; + +function localeFirstDayOfWeek () { + return this._week.dow; +} + +function localeFirstDayOfYear () { + return this._week.doy; +} + +// MOMENTS + +function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); +} + +function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); +} + +// FORMATTING + +addFormatToken('d', 0, 'do', 'day'); + +addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); +}); + +addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); +}); + +addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); +}); + +addFormatToken('e', 0, 0, 'weekday'); +addFormatToken('E', 0, 0, 'isoWeekday'); + +// ALIASES + +addUnitAlias('day', 'd'); +addUnitAlias('weekday', 'e'); +addUnitAlias('isoWeekday', 'E'); + +// PRIORITY +addUnitPriority('day', 11); +addUnitPriority('weekday', 11); +addUnitPriority('isoWeekday', 11); + +// PARSING + +addRegexToken('d', match1to2); +addRegexToken('e', match1to2); +addRegexToken('E', match1to2); +addRegexToken('dd', function (isStrict, locale) { + return locale.weekdaysMinRegex(isStrict); +}); +addRegexToken('ddd', function (isStrict, locale) { + return locale.weekdaysShortRegex(isStrict); +}); +addRegexToken('dddd', function (isStrict, locale) { + return locale.weekdaysRegex(isStrict); +}); + +addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { + var weekday = config._locale.weekdaysParse(input, token, config._strict); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } +}); + +addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); +}); + +// HELPERS + +function parseWeekday(input, locale) { + if (typeof input !== 'string') { + return input; + } + + if (!isNaN(input)) { + return parseInt(input, 10); + } + + input = locale.weekdaysParse(input); + if (typeof input === 'number') { + return input; + } + + return null; +} + +function parseIsoWeekday(input, locale) { + if (typeof input === 'string') { + return locale.weekdaysParse(input) % 7 || 7; + } + return isNaN(input) ? null : input; +} + +// LOCALES + +var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); +function localeWeekdays (m, format) { + if (!m) { + return isArray(this._weekdays) ? this._weekdays : + this._weekdays['standalone']; + } + return isArray(this._weekdays) ? this._weekdays[m.day()] : + this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; +} + +var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); +function localeWeekdaysShort (m) { + return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort; +} + +var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); +function localeWeekdaysMin (m) { + return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin; +} + +function handleStrictParse$1(weekdayName, format, strict) { + var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._shortWeekdaysParse = []; + this._minWeekdaysParse = []; + + for (i = 0; i < 7; ++i) { + mom = createUTC([2000, 1]).day(i); + this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); + this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); + this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'dddd') { + ii = indexOf$1.call(this._weekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf$1.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf$1.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'dddd') { + ii = indexOf$1.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf$1.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf$1.call(this._minWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf$1.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } +} + +function localeWeekdaysParse (weekdayName, format, strict) { + var i, mom, regex; + + if (this._weekdaysParseExact) { + return handleStrictParse$1.call(this, weekdayName, format, strict); + } + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._minWeekdaysParse = []; + this._shortWeekdaysParse = []; + this._fullWeekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + + mom = createUTC([2000, 1]).day(i); + if (strict && !this._fullWeekdaysParse[i]) { + this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i'); + this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i'); + this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i'); + } + if (!this._weekdaysParse[i]) { + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } +} + +// MOMENTS + +function getSetDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } +} + +function getSetLocaleDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); +} + +function getSetISODayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + + if (input != null) { + var weekday = parseIsoWeekday(input, this.localeData()); + return this.day(this.day() % 7 ? weekday : weekday - 7); + } else { + return this.day() || 7; + } +} + +var defaultWeekdaysRegex = matchWord; +function weekdaysRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysStrictRegex; + } else { + return this._weekdaysRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysRegex')) { + this._weekdaysRegex = defaultWeekdaysRegex; + } + return this._weekdaysStrictRegex && isStrict ? + this._weekdaysStrictRegex : this._weekdaysRegex; + } +} + +var defaultWeekdaysShortRegex = matchWord; +function weekdaysShortRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysShortStrictRegex; + } else { + return this._weekdaysShortRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysShortRegex')) { + this._weekdaysShortRegex = defaultWeekdaysShortRegex; + } + return this._weekdaysShortStrictRegex && isStrict ? + this._weekdaysShortStrictRegex : this._weekdaysShortRegex; + } +} + +var defaultWeekdaysMinRegex = matchWord; +function weekdaysMinRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysMinStrictRegex; + } else { + return this._weekdaysMinRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysMinRegex')) { + this._weekdaysMinRegex = defaultWeekdaysMinRegex; + } + return this._weekdaysMinStrictRegex && isStrict ? + this._weekdaysMinStrictRegex : this._weekdaysMinRegex; + } +} + + +function computeWeekdaysParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], + i, mom, minp, shortp, longp; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, 1]).day(i); + minp = this.weekdaysMin(mom, ''); + shortp = this.weekdaysShort(mom, ''); + longp = this.weekdays(mom, ''); + minPieces.push(minp); + shortPieces.push(shortp); + longPieces.push(longp); + mixedPieces.push(minp); + mixedPieces.push(shortp); + mixedPieces.push(longp); + } + // Sorting makes sure if one weekday (or abbr) is a prefix of another it + // will match the longer piece. + minPieces.sort(cmpLenRev); + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 7; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._weekdaysShortRegex = this._weekdaysRegex; + this._weekdaysMinRegex = this._weekdaysRegex; + + this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); +} + +// FORMATTING + +function hFormat() { + return this.hours() % 12 || 12; +} + +function kFormat() { + return this.hours() || 24; +} + +addFormatToken('H', ['HH', 2], 0, 'hour'); +addFormatToken('h', ['hh', 2], 0, hFormat); +addFormatToken('k', ['kk', 2], 0, kFormat); + +addFormatToken('hmm', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); +}); + +addFormatToken('hmmss', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); +}); + +addFormatToken('Hmm', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2); +}); + +addFormatToken('Hmmss', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); +}); + +function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); +} + +meridiem('a', true); +meridiem('A', false); + +// ALIASES + +addUnitAlias('hour', 'h'); + +// PRIORITY +addUnitPriority('hour', 13); + +// PARSING + +function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; +} + +addRegexToken('a', matchMeridiem); +addRegexToken('A', matchMeridiem); +addRegexToken('H', match1to2); +addRegexToken('h', match1to2); +addRegexToken('k', match1to2); +addRegexToken('HH', match1to2, match2); +addRegexToken('hh', match1to2, match2); +addRegexToken('kk', match1to2, match2); + +addRegexToken('hmm', match3to4); +addRegexToken('hmmss', match5to6); +addRegexToken('Hmm', match3to4); +addRegexToken('Hmmss', match5to6); + +addParseToken(['H', 'HH'], HOUR); +addParseToken(['k', 'kk'], function (input, array, config) { + var kInput = toInt(input); + array[HOUR] = kInput === 24 ? 0 : kInput; +}); +addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; +}); +addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; +}); +addParseToken('hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + getParsingFlags(config).bigHour = true; +}); +addParseToken('hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + getParsingFlags(config).bigHour = true; +}); +addParseToken('Hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); +}); +addParseToken('Hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); +}); + +// LOCALES + +function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); +} + +var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; +function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } +} + + +// MOMENTS + +// Setting the hour should keep the time, because the user explicitly +// specified which hour he wants. So trying to maintain the same hour (in +// a new timezone) makes sense. Adding/subtracting hours does not follow +// this rule. +var getSetHour = makeGetSet('Hours', true); + +// months +// week +// weekdays +// meridiem +var baseConfig = { + calendar: defaultCalendar, + longDateFormat: defaultLongDateFormat, + invalidDate: defaultInvalidDate, + ordinal: defaultOrdinal, + dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse, + relativeTime: defaultRelativeTime, + + months: defaultLocaleMonths, + monthsShort: defaultLocaleMonthsShort, + + week: defaultLocaleWeek, + + weekdays: defaultLocaleWeekdays, + weekdaysMin: defaultLocaleWeekdaysMin, + weekdaysShort: defaultLocaleWeekdaysShort, + + meridiemParse: defaultLocaleMeridiemParse +}; + +// internal storage for locale config files +var locales = {}; +var localeFamilies = {}; +var globalLocale; + +function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; +} + +// pick the locale from the array +// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each +// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root +function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; +} + +function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && (typeof module !== 'undefined') && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + __webpack_require__(740)("./" + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; +} + +// This function will load locale and then set the global locale. If +// no arguments are passed in, it will simply return the current global +// locale key. +function getSetGlobalLocale (key, values) { + var data; + if (key) { + if (isUndefined(values)) { + data = getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; +} + +function defineLocale (name, config) { + if (config !== null) { + var parentConfig = baseConfig; + config.abbr = name; + if (locales[name] != null) { + deprecateSimple('defineLocaleOverride', + 'use moment.updateLocale(localeName, config) to change ' + + 'an existing locale. moment.defineLocale(localeName, ' + + 'config) should only be used for creating a new locale ' + + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); + parentConfig = locales[name]._config; + } else if (config.parentLocale != null) { + if (locales[config.parentLocale] != null) { + parentConfig = locales[config.parentLocale]._config; + } else { + if (!localeFamilies[config.parentLocale]) { + localeFamilies[config.parentLocale] = []; + } + localeFamilies[config.parentLocale].push({ + name: name, + config: config + }); + return null; + } + } + locales[name] = new Locale(mergeConfigs(parentConfig, config)); + + if (localeFamilies[name]) { + localeFamilies[name].forEach(function (x) { + defineLocale(x.name, x.config); + }); + } + + // backwards compat for now: also set the locale + // make sure we set the locale AFTER all child locales have been + // created, so we won't end up with the child locale set. + getSetGlobalLocale(name); + + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } +} + +function updateLocale(name, config) { + if (config != null) { + var locale, parentConfig = baseConfig; + // MERGE + if (locales[name] != null) { + parentConfig = locales[name]._config; + } + config = mergeConfigs(parentConfig, config); + locale = new Locale(config); + locale.parentLocale = locales[name]; + locales[name] = locale; + + // backwards compat for now: also set the locale + getSetGlobalLocale(name); + } else { + // pass null for config to unupdate, useful for tests + if (locales[name] != null) { + if (locales[name].parentLocale != null) { + locales[name] = locales[name].parentLocale; + } else if (locales[name] != null) { + delete locales[name]; + } + } + } + return locales[name]; +} + +// returns locale data +function getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); +} + +function listLocales() { + return keys$1(locales); +} + +function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + if (getParsingFlags(m)._overflowWeeks && overflow === -1) { + overflow = WEEK; + } + if (getParsingFlags(m)._overflowWeekday && overflow === -1) { + overflow = WEEKDAY; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; +} + +// iso 8601 regex +// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) +var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; +var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; + +var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; + +var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], + ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], + ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], + ['GGGG-[W]WW', /\d{4}-W\d\d/, false], + ['YYYY-DDD', /\d{4}-\d{3}/], + ['YYYY-MM', /\d{4}-\d\d/, false], + ['YYYYYYMMDD', /[+-]\d{10}/], + ['YYYYMMDD', /\d{8}/], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{3}/], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{7}/] +]; + +// iso time formats and regexes +var isoTimes = [ + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], + ['HH:mm:ss', /\d\d:\d\d:\d\d/], + ['HH:mm', /\d\d:\d\d/], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], + ['HHmmss', /\d\d\d\d\d\d/], + ['HHmm', /\d\d\d\d/], + ['HH', /\d\d/] +]; + +var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + +// date from iso format +function configFromISO(config) { + var i, l, + string = config._i, + match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), + allowTime, dateFormat, timeFormat, tzFormat; + + if (match) { + getParsingFlags(config).iso = true; + + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(match[1])) { + dateFormat = isoDates[i][0]; + allowTime = isoDates[i][2] !== false; + break; + } + } + if (dateFormat == null) { + config._isValid = false; + return; + } + if (match[3]) { + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + timeFormat = (match[2] || ' ') + isoTimes[i][0]; + break; + } + } + if (timeFormat == null) { + config._isValid = false; + return; + } + } + if (!allowTime && timeFormat != null) { + config._isValid = false; + return; + } + if (match[4]) { + if (tzRegex.exec(match[4])) { + tzFormat = 'Z'; + } else { + config._isValid = false; + return; + } + } + config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); + configFromStringAndFormat(config); + } else { + config._isValid = false; + } +} + +// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 +var basicRfcRegex = /^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/; + +// date and time from ref 2822 format +function configFromRFC2822(config) { + var string, match, dayFormat, + dateFormat, timeFormat, tzFormat; + var timezones = { + ' GMT': ' +0000', + ' EDT': ' -0400', + ' EST': ' -0500', + ' CDT': ' -0500', + ' CST': ' -0600', + ' MDT': ' -0600', + ' MST': ' -0700', + ' PDT': ' -0700', + ' PST': ' -0800' + }; + var military = 'YXWVUTSRQPONZABCDEFGHIKLM'; + var timezone, timezoneIndex; + + string = config._i + .replace(/\([^\)]*\)|[\n\t]/g, ' ') // Remove comments and folding whitespace + .replace(/(\s\s+)/g, ' ') // Replace multiple-spaces with a single space + .replace(/^\s|\s$/g, ''); // Remove leading and trailing spaces + match = basicRfcRegex.exec(string); + + if (match) { + dayFormat = match[1] ? 'ddd' + ((match[1].length === 5) ? ', ' : ' ') : ''; + dateFormat = 'D MMM ' + ((match[2].length > 10) ? 'YYYY ' : 'YY '); + timeFormat = 'HH:mm' + (match[4] ? ':ss' : ''); + + // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check. + if (match[1]) { // day of week given + var momentDate = new Date(match[2]); + var momentDay = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][momentDate.getDay()]; + + if (match[1].substr(0,3) !== momentDay) { + getParsingFlags(config).weekdayMismatch = true; + config._isValid = false; + return; + } + } + + switch (match[5].length) { + case 2: // military + if (timezoneIndex === 0) { + timezone = ' +0000'; + } else { + timezoneIndex = military.indexOf(match[5][1].toUpperCase()) - 12; + timezone = ((timezoneIndex < 0) ? ' -' : ' +') + + (('' + timezoneIndex).replace(/^-?/, '0')).match(/..$/)[0] + '00'; + } + break; + case 4: // Zone + timezone = timezones[match[5]]; + break; + default: // UT or +/-9999 + timezone = timezones[' GMT']; + } + match[5] = timezone; + config._i = match.splice(1).join(''); + tzFormat = ' ZZ'; + config._f = dayFormat + dateFormat + timeFormat + tzFormat; + configFromStringAndFormat(config); + getParsingFlags(config).rfc2822 = true; + } else { + config._isValid = false; + } +} + +// date from iso format or fallback +function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + } else { + return; + } + + configFromRFC2822(config); + if (config._isValid === false) { + delete config._isValid; + } else { + return; + } + + // Final attempt, use Input Fallback + hooks.createFromInputFallback(config); +} + +hooks.createFromInputFallback = deprecate( + 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + + 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + + 'discouraged and will be removed in an upcoming major release. Please refer to ' + + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } +); + +// Pick the first defined of two or three arguments. +function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; +} + +function currentDateArray(config) { + // hooks is actually the exported moment object + var nowValue = new Date(hooks.now()); + if (config._useUTC) { + return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; + } + return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; +} + +// convert an array to a date. +// the array should mirror the parameters below +// note: all values past the year are optional and will default to the lowest possible value. +// [year, month, day , hour, minute, second, millisecond] +function configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear != null) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } +} + +function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + if (weekday < 1 || weekday > 7) { + weekdayOverflow = true; + } + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + var curWeek = weekOfYear(createLocal(), dow, doy); + + weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); + + // Default to current week. + week = defaults(w.w, curWeek.week); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < 0 || weekday > 6) { + weekdayOverflow = true; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + if (w.e < 0 || w.e > 6) { + weekdayOverflow = true; + } + } else { + // default to begining of week + weekday = dow; + } + } + if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { + getParsingFlags(config)._overflowWeeks = true; + } else if (weekdayOverflow != null) { + getParsingFlags(config)._overflowWeekday = true; + } else { + temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } +} + +// constant that refers to the ISO standard +hooks.ISO_8601 = function () {}; + +// constant that refers to the RFC 2822 form +hooks.RFC_2822 = function () {}; + +// date from string and format string +function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === hooks.ISO_8601) { + configFromISO(config); + return; + } + if (config._f === hooks.RFC_2822) { + configFromRFC2822(config); + return; + } + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + // console.log('token', token, 'parsedInput', parsedInput, + // 'regex', getParseRegexForToken(token, config)); + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (config._a[HOUR] <= 12 && + getParsingFlags(config).bigHour === true && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); +} + + +function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } +} + +// date from string and array of format strings +function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); +} + +function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { + return obj && parseInt(obj, 10); + }); + + configFromArray(config); +} + +function createFromConfig (config) { + var res = new Moment(checkOverflow(prepareConfig(config))); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; +} + +function prepareConfig (config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isDate(input)) { + config._d = input; + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (format) { + configFromStringAndFormat(config); + } else { + configFromInput(config); + } + + if (!isValid(config)) { + config._d = null; + } + + return config; +} + +function configFromInput(config) { + var input = config._i; + if (isUndefined(input)) { + config._d = new Date(hooks.now()); + } else if (isDate(input)) { + config._d = new Date(input.valueOf()); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (isObject(input)) { + configFromObject(config); + } else if (isNumber(input)) { + // from milliseconds + config._d = new Date(input); + } else { + hooks.createFromInputFallback(config); + } +} + +function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (locale === true || locale === false) { + strict = locale; + locale = undefined; + } + + if ((isObject(input) && isObjectEmpty(input)) || + (isArray(input) && input.length === 0)) { + input = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); +} + +function createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); +} + +var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other < this ? this : other; + } else { + return createInvalid(); + } + } +); + +var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other > this ? this : other; + } else { + return createInvalid(); + } + } +); + +// Pick a moment m from moments so that m[fn](other) is true for all +// other. This relies on the function fn to be transitive. +// +// moments should either be an array of moment objects or an array, whose +// first element is an array of moment objects. +function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (!moments[i].isValid() || moments[i][fn](res)) { + res = moments[i]; + } + } + return res; +} + +// TODO: Use [].sort instead? +function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); +} + +function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); +} + +var now = function () { + return Date.now ? Date.now() : +(new Date()); +}; + +var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond']; + +function isDurationValid(m) { + for (var key in m) { + if (!(ordering.indexOf(key) !== -1 && (m[key] == null || !isNaN(m[key])))) { + return false; + } + } + + var unitHasDecimal = false; + for (var i = 0; i < ordering.length; ++i) { + if (m[ordering[i]]) { + if (unitHasDecimal) { + return false; // only allow non-integers for smallest unit + } + if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) { + unitHasDecimal = true; + } + } + } + + return true; +} + +function isValid$1() { + return this._isValid; +} + +function createInvalid$1() { + return createDuration(NaN); +} + +function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + this._isValid = isDurationValid(normalizedInput); + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = getLocale(); + + this._bubble(); +} + +function isDuration (obj) { + return obj instanceof Duration; +} + +function absRound (number) { + if (number < 0) { + return Math.round(-1 * number) * -1; + } else { + return Math.round(number); + } +} + +// FORMATTING + +function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); +} + +offset('Z', ':'); +offset('ZZ', ''); + +// PARSING + +addRegexToken('Z', matchShortOffset); +addRegexToken('ZZ', matchShortOffset); +addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(matchShortOffset, input); +}); + +// HELPERS + +// timezone chunker +// '+10:00' > ['10', '00'] +// '-1530' > ['-15', '30'] +var chunkOffset = /([\+\-]|\d\d)/gi; + +function offsetFromString(matcher, string) { + var matches = (string || '').match(matcher); + + if (matches === null) { + return null; + } + + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return minutes === 0 ? + 0 : + parts[0] === '+' ? minutes : -minutes; +} + +// Return a moment from input, that is local/utc/zone equivalent to model. +function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); + // Use low-level api, because this fn is low-level api. + res._d.setTime(res._d.valueOf() + diff); + hooks.updateOffset(res, false); + return res; + } else { + return createLocal(input).local(); + } +} + +function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; +} + +// HOOKS + +// This function will be called whenever a moment is mutated. +// It is intended to keep the offset in sync with the timezone. +hooks.updateOffset = function () {}; + +// MOMENTS + +// keepLocalTime = true means only change the timezone, without +// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> +// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset +// +0200, so we adjust the time as needed, to be valid. +// +// Keeping the time actually adds/subtracts (one hour) +// from the actual represented time. That is why we call updateOffset +// a second time. In case it wants us to change the offset again +// _changeInProgress == true case, then we have to adjust, because +// there is no such time in the given timezone. +function getSetOffset (input, keepLocalTime, keepMinutes) { + var offset = this._offset || 0, + localAdjust; + if (!this.isValid()) { + return input != null ? this : NaN; + } + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(matchShortOffset, input); + if (input === null) { + return this; + } + } else if (Math.abs(input) < 16 && !keepMinutes) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addSubtract(this, createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } +} + +function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } +} + +function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); +} + +function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; +} + +function setOffsetToParsedOffset () { + if (this._tzm != null) { + this.utcOffset(this._tzm, false, true); + } else if (typeof this._i === 'string') { + var tZone = offsetFromString(matchOffset, this._i); + if (tZone != null) { + this.utcOffset(tZone); + } + else { + this.utcOffset(0, true); + } + } + return this; +} + +function hasAlignedHourOffset (input) { + if (!this.isValid()) { + return false; + } + input = input ? createLocal(input).utcOffset() : 0; + + return (this.utcOffset() - input) % 60 === 0; +} + +function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); +} + +function isDaylightSavingTimeShifted () { + if (!isUndefined(this._isDSTShifted)) { + return this._isDSTShifted; + } + + var c = {}; + + copyConfig(c, this); + c = prepareConfig(c); + + if (c._a) { + var other = c._isUTC ? createUTC(c._a) : createLocal(c._a); + this._isDSTShifted = this.isValid() && + compareArrays(c._a, other.toArray()) > 0; + } else { + this._isDSTShifted = false; + } + + return this._isDSTShifted; +} + +function isLocal () { + return this.isValid() ? !this._isUTC : false; +} + +function isUtcOffset () { + return this.isValid() ? this._isUTC : false; +} + +function isUtc () { + return this.isValid() ? this._isUTC && this._offset === 0 : false; +} + +// ASP.NET json date format regex +var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; + +// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html +// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere +// and further modified to allow for strings containing both week and day +var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/; + +function createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (isNumber(input)) { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + w : parseIso(match[4], sign), + d : parseIso(match[5], sign), + h : parseIso(match[6], sign), + m : parseIso(match[7], sign), + s : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; +} + +createDuration.fn = Duration.prototype; +createDuration.invalid = createInvalid$1; + +function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; +} + +function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; +} + +function momentsDifference(base, other) { + var res; + if (!(base.isValid() && other.isValid())) { + return {milliseconds: 0, months: 0}; + } + + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; +} + +// TODO: remove 'name' arg after deprecation is removed +function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = createDuration(val, period); + addSubtract(this, dur, direction); + return this; + }; +} + +function addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = absRound(duration._days), + months = absRound(duration._months); + + if (!mom.isValid()) { + // No op + return; + } + + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); + } + if (days) { + set$1(mom, 'Date', get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + hooks.updateOffset(mom, days || months); + } +} + +var add = createAdder(1, 'add'); +var subtract = createAdder(-1, 'subtract'); + +function getCalendarFormat(myMoment, now) { + var diff = myMoment.diff(now, 'days', true); + return diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; +} + +function calendar$1 (time, formats) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + format = hooks.calendarFormat(this, sod) || 'sameElse'; + + var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); + + return this.format(output || this.localeData().calendar(format, this, createLocal(now))); +} + +function clone () { + return new Moment(this); +} + +function isAfter (input, units) { + var localInput = isMoment(input) ? input : createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() > localInput.valueOf(); + } else { + return localInput.valueOf() < this.clone().startOf(units).valueOf(); + } +} + +function isBefore (input, units) { + var localInput = isMoment(input) ? input : createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() < localInput.valueOf(); + } else { + return this.clone().endOf(units).valueOf() < localInput.valueOf(); + } +} + +function isBetween (from, to, units, inclusivity) { + inclusivity = inclusivity || '()'; + return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) && + (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units)); +} + +function isSame (input, units) { + var localInput = isMoment(input) ? input : createLocal(input), + inputMs; + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() === localInput.valueOf(); + } else { + inputMs = localInput.valueOf(); + return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); + } +} + +function isSameOrAfter (input, units) { + return this.isSame(input, units) || this.isAfter(input,units); +} + +function isSameOrBefore (input, units) { + return this.isSame(input, units) || this.isBefore(input,units); +} + +function diff (input, units, asFloat) { + var that, + zoneDelta, + delta, output; + + if (!this.isValid()) { + return NaN; + } + + that = cloneWithOffset(input, this); + + if (!that.isValid()) { + return NaN; + } + + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); +} + +function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + //check for negative zero, return zero if negative zero + return -(wholeMonthDiff + adjust) || 0; +} + +hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; +hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; + +function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); +} + +function toISOString() { + if (!this.isValid()) { + return null; + } + var m = this.clone().utc(); + if (m.year() < 0 || m.year() > 9999) { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + if (isFunction(Date.prototype.toISOString)) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); +} + +/** + * Return a human readable representation of a moment that can + * also be evaluated to get a new moment which is the same + * + * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects + */ +function inspect () { + if (!this.isValid()) { + return 'moment.invalid(/* ' + this._i + ' */)'; + } + var func = 'moment'; + var zone = ''; + if (!this.isLocal()) { + func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone'; + zone = 'Z'; + } + var prefix = '[' + func + '("]'; + var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY'; + var datetime = '-MM-DD[T]HH:mm:ss.SSS'; + var suffix = zone + '[")]'; + + return this.format(prefix + year + datetime + suffix); +} + +function format (inputString) { + if (!inputString) { + inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat; + } + var output = formatMoment(this, inputString); + return this.localeData().postformat(output); +} + +function from (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + createLocal(time).isValid())) { + return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } +} + +function fromNow (withoutSuffix) { + return this.from(createLocal(), withoutSuffix); +} + +function to (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + createLocal(time).isValid())) { + return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } +} + +function toNow (withoutSuffix) { + return this.to(createLocal(), withoutSuffix); +} + +// If passed a locale key, it will set the locale for this +// instance. Otherwise, it will return the locale configuration +// variables for this instance. +function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } +} + +var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } +); + +function localeData () { + return this._locale; +} + +function startOf (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + case 'date': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; +} + +function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + + // 'date' is an alias for 'day', so it should be considered as such. + if (units === 'date') { + units = 'day'; + } + + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); +} + +function valueOf () { + return this._d.valueOf() - ((this._offset || 0) * 60000); +} + +function unix () { + return Math.floor(this.valueOf() / 1000); +} + +function toDate () { + return new Date(this.valueOf()); +} + +function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; +} + +function toObject () { + var m = this; + return { + years: m.year(), + months: m.month(), + date: m.date(), + hours: m.hours(), + minutes: m.minutes(), + seconds: m.seconds(), + milliseconds: m.milliseconds() + }; +} + +function toJSON () { + // new Date(NaN).toJSON() === null + return this.isValid() ? this.toISOString() : null; +} + +function isValid$2 () { + return isValid(this); +} + +function parsingFlags () { + return extend({}, getParsingFlags(this)); +} + +function invalidAt () { + return getParsingFlags(this).overflow; +} + +function creationData() { + return { + input: this._i, + format: this._f, + locale: this._locale, + isUTC: this._isUTC, + strict: this._strict + }; +} + +// FORMATTING + +addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; +}); + +addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; +}); + +function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); +} + +addWeekYearFormatToken('gggg', 'weekYear'); +addWeekYearFormatToken('ggggg', 'weekYear'); +addWeekYearFormatToken('GGGG', 'isoWeekYear'); +addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + +// ALIASES + +addUnitAlias('weekYear', 'gg'); +addUnitAlias('isoWeekYear', 'GG'); + +// PRIORITY + +addUnitPriority('weekYear', 1); +addUnitPriority('isoWeekYear', 1); + + +// PARSING + +addRegexToken('G', matchSigned); +addRegexToken('g', matchSigned); +addRegexToken('GG', match1to2, match2); +addRegexToken('gg', match1to2, match2); +addRegexToken('GGGG', match1to4, match4); +addRegexToken('gggg', match1to4, match4); +addRegexToken('GGGGG', match1to6, match6); +addRegexToken('ggggg', match1to6, match6); + +addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); +}); + +addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = hooks.parseTwoDigitYear(input); +}); + +// MOMENTS + +function getSetWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, + this.week(), + this.weekday(), + this.localeData()._week.dow, + this.localeData()._week.doy); +} + +function getSetISOWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, this.isoWeek(), this.isoWeekday(), 1, 4); +} + +function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); +} + +function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); +} + +function getSetWeekYearHelper(input, week, weekday, dow, doy) { + var weeksTarget; + if (input == null) { + return weekOfYear(this, dow, doy).year; + } else { + weeksTarget = weeksInYear(input, dow, doy); + if (week > weeksTarget) { + week = weeksTarget; + } + return setWeekAll.call(this, input, week, weekday, dow, doy); + } +} + +function setWeekAll(weekYear, week, weekday, dow, doy) { + var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), + date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); + + this.year(date.getUTCFullYear()); + this.month(date.getUTCMonth()); + this.date(date.getUTCDate()); + return this; +} + +// FORMATTING + +addFormatToken('Q', 0, 'Qo', 'quarter'); + +// ALIASES + +addUnitAlias('quarter', 'Q'); + +// PRIORITY + +addUnitPriority('quarter', 7); + +// PARSING + +addRegexToken('Q', match1); +addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; +}); + +// MOMENTS + +function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); +} + +// FORMATTING + +addFormatToken('D', ['DD', 2], 'Do', 'date'); + +// ALIASES + +addUnitAlias('date', 'D'); + +// PRIOROITY +addUnitPriority('date', 9); + +// PARSING + +addRegexToken('D', match1to2); +addRegexToken('DD', match1to2, match2); +addRegexToken('Do', function (isStrict, locale) { + // TODO: Remove "ordinalParse" fallback in next major release. + return isStrict ? + (locale._dayOfMonthOrdinalParse || locale._ordinalParse) : + locale._dayOfMonthOrdinalParseLenient; +}); + +addParseToken(['D', 'DD'], DATE); +addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); +}); + +// MOMENTS + +var getSetDayOfMonth = makeGetSet('Date', true); + +// FORMATTING + +addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + +// ALIASES + +addUnitAlias('dayOfYear', 'DDD'); + +// PRIORITY +addUnitPriority('dayOfYear', 4); + +// PARSING + +addRegexToken('DDD', match1to3); +addRegexToken('DDDD', match3); +addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); +}); + +// HELPERS + +// MOMENTS + +function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); +} + +// FORMATTING + +addFormatToken('m', ['mm', 2], 0, 'minute'); + +// ALIASES + +addUnitAlias('minute', 'm'); + +// PRIORITY + +addUnitPriority('minute', 14); + +// PARSING + +addRegexToken('m', match1to2); +addRegexToken('mm', match1to2, match2); +addParseToken(['m', 'mm'], MINUTE); + +// MOMENTS + +var getSetMinute = makeGetSet('Minutes', false); + +// FORMATTING + +addFormatToken('s', ['ss', 2], 0, 'second'); + +// ALIASES + +addUnitAlias('second', 's'); + +// PRIORITY + +addUnitPriority('second', 15); + +// PARSING + +addRegexToken('s', match1to2); +addRegexToken('ss', match1to2, match2); +addParseToken(['s', 'ss'], SECOND); + +// MOMENTS + +var getSetSecond = makeGetSet('Seconds', false); + +// FORMATTING + +addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); +}); + +addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); +}); + +addFormatToken(0, ['SSS', 3], 0, 'millisecond'); +addFormatToken(0, ['SSSS', 4], 0, function () { + return this.millisecond() * 10; +}); +addFormatToken(0, ['SSSSS', 5], 0, function () { + return this.millisecond() * 100; +}); +addFormatToken(0, ['SSSSSS', 6], 0, function () { + return this.millisecond() * 1000; +}); +addFormatToken(0, ['SSSSSSS', 7], 0, function () { + return this.millisecond() * 10000; +}); +addFormatToken(0, ['SSSSSSSS', 8], 0, function () { + return this.millisecond() * 100000; +}); +addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { + return this.millisecond() * 1000000; +}); + + +// ALIASES + +addUnitAlias('millisecond', 'ms'); + +// PRIORITY + +addUnitPriority('millisecond', 16); + +// PARSING + +addRegexToken('S', match1to3, match1); +addRegexToken('SS', match1to3, match2); +addRegexToken('SSS', match1to3, match3); + +var token; +for (token = 'SSSS'; token.length <= 9; token += 'S') { + addRegexToken(token, matchUnsigned); +} + +function parseMs(input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); +} + +for (token = 'S'; token.length <= 9; token += 'S') { + addParseToken(token, parseMs); +} +// MOMENTS + +var getSetMillisecond = makeGetSet('Milliseconds', false); + +// FORMATTING + +addFormatToken('z', 0, 0, 'zoneAbbr'); +addFormatToken('zz', 0, 0, 'zoneName'); + +// MOMENTS + +function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; +} + +function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; +} + +var proto = Moment.prototype; + +proto.add = add; +proto.calendar = calendar$1; +proto.clone = clone; +proto.diff = diff; +proto.endOf = endOf; +proto.format = format; +proto.from = from; +proto.fromNow = fromNow; +proto.to = to; +proto.toNow = toNow; +proto.get = stringGet; +proto.invalidAt = invalidAt; +proto.isAfter = isAfter; +proto.isBefore = isBefore; +proto.isBetween = isBetween; +proto.isSame = isSame; +proto.isSameOrAfter = isSameOrAfter; +proto.isSameOrBefore = isSameOrBefore; +proto.isValid = isValid$2; +proto.lang = lang; +proto.locale = locale; +proto.localeData = localeData; +proto.max = prototypeMax; +proto.min = prototypeMin; +proto.parsingFlags = parsingFlags; +proto.set = stringSet; +proto.startOf = startOf; +proto.subtract = subtract; +proto.toArray = toArray; +proto.toObject = toObject; +proto.toDate = toDate; +proto.toISOString = toISOString; +proto.inspect = inspect; +proto.toJSON = toJSON; +proto.toString = toString; +proto.unix = unix; +proto.valueOf = valueOf; +proto.creationData = creationData; + +// Year +proto.year = getSetYear; +proto.isLeapYear = getIsLeapYear; + +// Week Year +proto.weekYear = getSetWeekYear; +proto.isoWeekYear = getSetISOWeekYear; + +// Quarter +proto.quarter = proto.quarters = getSetQuarter; + +// Month +proto.month = getSetMonth; +proto.daysInMonth = getDaysInMonth; + +// Week +proto.week = proto.weeks = getSetWeek; +proto.isoWeek = proto.isoWeeks = getSetISOWeek; +proto.weeksInYear = getWeeksInYear; +proto.isoWeeksInYear = getISOWeeksInYear; + +// Day +proto.date = getSetDayOfMonth; +proto.day = proto.days = getSetDayOfWeek; +proto.weekday = getSetLocaleDayOfWeek; +proto.isoWeekday = getSetISODayOfWeek; +proto.dayOfYear = getSetDayOfYear; + +// Hour +proto.hour = proto.hours = getSetHour; + +// Minute +proto.minute = proto.minutes = getSetMinute; + +// Second +proto.second = proto.seconds = getSetSecond; + +// Millisecond +proto.millisecond = proto.milliseconds = getSetMillisecond; + +// Offset +proto.utcOffset = getSetOffset; +proto.utc = setOffsetToUTC; +proto.local = setOffsetToLocal; +proto.parseZone = setOffsetToParsedOffset; +proto.hasAlignedHourOffset = hasAlignedHourOffset; +proto.isDST = isDaylightSavingTime; +proto.isLocal = isLocal; +proto.isUtcOffset = isUtcOffset; +proto.isUtc = isUtc; +proto.isUTC = isUtc; + +// Timezone +proto.zoneAbbr = getZoneAbbr; +proto.zoneName = getZoneName; + +// Deprecations +proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); +proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); +proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); +proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); +proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); + +function createUnix (input) { + return createLocal(input * 1000); +} + +function createInZone () { + return createLocal.apply(null, arguments).parseZone(); +} + +function preParsePostFormat (string) { + return string; +} + +var proto$1 = Locale.prototype; + +proto$1.calendar = calendar; +proto$1.longDateFormat = longDateFormat; +proto$1.invalidDate = invalidDate; +proto$1.ordinal = ordinal; +proto$1.preparse = preParsePostFormat; +proto$1.postformat = preParsePostFormat; +proto$1.relativeTime = relativeTime; +proto$1.pastFuture = pastFuture; +proto$1.set = set; + +// Month +proto$1.months = localeMonths; +proto$1.monthsShort = localeMonthsShort; +proto$1.monthsParse = localeMonthsParse; +proto$1.monthsRegex = monthsRegex; +proto$1.monthsShortRegex = monthsShortRegex; + +// Week +proto$1.week = localeWeek; +proto$1.firstDayOfYear = localeFirstDayOfYear; +proto$1.firstDayOfWeek = localeFirstDayOfWeek; + +// Day of Week +proto$1.weekdays = localeWeekdays; +proto$1.weekdaysMin = localeWeekdaysMin; +proto$1.weekdaysShort = localeWeekdaysShort; +proto$1.weekdaysParse = localeWeekdaysParse; + +proto$1.weekdaysRegex = weekdaysRegex; +proto$1.weekdaysShortRegex = weekdaysShortRegex; +proto$1.weekdaysMinRegex = weekdaysMinRegex; + +// Hours +proto$1.isPM = localeIsPM; +proto$1.meridiem = localeMeridiem; + +function get$1 (format, index, field, setter) { + var locale = getLocale(); + var utc = createUTC().set(setter, index); + return locale[field](utc, format); +} + +function listMonthsImpl (format, index, field) { + if (isNumber(format)) { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return get$1(format, index, field, 'month'); + } + + var i; + var out = []; + for (i = 0; i < 12; i++) { + out[i] = get$1(format, i, field, 'month'); + } + return out; +} + +// () +// (5) +// (fmt, 5) +// (fmt) +// (true) +// (true, 5) +// (true, fmt, 5) +// (true, fmt) +function listWeekdaysImpl (localeSorted, format, index, field) { + if (typeof localeSorted === 'boolean') { + if (isNumber(format)) { + index = format; + format = undefined; + } + + format = format || ''; + } else { + format = localeSorted; + index = format; + localeSorted = false; + + if (isNumber(format)) { + index = format; + format = undefined; + } + + format = format || ''; + } + + var locale = getLocale(), + shift = localeSorted ? locale._week.dow : 0; + + if (index != null) { + return get$1(format, (index + shift) % 7, field, 'day'); + } + + var i; + var out = []; + for (i = 0; i < 7; i++) { + out[i] = get$1(format, (i + shift) % 7, field, 'day'); + } + return out; +} + +function listMonths (format, index) { + return listMonthsImpl(format, index, 'months'); +} + +function listMonthsShort (format, index) { + return listMonthsImpl(format, index, 'monthsShort'); +} + +function listWeekdays (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); +} + +function listWeekdaysShort (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); +} + +function listWeekdaysMin (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); +} + +getSetGlobalLocale('en', { + dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } +}); + +// Side effect imports +hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale); +hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale); + +var mathAbs = Math.abs; + +function abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; +} + +function addSubtract$1 (duration, input, value, direction) { + var other = createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); +} + +// supports only 2.0-style add(1, 's') or add(duration) +function add$1 (input, value) { + return addSubtract$1(this, input, value, 1); +} + +// supports only 2.0-style subtract(1, 's') or subtract(duration) +function subtract$1 (input, value) { + return addSubtract$1(this, input, value, -1); +} + +function absCeil (number) { + if (number < 0) { + return Math.floor(number); + } else { + return Math.ceil(number); + } +} + +function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years, monthsFromDays; + + // if we have a mix of positive and negative values, bubble down first + // check: https://github.com/moment/moment/issues/2166 + if (!((milliseconds >= 0 && days >= 0 && months >= 0) || + (milliseconds <= 0 && days <= 0 && months <= 0))) { + milliseconds += absCeil(monthsToDays(months) + days) * 864e5; + days = 0; + months = 0; + } + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // convert days to months + monthsFromDays = absFloor(daysToMonths(days)); + months += monthsFromDays; + days -= absCeil(monthsToDays(monthsFromDays)); + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; +} + +function daysToMonths (days) { + // 400 years have 146097 days (taking into account leap year rules) + // 400 years have 12 months === 4800 + return days * 4800 / 146097; +} + +function monthsToDays (months) { + // the reverse of daysToMonths + return months * 146097 / 4800; +} + +function as (units) { + if (!this.isValid()) { + return NaN; + } + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToMonths(days); + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(monthsToDays(this._months)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } +} + +// TODO: Use this.as('ms')? +function valueOf$1 () { + if (!this.isValid()) { + return NaN; + } + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); +} + +function makeAs (alias) { + return function () { + return this.as(alias); + }; +} + +var asMilliseconds = makeAs('ms'); +var asSeconds = makeAs('s'); +var asMinutes = makeAs('m'); +var asHours = makeAs('h'); +var asDays = makeAs('d'); +var asWeeks = makeAs('w'); +var asMonths = makeAs('M'); +var asYears = makeAs('y'); + +function get$2 (units) { + units = normalizeUnits(units); + return this.isValid() ? this[units + 's']() : NaN; +} + +function makeGetter(name) { + return function () { + return this.isValid() ? this._data[name] : NaN; + }; +} + +var milliseconds = makeGetter('milliseconds'); +var seconds = makeGetter('seconds'); +var minutes = makeGetter('minutes'); +var hours = makeGetter('hours'); +var days = makeGetter('days'); +var months = makeGetter('months'); +var years = makeGetter('years'); + +function weeks () { + return absFloor(this.days() / 7); +} + +var round = Math.round; +var thresholds = { + ss: 44, // a few seconds to seconds + s : 45, // seconds to minute + m : 45, // minutes to hour + h : 22, // hours to day + d : 26, // days to month + M : 11 // months to year +}; + +// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize +function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); +} + +function relativeTime$1 (posNegDuration, withoutSuffix, locale) { + var duration = createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds <= thresholds.ss && ['s', seconds] || + seconds < thresholds.s && ['ss', seconds] || + minutes <= 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours <= 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days <= 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months <= 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years <= 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); +} + +// This function allows you to set the rounding function for relative time strings +function getSetRelativeTimeRounding (roundingFunction) { + if (roundingFunction === undefined) { + return round; + } + if (typeof(roundingFunction) === 'function') { + round = roundingFunction; + return true; + } + return false; +} + +// This function allows you to set a threshold for relative time strings +function getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + if (threshold === 's') { + thresholds.ss = limit - 1; + } + return true; +} + +function humanize (withSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + + var locale = this.localeData(); + var output = relativeTime$1(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); +} + +var abs$1 = Math.abs; + +function toISOString$1() { + // for ISO strings we do not use the normal bubbling rules: + // * milliseconds bubble up until they become hours + // * days do not bubble at all + // * months bubble up until they become years + // This is because there is no context-free conversion between hours and days + // (think of clock changes) + // and also not between days and months (28-31 days per month) + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + + var seconds = abs$1(this._milliseconds) / 1000; + var days = abs$1(this._days); + var months = abs$1(this._months); + var minutes, hours, years; + + // 3600 seconds -> 60 minutes -> 1 hour + minutes = absFloor(seconds / 60); + hours = absFloor(minutes / 60); + seconds %= 60; + minutes %= 60; + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = years; + var M = months; + var D = days; + var h = hours; + var m = minutes; + var s = seconds; + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); +} + +var proto$2 = Duration.prototype; + +proto$2.isValid = isValid$1; +proto$2.abs = abs; +proto$2.add = add$1; +proto$2.subtract = subtract$1; +proto$2.as = as; +proto$2.asMilliseconds = asMilliseconds; +proto$2.asSeconds = asSeconds; +proto$2.asMinutes = asMinutes; +proto$2.asHours = asHours; +proto$2.asDays = asDays; +proto$2.asWeeks = asWeeks; +proto$2.asMonths = asMonths; +proto$2.asYears = asYears; +proto$2.valueOf = valueOf$1; +proto$2._bubble = bubble; +proto$2.get = get$2; +proto$2.milliseconds = milliseconds; +proto$2.seconds = seconds; +proto$2.minutes = minutes; +proto$2.hours = hours; +proto$2.days = days; +proto$2.weeks = weeks; +proto$2.months = months; +proto$2.years = years; +proto$2.humanize = humanize; +proto$2.toISOString = toISOString$1; +proto$2.toString = toISOString$1; +proto$2.toJSON = toISOString$1; +proto$2.locale = locale; +proto$2.localeData = localeData; + +// Deprecations +proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1); +proto$2.lang = lang; + +// Side effect imports + +// FORMATTING + +addFormatToken('X', 0, 0, 'unix'); +addFormatToken('x', 0, 0, 'valueOf'); + +// PARSING + +addRegexToken('x', matchSigned); +addRegexToken('X', matchTimestamp); +addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); +}); +addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); +}); + +// Side effect imports + + +hooks.version = '2.18.1'; + +setHookCallback(createLocal); + +hooks.fn = proto; +hooks.min = min; +hooks.max = max; +hooks.now = now; +hooks.utc = createUTC; +hooks.unix = createUnix; +hooks.months = listMonths; +hooks.isDate = isDate; +hooks.locale = getSetGlobalLocale; +hooks.invalid = createInvalid; +hooks.duration = createDuration; +hooks.isMoment = isMoment; +hooks.weekdays = listWeekdays; +hooks.parseZone = createInZone; +hooks.localeData = getLocale; +hooks.isDuration = isDuration; +hooks.monthsShort = listMonthsShort; +hooks.weekdaysMin = listWeekdaysMin; +hooks.defineLocale = defineLocale; +hooks.updateLocale = updateLocale; +hooks.locales = listLocales; +hooks.weekdaysShort = listWeekdaysShort; +hooks.normalizeUnits = normalizeUnits; +hooks.relativeTimeRounding = getSetRelativeTimeRounding; +hooks.relativeTimeThreshold = getSetRelativeTimeThreshold; +hooks.calendarFormat = getCalendarFormat; +hooks.prototype = proto; + +return hooks; + +}))); + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(204)(module))) + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = __webpack_require__(56); + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +if (false) { + var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' && + Symbol.for && + Symbol.for('react.element')) || + 0xeac7; + + var isValidElement = function(object) { + return typeof object === 'object' && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE; + }; + + // By explicitly using `prop-types` you are opting into new development behavior. + // http://fb.me/prop-types-in-prod + var throwOnDirectAccess = true; + module.exports = require('./factoryWithTypeCheckers')(isValidElement, throwOnDirectAccess); +} else { + // By explicitly using `prop-types` you are opting into new production behavior. + // http://fb.me/prop-types-in-prod + module.exports = __webpack_require__(469)(); +} + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = __webpack_require__(396); + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + + + +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + +var validateFormat = function validateFormat(format) {}; + +if (false) { + validateFormat = function validateFormat(format) { + if (format === undefined) { + throw new Error('invariant requires an error message argument'); + } + }; +} + +function invariant(condition, format, a, b, c, d, e, f) { + validateFormat(format); + + if (!condition) { + var error; + if (format === undefined) { + error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error(format.replace(/%s/g, function () { + return args[argIndex++]; + })); + error.name = 'Invariant Violation'; + } + + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } +} + +module.exports = invariant; + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_RESULT__;/** + * @license + * Lodash + * Copyright JS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.4'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 800, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + domExcTag = '[object DOMException]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + nullTag = '[object Null]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading and trailing whitespace. */ + var reTrim = /^\s+|\s+$/g, + reTrimStart = /^\s+/, + reTrimEnd = /\s+$/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)', + rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ + function addMapEntry(map, pair) { + // Don't return `map.set` because it's not chainable in IE 11. + map.set(pair[0], pair[1]); + return map; + } + + /** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ + function addSetEntry(set, value) { + // Don't return `set.add` because it's not chainable in IE 11. + set.add(value); + return set; + } + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, + symIterator = Symbol ? Symbol.iterator : undefined, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB) as well as ES2015 template strings. Change the + * following template settings to use alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; + + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, baseClone, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee == null ? value : iteratee(value); + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(object[key], srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + var index = -1; + iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array == null ? low : array.length; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array == null ? 0 : array.length, + valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The property path to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, + result = Array(length); + + while (++index < length) { + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } + } + return baseUniq(baseFlatten(result, 1), iteratee, comparator); + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned map. + */ + function cloneMap(map, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map); + return arrayReduce(array, addMapEntry, new map.constructor); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned set. + */ + function cloneSet(set, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set); + return arrayReduce(array, addSetEntry, new set.constructor); + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ + function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } + + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, cloneFunc, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return cloneMap(object, isDeep, cloneFunc); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return cloneSet(object, isDeep, cloneFunc); + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs == null ? 0 : pairs.length, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array == null ? '' : nativeJoin.call(array, separator); + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array == null ? array : nativeReverse.call(array); + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) ? baseUniq(array) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + comparator = typeof comparator == 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine + * grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + result = wait - timeSinceLastCall; + + return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '

' + func(text) + '

'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

fred, barney, & pebbles

' + */ + function wrap(value, wrapper) { + return partial(castFunction(wrapper), value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ + function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return value + ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) + : (value === 0 ? value : 0); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : baseAssign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(args) { + args.push(undefined, customDefaultsAssignIn); + return apply(assignInWith, undefined, args); + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable property paths of `object` that are not omitted. + * + * **Note:** This method is considerably slower than `_.pick`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, paths) { + var result = {}; + if (object == null) { + return result; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result); + if (isDeep) { + result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result, paths[length]); + } + return result; + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = castPath(path, object); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + length = 1; + object = undefined; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = position == null + ? 0 + : baseClamp(toInteger(position), 0, string.length); + + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': ' + \ No newline at end of file diff --git a/docs/src/docs/XTicks/propDocs.json b/docs/src/docs/XTicks/propDocs.json index d56af18d..a7e02726 100644 --- a/docs/src/docs/XTicks/propDocs.json +++ b/docs/src/docs/XTicks/propDocs.json @@ -45,29 +45,71 @@ "description": "" }, "position": { + "type": { + "name": "enum", + "value": [ + { + "value": "'bottom'", + "computed": false + }, + { + "value": "'top'", + "computed": false + } + ] + }, + "required": false, + "description": "", "defaultValue": { "value": "'bottom'", "computed": false } }, - "nice": { - "defaultValue": { - "value": "true", - "computed": false - } + "placement": { + "type": { + "name": "enum", + "value": [ + { + "value": "'above'", + "computed": false + }, + { + "value": "'below'", + "computed": false + } + ] + }, + "required": false, + "description": "" }, "tickLength": { + "type": { + "name": "number" + }, + "required": false, + "description": "", "defaultValue": { "value": "5", "computed": false } }, "tickStyle": { + "type": { + "name": "object" + }, + "required": false, + "description": "", "defaultValue": { "value": "{}", "computed": false } }, + "nice": { + "defaultValue": { + "value": "true", + "computed": false + } + }, "spacing": { "defaultValue": { "value": "{top: 0, bottom: 0, left: 0, right: 0}", diff --git a/lib/AreaBarChart.js b/lib/AreaBarChart.js index 3513c883..0b6a43c5 100644 --- a/lib/AreaBarChart.js +++ b/lib/AreaBarChart.js @@ -34,6 +34,10 @@ var _Scale = require('./utils/Scale'); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _RangeRect = require('./RangeRect'); var _RangeRect2 = _interopRequireDefault(_RangeRect); @@ -60,6 +64,13 @@ var AreaBarChart = function (_React$Component) { } _createClass(AreaBarChart, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['barStyle']); + // console.log('should areabarchart update?', shouldUpdate); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var _this2 = this; diff --git a/lib/AreaBarChart.js.map b/lib/AreaBarChart.js.map index aa2caf59..0c0a9e58 100644 --- a/lib/AreaBarChart.js.map +++ b/lib/AreaBarChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/AreaBarChart.js"],"names":["CustomPropTypes","AreaBarChart","props","scale","data","horizontal","getX","getXEnd","getY","getYEnd","barClassName","barStyle","getClass","barProps","style","getZero","constant","map","d","i","callback","get","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","className","scaleType","rangeAxis","rangeDataType","rangeStartAccessor","toUpperCase","rangeEndAccessor","Component","propTypes","xyObjectOf","func","isRequired","array","bool","getter","string","object","onMouseEnterBar","onMouseMoveBar","onMouseLeaveBar","defaultProps"],"mappings":"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","file":"AreaBarChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {hasXYScales, dataTypeFromScaleType} from './utils/Scale';\nimport {makeAccessor, domainFromRangeData} from './utils/Data';\nimport RangeRect from './RangeRect';\n\nexport default class AreaBarChart extends React.Component {\n static propTypes = {\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n data: PropTypes.array,\n horizontal: PropTypes.bool,\n\n getX: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n getClass: CustomPropTypes.getter,\n\n barClassName: PropTypes.string,\n barStyle: PropTypes.object,\n\n onMouseEnterBar: PropTypes.func,\n onMouseMoveBar: PropTypes.func,\n onMouseLeaveBar: PropTypes.func\n };\n static defaultProps = {\n data: [],\n horizontal: false,\n barClassName: '',\n barStyle: {}\n };\n\n static getDomain(props) {\n const {scaleType, horizontal, data} = props;\n\n // only have to specify range axis domain, other axis uses default domainFromData\n // for area bar chart, the independent variable is the range\n // ie. the range controls the thickness of the bar\n const rangeAxis = horizontal ? 'y' : 'x';\n const rangeDataType = dataTypeFromScaleType(scaleType[rangeAxis]);\n // make accessor functions from getX|Y and getX|YEnd\n const rangeStartAccessor = makeAccessor(props[`get${rangeAxis.toUpperCase()}`]);\n const rangeEndAccessor = makeAccessor(props[`get${rangeAxis.toUpperCase()}End`]);\n\n return {\n [rangeAxis]: domainFromRangeData(data, rangeStartAccessor, rangeEndAccessor, rangeDataType)\n };\n }\n\n render() {\n const {scale, data, horizontal, getX, getXEnd, getY, getYEnd, barClassName, barStyle, getClass} = this.props;\n invariant(hasXYScales(scale), `AreaBarChart.props.scale.x and scale.y must both be valid d3 scales`);\n\n const barProps = {\n scale,\n style: barStyle\n };\n const getZero = _.constant(0);\n\n return \n {data.map((d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterBar', 'onMouseMoveBar', 'onMouseLeaveBar'].map(eventName => {\n\n // partially apply this bar's data point as 2nd callback argument\n const callback = _.get(this.props, eventName);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n barProps.className = `chart-area-bar ${getClass ? makeAccessor(getClass)(d) : ''} ${barClassName}`; \n return ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/AreaBarChart.js"],"names":["CustomPropTypes","AreaBarChart","nextProps","nextState","shouldUpdate","props","scale","data","horizontal","getX","getXEnd","getY","getYEnd","barClassName","barStyle","getClass","barProps","style","getZero","constant","map","d","i","callback","get","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","className","scaleType","rangeAxis","rangeDataType","rangeStartAccessor","toUpperCase","rangeEndAccessor","Component","propTypes","xyObjectOf","func","isRequired","array","bool","getter","string","object","onMouseEnterBar","onMouseMoveBar","onMouseLeaveBar","defaultProps"],"mappings":"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","file":"AreaBarChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {hasXYScales, dataTypeFromScaleType} from './utils/Scale';\nimport {makeAccessor, domainFromRangeData} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\nimport RangeRect from './RangeRect';\n\nexport default class AreaBarChart extends React.Component {\n static propTypes = {\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n data: PropTypes.array,\n horizontal: PropTypes.bool,\n\n getX: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n getClass: CustomPropTypes.getter,\n\n barClassName: PropTypes.string,\n barStyle: PropTypes.object,\n\n onMouseEnterBar: PropTypes.func,\n onMouseMoveBar: PropTypes.func,\n onMouseLeaveBar: PropTypes.func\n };\n static defaultProps = {\n data: [],\n horizontal: false,\n barClassName: '',\n barStyle: {}\n };\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['barStyle']);\n // console.log('should areabarchart update?', shouldUpdate);\n return shouldUpdate;\n }\n\n static getDomain(props) {\n const {scaleType, horizontal, data} = props;\n\n // only have to specify range axis domain, other axis uses default domainFromData\n // for area bar chart, the independent variable is the range\n // ie. the range controls the thickness of the bar\n const rangeAxis = horizontal ? 'y' : 'x';\n const rangeDataType = dataTypeFromScaleType(scaleType[rangeAxis]);\n // make accessor functions from getX|Y and getX|YEnd\n const rangeStartAccessor = makeAccessor(props[`get${rangeAxis.toUpperCase()}`]);\n const rangeEndAccessor = makeAccessor(props[`get${rangeAxis.toUpperCase()}End`]);\n\n return {\n [rangeAxis]: domainFromRangeData(data, rangeStartAccessor, rangeEndAccessor, rangeDataType)\n };\n }\n\n render() {\n const {scale, data, horizontal, getX, getXEnd, getY, getYEnd, barClassName, barStyle, getClass} = this.props;\n invariant(hasXYScales(scale), `AreaBarChart.props.scale.x and scale.y must both be valid d3 scales`);\n\n const barProps = {\n scale,\n style: barStyle\n };\n const getZero = _.constant(0);\n\n return \n {data.map((d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterBar', 'onMouseMoveBar', 'onMouseLeaveBar'].map(eventName => {\n\n // partially apply this bar's data point as 2nd callback argument\n const callback = _.get(this.props, eventName);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n barProps.className = `chart-area-bar ${getClass ? makeAccessor(getClass)(d) : ''} ${barClassName}`; \n return ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/AreaChart.js b/lib/AreaChart.js index d1eea643..3438e112 100644 --- a/lib/AreaChart.js +++ b/lib/AreaChart.js @@ -22,6 +22,10 @@ var _d = require('d3'); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _CustomPropTypes = require('./utils/CustomPropTypes'); var CustomPropTypes = _interopRequireWildcard(_CustomPropTypes); @@ -53,6 +57,12 @@ var AreaChart = function (_React$Component) { } _createClass(AreaChart, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['pathStyle', 'pathStylePositive', 'pathStyleNegative']); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var _props = this.props, diff --git a/lib/AreaChart.js.map b/lib/AreaChart.js.map index 092151b6..f092d8da 100644 --- a/lib/AreaChart.js.map +++ b/lib/AreaChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/AreaChart.js"],"names":["CustomPropTypes","AreaChart","props","name","data","getX","getY","getYEnd","scale","isDifference","pathStyle","pathStylePositive","pathStyleNegative","shouldShowGaps","isDefined","accessors","x","y","yEnd","areaGenerator","defined","d","i","y0","y1","areaPathStr","height","clipBelowPathStr","clipAbovePathStr","chartId","uniqueId","clipAboveId","clipBelowId","pathStyleAbove","pathStyleBelow","Component","propTypes","array","isRequired","getter","object","bool","scaleType","func","defaultProps","isUndefined"],"mappings":"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","file":"AreaChart.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport _ from 'lodash';\nimport {area} from 'd3';\n\nimport {makeAccessor, domainFromData, combineDomains} from './utils/Data';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\n\n// AreaChart represents a simple bivariate area chart,\n// a filled path drawn between two lines (datasets).\n\n// todo horizontal prop, for filling area horizontally?\n// todo support categorical data?\n// todo build StackedAreaChart that composes multiple AreaCharts\n\nexport default class AreaChart extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n /**\n * data getter for X coordinates\n */\n getX: CustomPropTypes.getter,\n /**\n * data getter for Y coordinates\n */\n getY: CustomPropTypes.getter,\n /**\n * data getter for Y end coordinates\n */\n getYEnd: CustomPropTypes.getter,\n /**\n * style applied to path element\n */\n pathStyle: PropTypes.object,\n /**\n * if isDifference is true, AreaChart generates a \"difference chart\" with two area paths instead of one:\n * one path which shows when YEnd > Y, and one vice versa, allowing them to be styled differently (eg red/green)\n */\n isDifference: PropTypes.bool,\n /**\n * when isDifference is true, pathStylePositive and pathStyleNegative can be passed to give 2 different inline\n * styles to the two different paths which are generated.\n * Ignored if isDifference is false.\n */\n pathStylePositive: PropTypes.object,\n pathStyleNegative: PropTypes.object,\n\n scaleType: PropTypes.object,\n scale: PropTypes.object,\n /**\n * if true, will show gaps in the shaded area for data where props.isDefined(datum) returns false\n */\n shouldShowGaps: PropTypes.bool,\n /**\n * if shouldShowGaps is true, isDefined function describes when a datum should be considered \"defined\" vs. when to show gap\n * by default, shows gap if either y or yEnd are undefined\n */\n isDefined: PropTypes.func\n };\n static defaultProps = {\n shouldShowGaps: true,\n isDefined: (d, i, accessors) => {\n return !_.isUndefined(accessors.y(d, i)) && !_.isUndefined(accessors.yEnd(d, i));\n }\n };\n\n static getDomain(props) {\n // custom Y domain - the total (union) extent of getY and getYEnd combined\n const {data, getX, getY, getYEnd} = props;\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY), yEnd: makeAccessor(getYEnd)};\n return {\n y: combineDomains([\n domainFromData(data, accessors.y),\n domainFromData(data, accessors.yEnd)\n ])\n }\n }\n\n render() {\n const {name, data, getX, getY, getYEnd, scale, isDifference, pathStyle,\n pathStylePositive, pathStyleNegative, shouldShowGaps, isDefined} = this.props;\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY), yEnd: makeAccessor(getYEnd)};\n\n // create d3 area path generator\n const areaGenerator = area();\n\n // if gaps in data should be shown, use `props.isDefined` function as the `defined` param for d3's area generator;\n // but wrap it & pass in accessors as well, so that the function can easily access the relevant data values\n if(shouldShowGaps) {\n areaGenerator.defined((d, i) => isDefined(d, i, accessors));\n }\n\n areaGenerator\n .x((d, i) => scale.x(accessors.x(d, i)))\n .y0((d, i) => scale.y(accessors.y(d, i)))\n .y1((d, i) => scale.y(accessors.yEnd(d, i)));\n\n const areaPathStr = areaGenerator(data);\n\n if(isDifference) {\n // difference chart - create 2 clip paths, one which clips to only show path where YEnd > Y, and other vice versa\n areaGenerator.y0(this.props.height);\n const clipBelowPathStr = areaGenerator(data);\n areaGenerator.y0(0);\n const clipAbovePathStr = areaGenerator(data);\n\n // make sure we have a unique ID for this chart, so clip path IDs don't affect other charts\n const chartId = name || _.uniqueId();\n const clipAboveId = `clip-above-area-${chartId}`;\n const clipBelowId = `clip-below-area-${chartId}`;\n const pathStyleAbove = pathStylePositive || pathStyle || {};\n const pathStyleBelow = pathStyleNegative || pathStyle || {};\n\n return (\n \n \n \n \n \n \n \n \n );\n\n } else {\n return (\n \n );\n }\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/AreaChart.js"],"names":["CustomPropTypes","AreaChart","nextProps","nextState","shouldUpdate","props","name","data","getX","getY","getYEnd","scale","isDifference","pathStyle","pathStylePositive","pathStyleNegative","shouldShowGaps","isDefined","accessors","x","y","yEnd","areaGenerator","defined","d","i","y0","y1","areaPathStr","height","clipBelowPathStr","clipAbovePathStr","chartId","uniqueId","clipAboveId","clipBelowId","pathStyleAbove","pathStyleBelow","Component","propTypes","array","isRequired","getter","object","bool","scaleType","func","defaultProps","isUndefined"],"mappings":"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","file":"AreaChart.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport _ from 'lodash';\nimport {area} from 'd3';\n\nimport {makeAccessor, domainFromData, combineDomains} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\n\n// AreaChart represents a simple bivariate area chart,\n// a filled path drawn between two lines (datasets).\n\n// todo horizontal prop, for filling area horizontally?\n// todo support categorical data?\n// todo build StackedAreaChart that composes multiple AreaCharts\n\nexport default class AreaChart extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n /**\n * data getter for X coordinates\n */\n getX: CustomPropTypes.getter,\n /**\n * data getter for Y coordinates\n */\n getY: CustomPropTypes.getter,\n /**\n * data getter for Y end coordinates\n */\n getYEnd: CustomPropTypes.getter,\n /**\n * style applied to path element\n */\n pathStyle: PropTypes.object,\n /**\n * if isDifference is true, AreaChart generates a \"difference chart\" with two area paths instead of one:\n * one path which shows when YEnd > Y, and one vice versa, allowing them to be styled differently (eg red/green)\n */\n isDifference: PropTypes.bool,\n /**\n * when isDifference is true, pathStylePositive and pathStyleNegative can be passed to give 2 different inline\n * styles to the two different paths which are generated.\n * Ignored if isDifference is false.\n */\n pathStylePositive: PropTypes.object,\n pathStyleNegative: PropTypes.object,\n\n scaleType: PropTypes.object,\n scale: PropTypes.object,\n /**\n * if true, will show gaps in the shaded area for data where props.isDefined(datum) returns false\n */\n shouldShowGaps: PropTypes.bool,\n /**\n * if shouldShowGaps is true, isDefined function describes when a datum should be considered \"defined\" vs. when to show gap\n * by default, shows gap if either y or yEnd are undefined\n */\n isDefined: PropTypes.func\n };\n static defaultProps = {\n shouldShowGaps: true,\n isDefined: (d, i, accessors) => {\n return !_.isUndefined(accessors.y(d, i)) && !_.isUndefined(accessors.yEnd(d, i));\n }\n };\n\n static getDomain(props) {\n // custom Y domain - the total (union) extent of getY and getYEnd combined\n const {data, getX, getY, getYEnd} = props;\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY), yEnd: makeAccessor(getYEnd)};\n return {\n y: combineDomains([\n domainFromData(data, accessors.y),\n domainFromData(data, accessors.yEnd)\n ])\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['pathStyle', 'pathStylePositive', 'pathStyleNegative']);\n return shouldUpdate;\n }\n\n render() {\n const {name, data, getX, getY, getYEnd, scale, isDifference, pathStyle,\n pathStylePositive, pathStyleNegative, shouldShowGaps, isDefined} = this.props;\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY), yEnd: makeAccessor(getYEnd)};\n\n // create d3 area path generator\n const areaGenerator = area();\n\n // if gaps in data should be shown, use `props.isDefined` function as the `defined` param for d3's area generator;\n // but wrap it & pass in accessors as well, so that the function can easily access the relevant data values\n if(shouldShowGaps) {\n areaGenerator.defined((d, i) => isDefined(d, i, accessors));\n }\n\n areaGenerator\n .x((d, i) => scale.x(accessors.x(d, i)))\n .y0((d, i) => scale.y(accessors.y(d, i)))\n .y1((d, i) => scale.y(accessors.yEnd(d, i)));\n\n const areaPathStr = areaGenerator(data);\n\n if(isDifference) {\n // difference chart - create 2 clip paths, one which clips to only show path where YEnd > Y, and other vice versa\n areaGenerator.y0(this.props.height);\n const clipBelowPathStr = areaGenerator(data);\n areaGenerator.y0(0);\n const clipAbovePathStr = areaGenerator(data);\n\n // make sure we have a unique ID for this chart, so clip path IDs don't affect other charts\n const chartId = name || _.uniqueId();\n const clipAboveId = `clip-above-area-${chartId}`;\n const clipBelowId = `clip-below-area-${chartId}`;\n const pathStyleAbove = pathStylePositive || pathStyle || {};\n const pathStyleBelow = pathStyleNegative || pathStyle || {};\n\n return (\n \n \n \n \n \n \n \n \n );\n\n } else {\n return (\n \n );\n }\n }\n}\n"]} \ No newline at end of file diff --git a/lib/AreaHeatmap.js b/lib/AreaHeatmap.js index d64d1b0d..06348db2 100644 --- a/lib/AreaHeatmap.js +++ b/lib/AreaHeatmap.js @@ -28,6 +28,10 @@ var _util = require('./util.js'); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -90,6 +94,12 @@ var AreaHeatmap = function (_React$Component) { } _createClass(AreaHeatmap, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['rectStyle']); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var _props = this.props, diff --git a/lib/AreaHeatmap.js.map b/lib/AreaHeatmap.js.map index b561ed9d..d1db12b0 100644 --- a/lib/AreaHeatmap.js.map +++ b/lib/AreaHeatmap.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/AreaHeatmap.js"],"names":["AreaHeatmap","onMouseEnter","e","props","onMouseLeave","onMouseMove","scale","data","getArea","getX","getXEnd","getY","getYEnd","isFunction","boundBox","refs","background","getBoundingClientRect","x","clientX","left","y","clientY","top","invert","xVal","yVal","scaleWidth","scaleHeight","rectClassName","rectStyle","map","areaAccessor","xAccessor","xEndAccessor","yAccessor","yEndAccessor","unitsPerPixel","Math","max","apply","d","abs","handlers","i","fullWidth","fullHeight","x0","min","y0","width","sqrt","height","every","isFinite","className","style","key","flatten","Component","propTypes","number","string","object","defaultProps"],"mappings":"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","file":"AreaHeatmap.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {extent} from 'd3';\nimport PropTypes from 'prop-types';\n\nimport {methodIfFuncProp} from './util.js';\nimport {makeAccessor} from './utils/Data';\n\nexport default class AreaHeatmap extends React.Component {\n static propTypes = {\n unitsPerPixel: PropTypes.number,\n rectClassName: PropTypes.string,\n rectStyle: PropTypes.object\n };\n static defaultProps = {\n rectClassName: '',\n rectStyle: {}\n };\n\n static getDomain(props) {\n const {data, getX, getXEnd, getY, getYEnd} = props;\n return {\n x: extent(_.flatten([data.map(makeAccessor(getX)), data.map(makeAccessor(getXEnd))])),\n y: extent(_.flatten([data.map(makeAccessor(getY)), data.map(makeAccessor(getYEnd))]))\n };\n }\n\n onMouseEnter = (e) => {\n this.props.onMouseEnter(e);\n };\n onMouseLeave = (e) => {\n this.props.onMouseLeave(e);\n };\n onMouseMove = (e) => {\n const {scale, data, getArea, getX, getXEnd, getY, getYEnd, onMouseMove} = this.props;\n if(!_.isFunction(onMouseMove)) return;\n // const [xAccessor, xEndAccessor, yAccessor, yEndAccessor] =\n // [getArea, getX, getXEnd, getY, getYEnd].map(makeAccessor);\n\n const boundBox = this.refs.background.getBoundingClientRect();\n if(!boundBox) return;\n const [x, y] = [e.clientX - (boundBox.left || 0), e.clientY - (boundBox.top || 0)];\n const [xVal, yVal] = [scale.x.invert(x), scale.y.invert(y)];\n //const xD = _.find(data, d => xVal >= xAccessor(d) && xVal < xEndAccessor(d));\n //const yD = _.find(data, d => yVal >= yAccessor(d) && yVal < yEndAccessor(d));\n //const d = _.find(data,\n // d => xVal >= xAccessor(d) && xVal < xEndAccessor(d) && yVal >= yAccessor(d) && yVal < yEndAccessor(d));\n //const xBin = [xAccessor(xD), xEndAccessor(xD)];\n //const yBin = [yAccessor(yD), yEndAccessor(yD)];\n\n //onMouseMove(e, {xVal, yVal, d, xD, yD, xBin, yBin});\n onMouseMove(e, {xVal, yVal});\n };\n\n render() {\n const {data, getArea, getX, getXEnd, getY, getYEnd, scale, scaleWidth, scaleHeight, rectClassName, rectStyle}\n = this.props;\n const [areaAccessor, xAccessor, xEndAccessor, yAccessor, yEndAccessor] =\n [getArea, getX, getXEnd, getY, getYEnd].map(makeAccessor);\n\n // to determine how many data units are represented by 1 square pixel of area,\n // find the bin that would require the highest unit-per-pixel scale if its rectangle filled the whole container\n const unitsPerPixel = this.props.unitsPerPixel ||\n Math.max.apply(this, data.map(d => areaAccessor(d) / Math.abs(\n // area of entire containing rectangle\n (scale.x(xEndAccessor(d)) - scale.x(xAccessor(d))) * (scale.y(yEndAccessor(d)) - scale.y(yAccessor(d)))\n )));\n\n const handlers = {\n onMouseMove: methodIfFuncProp('onMouseMove', this.props, this),\n onMouseEnter: methodIfFuncProp('onMouseEnter', this.props, this),\n onMouseLeave: methodIfFuncProp('onMouseLeave', this.props, this)\n };\n\n return \n \n {data.map((d, i) => {\n // full width and height of the containing rectangle\n const fullWidth = Math.abs(scale.x(xEndAccessor(d)) - scale.x(xAccessor(d)));\n const fullHeight = Math.abs(scale.y(yEndAccessor(d)) - scale.y(yAccessor(d)));\n // x / y position of top left of the containing rectangle\n const x0 = Math.min(scale.x(xEndAccessor(d)), scale.x(xAccessor(d)));\n const y0 = Math.min(scale.y(yEndAccessor(d)), scale.y(yAccessor(d)));\n\n // we know two facts:\n // 1. the (pixel) area of the rect will be the data value divided by the # of data units per pixel\n // ie. area = height * width = areaAccessor(d) / unitsPerPixel\n // 2. all rectangles, regardless of size, have the same shape (are congruent), so the ratio\n // of the rect's width to the full width is equal to the ratio of its height to the full height.\n // ie. (height / fullHeight) = (width / fullWidth)\n // solve for height and width to get...\n const width = Math.sqrt((areaAccessor(d) / unitsPerPixel) * (fullWidth / fullHeight));\n const height = Math.sqrt((areaAccessor(d) / unitsPerPixel) * (fullHeight / fullWidth));\n\n // center the data rect in the containing rectangle\n const x = x0 + ((fullWidth - width) / 2);\n const y = y0 + ((fullHeight - height) / 2);\n\n if(!_.every([x, y, width, height], _.isFinite)) return null;\n\n const className = `area-heatmap-rect ${rectClassName}`;\n const style = rectStyle;\n const key = `rect-${i}`;\n\n return ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/AreaHeatmap.js"],"names":["AreaHeatmap","onMouseEnter","e","props","onMouseLeave","onMouseMove","scale","data","getArea","getX","getXEnd","getY","getYEnd","isFunction","boundBox","refs","background","getBoundingClientRect","x","clientX","left","y","clientY","top","invert","xVal","yVal","nextProps","nextState","shouldUpdate","scaleWidth","scaleHeight","rectClassName","rectStyle","map","areaAccessor","xAccessor","xEndAccessor","yAccessor","yEndAccessor","unitsPerPixel","Math","max","apply","d","abs","handlers","i","fullWidth","fullHeight","x0","min","y0","width","sqrt","height","every","isFinite","className","style","key","flatten","Component","propTypes","number","string","object","defaultProps"],"mappings":"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","file":"AreaHeatmap.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {extent} from 'd3';\nimport PropTypes from 'prop-types';\n\nimport {methodIfFuncProp} from './util.js';\nimport {makeAccessor} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\nexport default class AreaHeatmap extends React.Component {\n static propTypes = {\n unitsPerPixel: PropTypes.number,\n rectClassName: PropTypes.string,\n rectStyle: PropTypes.object\n };\n static defaultProps = {\n rectClassName: '',\n rectStyle: {}\n };\n\n static getDomain(props) {\n const {data, getX, getXEnd, getY, getYEnd} = props;\n return {\n x: extent(_.flatten([data.map(makeAccessor(getX)), data.map(makeAccessor(getXEnd))])),\n y: extent(_.flatten([data.map(makeAccessor(getY)), data.map(makeAccessor(getYEnd))]))\n };\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['rectStyle']);\n return shouldUpdate;\n }\n\n onMouseEnter = (e) => {\n this.props.onMouseEnter(e);\n };\n onMouseLeave = (e) => {\n this.props.onMouseLeave(e);\n };\n onMouseMove = (e) => {\n const {scale, data, getArea, getX, getXEnd, getY, getYEnd, onMouseMove} = this.props;\n if(!_.isFunction(onMouseMove)) return;\n // const [xAccessor, xEndAccessor, yAccessor, yEndAccessor] =\n // [getArea, getX, getXEnd, getY, getYEnd].map(makeAccessor);\n\n const boundBox = this.refs.background.getBoundingClientRect();\n if(!boundBox) return;\n const [x, y] = [e.clientX - (boundBox.left || 0), e.clientY - (boundBox.top || 0)];\n const [xVal, yVal] = [scale.x.invert(x), scale.y.invert(y)];\n //const xD = _.find(data, d => xVal >= xAccessor(d) && xVal < xEndAccessor(d));\n //const yD = _.find(data, d => yVal >= yAccessor(d) && yVal < yEndAccessor(d));\n //const d = _.find(data,\n // d => xVal >= xAccessor(d) && xVal < xEndAccessor(d) && yVal >= yAccessor(d) && yVal < yEndAccessor(d));\n //const xBin = [xAccessor(xD), xEndAccessor(xD)];\n //const yBin = [yAccessor(yD), yEndAccessor(yD)];\n\n //onMouseMove(e, {xVal, yVal, d, xD, yD, xBin, yBin});\n onMouseMove(e, {xVal, yVal});\n };\n\n render() {\n const {data, getArea, getX, getXEnd, getY, getYEnd, scale, scaleWidth, scaleHeight, rectClassName, rectStyle}\n = this.props;\n const [areaAccessor, xAccessor, xEndAccessor, yAccessor, yEndAccessor] =\n [getArea, getX, getXEnd, getY, getYEnd].map(makeAccessor);\n\n // to determine how many data units are represented by 1 square pixel of area,\n // find the bin that would require the highest unit-per-pixel scale if its rectangle filled the whole container\n const unitsPerPixel = this.props.unitsPerPixel ||\n Math.max.apply(this, data.map(d => areaAccessor(d) / Math.abs(\n // area of entire containing rectangle\n (scale.x(xEndAccessor(d)) - scale.x(xAccessor(d))) * (scale.y(yEndAccessor(d)) - scale.y(yAccessor(d)))\n )));\n\n const handlers = {\n onMouseMove: methodIfFuncProp('onMouseMove', this.props, this),\n onMouseEnter: methodIfFuncProp('onMouseEnter', this.props, this),\n onMouseLeave: methodIfFuncProp('onMouseLeave', this.props, this)\n };\n\n return \n \n {data.map((d, i) => {\n // full width and height of the containing rectangle\n const fullWidth = Math.abs(scale.x(xEndAccessor(d)) - scale.x(xAccessor(d)));\n const fullHeight = Math.abs(scale.y(yEndAccessor(d)) - scale.y(yAccessor(d)));\n // x / y position of top left of the containing rectangle\n const x0 = Math.min(scale.x(xEndAccessor(d)), scale.x(xAccessor(d)));\n const y0 = Math.min(scale.y(yEndAccessor(d)), scale.y(yAccessor(d)));\n\n // we know two facts:\n // 1. the (pixel) area of the rect will be the data value divided by the # of data units per pixel\n // ie. area = height * width = areaAccessor(d) / unitsPerPixel\n // 2. all rectangles, regardless of size, have the same shape (are congruent), so the ratio\n // of the rect's width to the full width is equal to the ratio of its height to the full height.\n // ie. (height / fullHeight) = (width / fullWidth)\n // solve for height and width to get...\n const width = Math.sqrt((areaAccessor(d) / unitsPerPixel) * (fullWidth / fullHeight));\n const height = Math.sqrt((areaAccessor(d) / unitsPerPixel) * (fullHeight / fullWidth));\n\n // center the data rect in the containing rectangle\n const x = x0 + ((fullWidth - width) / 2);\n const y = y0 + ((fullHeight - height) / 2);\n\n if(!_.every([x, y, width, height], _.isFinite)) return null;\n\n const className = `area-heatmap-rect ${rectClassName}`;\n const style = rectStyle;\n const key = `rect-${i}`;\n\n return ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/BarChart.js b/lib/BarChart.js index f232199b..166697ed 100644 --- a/lib/BarChart.js +++ b/lib/BarChart.js @@ -36,6 +36,10 @@ var _Scale = require('./utils/Scale'); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + 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; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -83,6 +87,12 @@ var BarChart = function (_React$Component) { } _createClass(BarChart, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['barStyle']); + return shouldUpdate; + } + }, { key: 'render', value: function render() { (0, _invariant2.default)((0, _Scale.hasXYScales)(this.props.scale), 'BarChart.props.scale.x and scale.y must both be valid d3 scales'); diff --git a/lib/BarChart.js.map b/lib/BarChart.js.map index bf2a92d4..b1a5d370 100644 --- a/lib/BarChart.js.map +++ b/lib/BarChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/BarChart.js"],"names":["CustomPropTypes","makeRangeBarChartProps","barChartProps","horizontal","getX","getY","getZero","constant","getXEnd","undefined","getYEnd","BarChart","props","scale","rangeBarChartProps","getDomain","getSpacing","Component","propTypes","xyObjectOf","func","isRequired","data","array","getter","bool","barThickness","number","barClassName","string","barStyle","object","getClass","onMouseEnterBar","onMouseMoveBar","onMouseLeaveBar","defaultProps"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;IAAYA,e;;AACZ;;AACA;;;;;;;;;;;;AAGA,SAASC,sBAAT,CAAgCC,aAAhC,EAA+C;AAC7C;AACA;AAF6C,MAGtCC,UAHsC,GAGZD,aAHY,CAGtCC,UAHsC;AAAA,MAG1BC,IAH0B,GAGZF,aAHY,CAG1BE,IAH0B;AAAA,MAGpBC,IAHoB,GAGZH,aAHY,CAGpBG,IAHoB;;AAI7C,MAAMC,UAAU,iBAAEC,QAAF,CAAW,CAAX,CAAhB;;AAEA,sBACKL,aADL;AAEEE,UAAMD,aAAaG,OAAb,GAAuBF,IAF/B;AAGEC,UAAMF,aAAaE,IAAb,GAAoBC,OAH5B;AAIEE,aAASL,aAAaC,IAAb,GAAoBK,SAJ/B;AAKEC,aAASP,aAAaM,SAAb,GAAyBJ;AALpC;AAOD;;AAED;;;;;;;;;;IAUqBM,Q;;;;;;;;;;;6BAgCV;AACP,+BAAU,wBAAY,KAAKC,KAAL,CAAWC,KAAvB,CAAV;;AAEA,UAAMC,qBAAqBb,uBAAuB,KAAKW,KAA5B,CAA3B;;AAEA,aAAO,uDAAmBE,kBAAnB,CAAP;AACD;;;;;AAbD;8BACiBF,K,EAAO;AACtB,aAAO,wBAAcG,SAAd,CAAwBd,uBAAuBW,KAAvB,CAAxB,CAAP;AACD;;;+BACiBA,K,EAAO;AACvB,aAAO,wBAAcI,UAAd,CAAyBf,uBAAuBW,KAAvB,CAAzB,CAAP;AACD;;;;EA/BmC,gBAAMK,S;;AAAvBN,Q,CACZO,S,GAAY;AACjBL,SAAOb,gBAAgBmB,UAAhB,CAA2B,oBAAUC,IAAV,CAAeC,UAA1C,CADU;AAEjBC,QAAM,oBAAUC,KAFC;AAGjBnB,QAAMJ,gBAAgBwB,MAHL;AAIjBnB,QAAML,gBAAgBwB,MAJL;AAKjBrB,cAAY,oBAAUsB,IALL;;AAOjBC,gBAAc,oBAAUC,MAPP;AAQjBC,gBAAc,oBAAUC,MARP;AASjBC,YAAU,oBAAUC,MATH;AAUjBC,YAAUhC,gBAAgBwB,MAVT;;AAYjBS,mBAAiB,oBAAUb,IAZV;AAajBc,kBAAgB,oBAAUd,IAbT;AAcjBe,mBAAiB,oBAAUf;AAdV,C;AADAT,Q,CAiBZyB,Y,GAAe;AACpBd,QAAM,EADc;AAEpBnB,cAAY,KAFQ;AAGpBuB,gBAAc,CAHM;AAIpBE,gBAAc,EAJM;AAKpBE,YAAU;AALU,C;kBAjBHnB,Q","file":"BarChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\nimport invariant from 'invariant';\nimport RangeBarChart from './RangeBarChart';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {hasXYScales} from './utils/Scale';\nimport {makeAccessor, domainFromData} from './utils/Data';\n\n\nfunction makeRangeBarChartProps(barChartProps) {\n // this component is a simple wrapper around RangeBarChart,\n // passing accessors to make range bars which span from zero to the data value\n const {horizontal, getX, getY} = barChartProps;\n const getZero = _.constant(0);\n\n return {\n ...barChartProps,\n getX: horizontal ? getZero : getX,\n getY: horizontal ? getY : getZero,\n getXEnd: horizontal ? getX : undefined,\n getYEnd: horizontal ? undefined : getY\n };\n}\n\n/**\n * BarChart represents a basic \"Value/Value\" bar chart,\n * where each bar represents a single independent variable value and a single dependent value,\n * with bars that are centered horizontally on x-value and extend from 0 to y-value,\n * (or centered vertically on their y-value and extend from 0 to the x-value, in the case of horizontal chart variant)\n * eg. http://www.snapsurveys.com/wp-content/uploads/2012/10/bar_2d8.png\n *\n * For other bar chart types, see RangeBarChart and AreaBarChart\n */\n\nexport default class BarChart extends React.Component {\n static propTypes = {\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n data: PropTypes.array,\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n horizontal: PropTypes.bool,\n\n barThickness: PropTypes.number,\n barClassName: PropTypes.string,\n barStyle: PropTypes.object,\n getClass: CustomPropTypes.getter,\n \n onMouseEnterBar: PropTypes.func,\n onMouseMoveBar: PropTypes.func,\n onMouseLeaveBar: PropTypes.func\n };\n static defaultProps = {\n data: [],\n horizontal: false,\n barThickness: 8,\n barClassName: '',\n barStyle: {}\n };\n\n // gets data domain of independent variable\n static getDomain(props) {\n return RangeBarChart.getDomain(makeRangeBarChartProps(props));\n }\n static getSpacing(props) {\n return RangeBarChart.getSpacing(makeRangeBarChartProps(props));\n }\n render() {\n invariant(hasXYScales(this.props.scale), `BarChart.props.scale.x and scale.y must both be valid d3 scales`);\n\n const rangeBarChartProps = makeRangeBarChartProps(this.props);\n\n return ;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/BarChart.js"],"names":["CustomPropTypes","makeRangeBarChartProps","barChartProps","horizontal","getX","getY","getZero","constant","getXEnd","undefined","getYEnd","BarChart","nextProps","nextState","shouldUpdate","props","scale","rangeBarChartProps","getDomain","getSpacing","Component","propTypes","xyObjectOf","func","isRequired","data","array","getter","bool","barThickness","number","barClassName","string","barStyle","object","getClass","onMouseEnterBar","onMouseMoveBar","onMouseLeaveBar","defaultProps"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;;;AACA;;IAAYA,e;;AACZ;;AACA;;AACA;;;;;;;;;;;;;;AAGA,SAASC,sBAAT,CAAgCC,aAAhC,EAA+C;AAC7C;AACA;AAF6C,MAGtCC,UAHsC,GAGZD,aAHY,CAGtCC,UAHsC;AAAA,MAG1BC,IAH0B,GAGZF,aAHY,CAG1BE,IAH0B;AAAA,MAGpBC,IAHoB,GAGZH,aAHY,CAGpBG,IAHoB;;AAI7C,MAAMC,UAAU,iBAAEC,QAAF,CAAW,CAAX,CAAhB;;AAEA,sBACKL,aADL;AAEEE,UAAMD,aAAaG,OAAb,GAAuBF,IAF/B;AAGEC,UAAMF,aAAaE,IAAb,GAAoBC,OAH5B;AAIEE,aAASL,aAAaC,IAAb,GAAoBK,SAJ/B;AAKEC,aAASP,aAAaM,SAAb,GAAyBJ;AALpC;AAOD;;AAED;;;;;;;;;;IAUqBM,Q;;;;;;;;;;;0CAiCGC,S,EAAWC,S,EAAW;AAC1C,UAAMC,eAAe,CAAC,4BAAa,KAAKC,KAAlB,EAAyBH,SAAzB,EAAoC,CAAC,UAAD,CAApC,CAAtB;AACA,aAAOE,YAAP;AACD;;;6BAEQ;AACP,+BAAU,wBAAY,KAAKC,KAAL,CAAWC,KAAvB,CAAV;;AAEA,UAAMC,qBAAqBhB,uBAAuB,KAAKc,KAA5B,CAA3B;;AAEA,aAAO,uDAAmBE,kBAAnB,CAAP;AACD;;;;;AAnBD;8BACiBF,K,EAAO;AACtB,aAAO,wBAAcG,SAAd,CAAwBjB,uBAAuBc,KAAvB,CAAxB,CAAP;AACD;;;+BACiBA,K,EAAO;AACvB,aAAO,wBAAcI,UAAd,CAAyBlB,uBAAuBc,KAAvB,CAAzB,CAAP;AACD;;;;EA/BmC,gBAAMK,S;;AAAvBT,Q,CACZU,S,GAAY;AACjBL,SAAOhB,gBAAgBsB,UAAhB,CAA2B,oBAAUC,IAAV,CAAeC,UAA1C,CADU;AAEjBC,QAAM,oBAAUC,KAFC;AAGjBtB,QAAMJ,gBAAgB2B,MAHL;AAIjBtB,QAAML,gBAAgB2B,MAJL;AAKjBxB,cAAY,oBAAUyB,IALL;;AAOjBC,gBAAc,oBAAUC,MAPP;AAQjBC,gBAAc,oBAAUC,MARP;AASjBC,YAAU,oBAAUC,MATH;AAUjBC,YAAUnC,gBAAgB2B,MAVT;;AAYjBS,mBAAiB,oBAAUb,IAZV;AAajBc,kBAAgB,oBAAUd,IAbT;AAcjBe,mBAAiB,oBAAUf;AAdV,C;AADAZ,Q,CAiBZ4B,Y,GAAe;AACpBd,QAAM,EADc;AAEpBtB,cAAY,KAFQ;AAGpB0B,gBAAc,CAHM;AAIpBE,gBAAc,EAJM;AAKpBE,YAAU;AALU,C;kBAjBHtB,Q","file":"BarChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\nimport invariant from 'invariant';\nimport RangeBarChart from './RangeBarChart';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {hasXYScales} from './utils/Scale';\nimport {makeAccessor, domainFromData} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\n\nfunction makeRangeBarChartProps(barChartProps) {\n // this component is a simple wrapper around RangeBarChart,\n // passing accessors to make range bars which span from zero to the data value\n const {horizontal, getX, getY} = barChartProps;\n const getZero = _.constant(0);\n\n return {\n ...barChartProps,\n getX: horizontal ? getZero : getX,\n getY: horizontal ? getY : getZero,\n getXEnd: horizontal ? getX : undefined,\n getYEnd: horizontal ? undefined : getY\n };\n}\n\n/**\n * BarChart represents a basic \"Value/Value\" bar chart,\n * where each bar represents a single independent variable value and a single dependent value,\n * with bars that are centered horizontally on x-value and extend from 0 to y-value,\n * (or centered vertically on their y-value and extend from 0 to the x-value, in the case of horizontal chart variant)\n * eg. http://www.snapsurveys.com/wp-content/uploads/2012/10/bar_2d8.png\n *\n * For other bar chart types, see RangeBarChart and AreaBarChart\n */\n\nexport default class BarChart extends React.Component {\n static propTypes = {\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n data: PropTypes.array,\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n horizontal: PropTypes.bool,\n\n barThickness: PropTypes.number,\n barClassName: PropTypes.string,\n barStyle: PropTypes.object,\n getClass: CustomPropTypes.getter,\n \n onMouseEnterBar: PropTypes.func,\n onMouseMoveBar: PropTypes.func,\n onMouseLeaveBar: PropTypes.func\n };\n static defaultProps = {\n data: [],\n horizontal: false,\n barThickness: 8,\n barClassName: '',\n barStyle: {}\n };\n\n // gets data domain of independent variable\n static getDomain(props) {\n return RangeBarChart.getDomain(makeRangeBarChartProps(props));\n }\n static getSpacing(props) {\n return RangeBarChart.getSpacing(makeRangeBarChartProps(props));\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['barStyle']);\n return shouldUpdate;\n }\n\n render() {\n invariant(hasXYScales(this.props.scale), `BarChart.props.scale.x and scale.y must both be valid d3 scales`);\n\n const rangeBarChartProps = makeRangeBarChartProps(this.props);\n\n return ;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/ColorHeatmap.js b/lib/ColorHeatmap.js index 5e671d7e..fda3bfc5 100644 --- a/lib/ColorHeatmap.js +++ b/lib/ColorHeatmap.js @@ -32,6 +32,10 @@ var _Data = require('./utils/Data'); var _Scale = require('./utils/Scale'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _RangeRect = require('./RangeRect'); var _RangeRect2 = _interopRequireDefault(_RangeRect); @@ -79,6 +83,12 @@ var ColorHeatmap = function (_React$Component) { } _createClass(ColorHeatmap, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['colors', 'valueDomain']); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var _props = this.props, diff --git a/lib/ColorHeatmap.js.map b/lib/ColorHeatmap.js.map index abf382b7..2c6113df 100644 --- a/lib/ColorHeatmap.js.map +++ b/lib/ColorHeatmap.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/ColorHeatmap.js"],"names":["CustomPropTypes","interpolatorFromType","type","toLowerCase","makeColorScale","domain","colors","interpolator","length","isString","range","interpolate","ColorHeatmap","props","data","scale","getValue","getX","getXEnd","getY","getYEnd","valueAccessor","colorScale","valueDomain","times","schemeCategory10","map","datum","i","color","style","fill","key","scaleType","x","y","Component","propTypes","xyObjectOf","func","isRequired","array","getter","string","defaultProps"],"mappings":"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","file":"ColorHeatmap.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {scaleLinear, interpolateHcl, interpolateHsl, interpolateLab, interpolateRgb} from 'd3';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {makeAccessor, domainFromData, domainFromRangeData} from './utils/Data';\nimport {dataTypeFromScaleType} from './utils/Scale';\nimport RangeRect from './RangeRect';\n\n\nfunction interpolatorFromType(type) {\n switch(type.toLowerCase()) {\n case 'hcl': return interpolateHcl;\n case 'hsl': return interpolateHsl;\n case 'lab': return interpolateLab;\n case 'rgb': return interpolateRgb;\n default: return interpolateHsl;\n }\n}\n\nfunction makeColorScale(domain, colors, interpolator) {\n invariant(domain.length == colors.length, 'makeColorScale: domain.length should equal colors.length');\n\n if(_.isString(interpolator))\n interpolator = interpolatorFromType(interpolator);\n\n return scaleLinear()\n .domain(domain)\n .range(colors)\n .interpolate(interpolator);\n}\n\nexport default class ColorHeatmap extends React.Component {\n static propTypes = {\n /**\n * d3 scale passed from xyplot\n */\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n /**\n * data array - should be 1D array of all grid values\n * (if you have a 2D array, _.flatten it)\n */\n data: PropTypes.array.isRequired,\n\n /**\n * data getters\n */\n getValue: CustomPropTypes.getter,\n getX: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n\n /**\n * a custom d3 color scale may be passed...\n */\n colorScale: PropTypes.func,\n /**\n * ...or else one will be constructed from colors, colorStops and interpolator\n */\n colors: PropTypes.array,\n valueDomain: PropTypes.array,\n interpolator: PropTypes.string\n };\n static defaultProps = {\n interpolator: 'lab'\n };\n\n static getDomain(props) {\n const {scaleType, data, getX, getXEnd, getY, getYEnd} = props;\n return {\n x: domainFromRangeData(data, makeAccessor(getX), makeAccessor(getXEnd), dataTypeFromScaleType(scaleType.x)),\n y: domainFromRangeData(data, makeAccessor(getY), makeAccessor(getYEnd), dataTypeFromScaleType(scaleType.y))\n };\n }\n\n render() {\n const {data, scale, getValue, getX, getXEnd, getY, getYEnd, interpolator} = this.props;\n const valueAccessor = makeAccessor(getValue);\n let colorScale;\n\n if(this.props.colorScale) colorScale = this.props.colorScale;\n else {\n const valueDomain = this.props.valueDomain || domainFromData(data, valueAccessor);\n const colors = this.props.colors || (\n (valueDomain.length == 2) ?\n ['#000000', '#ffffff'] :\n _.times(valueDomain.length, scale.schemeCategory10().domain(_.range(10)))\n );\n colorScale = makeColorScale(valueDomain, colors, interpolator);\n }\n\n return \n {data.map((datum, i) => {\n const color = colorScale(valueAccessor(datum));\n const style = {fill: color};\n const key = `heatmap-rect-${i}`;\n return \n })}\n ;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/ColorHeatmap.js"],"names":["CustomPropTypes","interpolatorFromType","type","toLowerCase","makeColorScale","domain","colors","interpolator","length","isString","range","interpolate","ColorHeatmap","nextProps","nextState","shouldUpdate","props","data","scale","getValue","getX","getXEnd","getY","getYEnd","valueAccessor","colorScale","valueDomain","times","schemeCategory10","map","datum","i","color","style","fill","key","scaleType","x","y","Component","propTypes","xyObjectOf","func","isRequired","array","getter","string","defaultProps"],"mappings":"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","file":"ColorHeatmap.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {scaleLinear, interpolateHcl, interpolateHsl, interpolateLab, interpolateRgb} from 'd3';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\n\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {makeAccessor, domainFromData, domainFromRangeData} from './utils/Data';\nimport {dataTypeFromScaleType} from './utils/Scale';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\nimport RangeRect from './RangeRect';\n\n\nfunction interpolatorFromType(type) {\n switch(type.toLowerCase()) {\n case 'hcl': return interpolateHcl;\n case 'hsl': return interpolateHsl;\n case 'lab': return interpolateLab;\n case 'rgb': return interpolateRgb;\n default: return interpolateHsl;\n }\n}\n\nfunction makeColorScale(domain, colors, interpolator) {\n invariant(domain.length == colors.length, 'makeColorScale: domain.length should equal colors.length');\n\n if(_.isString(interpolator))\n interpolator = interpolatorFromType(interpolator);\n\n return scaleLinear()\n .domain(domain)\n .range(colors)\n .interpolate(interpolator);\n}\n\nexport default class ColorHeatmap extends React.Component {\n static propTypes = {\n /**\n * d3 scale passed from xyplot\n */\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n /**\n * data array - should be 1D array of all grid values\n * (if you have a 2D array, _.flatten it)\n */\n data: PropTypes.array.isRequired,\n\n /**\n * data getters\n */\n getValue: CustomPropTypes.getter,\n getX: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n\n /**\n * a custom d3 color scale may be passed...\n */\n colorScale: PropTypes.func,\n /**\n * ...or else one will be constructed from colors, colorStops and interpolator\n */\n colors: PropTypes.array,\n valueDomain: PropTypes.array,\n interpolator: PropTypes.string\n };\n static defaultProps = {\n interpolator: 'lab'\n };\n\n static getDomain(props) {\n const {scaleType, data, getX, getXEnd, getY, getYEnd} = props;\n return {\n x: domainFromRangeData(data, makeAccessor(getX), makeAccessor(getXEnd), dataTypeFromScaleType(scaleType.x)),\n y: domainFromRangeData(data, makeAccessor(getY), makeAccessor(getYEnd), dataTypeFromScaleType(scaleType.y))\n };\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['colors', 'valueDomain']);\n return shouldUpdate;\n }\n\n render() {\n const {data, scale, getValue, getX, getXEnd, getY, getYEnd, interpolator} = this.props;\n const valueAccessor = makeAccessor(getValue);\n let colorScale;\n\n if(this.props.colorScale) colorScale = this.props.colorScale;\n else {\n const valueDomain = this.props.valueDomain || domainFromData(data, valueAccessor);\n const colors = this.props.colors || (\n (valueDomain.length == 2) ?\n ['#000000', '#ffffff'] :\n _.times(valueDomain.length, scale.schemeCategory10().domain(_.range(10)))\n );\n colorScale = makeColorScale(valueDomain, colors, interpolator);\n }\n\n return \n {data.map((datum, i) => {\n const color = colorScale(valueAccessor(datum));\n const style = {fill: color};\n const key = `heatmap-rect-${i}`;\n return \n })}\n ;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/FunnelChart.js b/lib/FunnelChart.js index 64c041b1..fd962a4d 100644 --- a/lib/FunnelChart.js +++ b/lib/FunnelChart.js @@ -32,6 +32,10 @@ var _Data = require('./utils/Data'); var _Scale = require('./utils/Scale'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + 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; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -52,6 +56,12 @@ var FunnelChart = function (_React$Component) { } _createClass(FunnelChart, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, []); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var _props = this.props, diff --git a/lib/FunnelChart.js.map b/lib/FunnelChart.js.map index a622287a..9fe8907f 100644 --- a/lib/FunnelChart.js.map +++ b/lib/FunnelChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/FunnelChart.js"],"names":["CustomPropTypes","FunnelChart","props","data","scale","getX","getY","horizontal","funnelArea","x0","x","d","x1","y","y0","y1","colors","domain","range","map","i","pathStr","fill","stroke","scaleType","xAccessor","yAccessor","xDataType","yDataType","Component","propTypes","xyObjectOf","func","isRequired","array","getter","defaultProps"],"mappings":"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","file":"FunnelChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {area, scaleOrdinal, schemeCategory20b} from 'd3';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {makeAccessor, domainFromData, combineDomains} from './utils/Data';\nimport {dataTypeFromScaleType} from './utils/Scale';\n\nexport default class FunnelChart extends React.Component {\n static propTypes = {\n // passed from xyplot\n\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n // data array\n data: PropTypes.array.isRequired,\n // data getters\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter\n };\n static defaultProps = {\n\n };\n\n static getDomain(props) {\n const {data, scale, scaleType, getX, getY, horizontal} = props;\n const [xAccessor, yAccessor] = [makeAccessor(getX), makeAccessor(getY)];\n const [xDataType, yDataType] = [dataTypeFromScaleType(scaleType.x), dataTypeFromScaleType(scaleType.y)];\n\n return horizontal ?\n {\n x: combineDomains([\n domainFromData(data, xAccessor, xDataType),\n domainFromData(data, d => -xAccessor(d), xDataType)\n ]),\n y: domainFromData(data, yAccessor, yDataType)\n } :\n {\n x: domainFromData(data, xAccessor, xDataType),\n y: combineDomains([\n domainFromData(data, yAccessor, yDataType),\n domainFromData(data, d => -yAccessor(d), yDataType)\n ])\n };\n }\n\n render() {\n const {data, scale, getX, getY, horizontal} = this.props;\n\n const funnelArea = area();\n if(horizontal) {\n funnelArea\n .x0(d => scale.x(-makeAccessor(getX)(d)))\n .x1(d => scale.x(makeAccessor(getX)(d)))\n .y(d => scale.y(makeAccessor(getY)(d)));\n } else {\n funnelArea\n .x(d => scale.x(makeAccessor(getX)(d)))\n .y0(d => scale.y(-makeAccessor(getY)(d)))\n .y1(d => scale.y(makeAccessor(getY)(d)));\n }\n\n const colors = scaleOrdinal(schemeCategory20b).domain(_.range(10));\n\n return \n {data.map((d, i) => {\n if(i == 0) return null;\n const pathStr = funnelArea([data[i-1], d]);\n\n return ;\n })}\n \n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/FunnelChart.js"],"names":["CustomPropTypes","FunnelChart","nextProps","nextState","shouldUpdate","props","data","scale","getX","getY","horizontal","funnelArea","x0","x","d","x1","y","y0","y1","colors","domain","range","map","i","pathStr","fill","stroke","scaleType","xAccessor","yAccessor","xDataType","yDataType","Component","propTypes","xyObjectOf","func","isRequired","array","getter","defaultProps"],"mappings":"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","file":"FunnelChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {area, scaleOrdinal, schemeCategory20b} from 'd3';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {makeAccessor, domainFromData, combineDomains} from './utils/Data';\nimport {dataTypeFromScaleType} from './utils/Scale';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\nexport default class FunnelChart extends React.Component {\n static propTypes = {\n // passed from xyplot\n\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n // data array\n data: PropTypes.array.isRequired,\n // data getters\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter\n };\n static defaultProps = {\n\n };\n\n static getDomain(props) {\n const {data, scale, scaleType, getX, getY, horizontal} = props;\n const [xAccessor, yAccessor] = [makeAccessor(getX), makeAccessor(getY)];\n const [xDataType, yDataType] = [dataTypeFromScaleType(scaleType.x), dataTypeFromScaleType(scaleType.y)];\n\n return horizontal ?\n {\n x: combineDomains([\n domainFromData(data, xAccessor, xDataType),\n domainFromData(data, d => -xAccessor(d), xDataType)\n ]),\n y: domainFromData(data, yAccessor, yDataType)\n } :\n {\n x: domainFromData(data, xAccessor, xDataType),\n y: combineDomains([\n domainFromData(data, yAccessor, yDataType),\n domainFromData(data, d => -yAccessor(d), yDataType)\n ])\n };\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, []);\n return shouldUpdate;\n }\n\n render() {\n const {data, scale, getX, getY, horizontal} = this.props;\n\n const funnelArea = area();\n if(horizontal) {\n funnelArea\n .x0(d => scale.x(-makeAccessor(getX)(d)))\n .x1(d => scale.x(makeAccessor(getX)(d)))\n .y(d => scale.y(makeAccessor(getY)(d)));\n } else {\n funnelArea\n .x(d => scale.x(makeAccessor(getX)(d)))\n .y0(d => scale.y(-makeAccessor(getY)(d)))\n .y1(d => scale.y(makeAccessor(getY)(d)));\n }\n\n const colors = scaleOrdinal(schemeCategory20b).domain(_.range(10));\n\n return \n {data.map((d, i) => {\n if(i == 0) return null;\n const pathStr = funnelArea([data[i-1], d]);\n\n return ;\n })}\n \n }\n}\n"]} \ No newline at end of file diff --git a/lib/Histogram.js b/lib/Histogram.js index ad857aca..14fa35ea 100644 --- a/lib/Histogram.js +++ b/lib/Histogram.js @@ -28,6 +28,10 @@ var CustomPropTypes = _interopRequireWildcard(_CustomPropTypes); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _AreaBarChart = require('./AreaBarChart'); var _AreaBarChart2 = _interopRequireDefault(_AreaBarChart); @@ -63,6 +67,12 @@ var Histogram = function (_React$Component) { } _createClass(Histogram, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, []); + return shouldUpdate; + } + }, { key: 'componentWillMount', value: function componentWillMount() { var _props = this.props, diff --git a/lib/Histogram.js.map b/lib/Histogram.js.map index 202d81a7..2e5d58c7 100644 --- a/lib/Histogram.js.map +++ b/lib/Histogram.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/Histogram.js"],"names":["CustomPropTypes","Histogram","state","histogramData","props","domain","getValue","data","chartHistogram","x","value","thresholds","setState","name","scale","axisType","scaleWidth","scaleHeight","plotWidth","plotHeight","d","x0","x1","length","y","Component","propTypes","array","isRequired","getter","object"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;AACA;;IAAYA,e;;AACZ;;AACA;;;;;;;;;;;;;;AAEA;IACqBC,S;;;;;;;;;;;;;;4LAWnBC,K,GAAQ;AACNC,qBAAe;AADT,K;;;;;yCAYa;AAAA,mBACc,KAAKC,KADnB;AAAA,UACZC,MADY,UACZA,MADY;AAAA,UACJC,QADI,UACJA,QADI;AAAA,UACMC,IADN,UACMA,IADN;;AAEnB,UAAMC,iBAAiB,oBACpBH,MADoB,CACbA,OAAOI,CADM;AAErB;AAFqB,OAGpBC,KAHoB,CAGd,wBAAaJ,QAAb,CAHc,EAIpBK,UAJoB,CAIT,EAJS,CAAvB;;AAMA,UAAMR,gBAAgBK,eAAeD,IAAf,CAAtB;;AAEA,WAAKK,QAAL,CAAc,EAACT,4BAAD,EAAd;AACD;;;6BAEQ;AACP,UAAG,CAAC,KAAKD,KAAL,CAAWC,aAAf,EAA8B,OAAO,wCAAP;AADvB,oBAEyE,KAAKC,KAF9E;AAAA,UAEAS,IAFA,WAEAA,IAFA;AAAA,UAEMC,KAFN,WAEMA,KAFN;AAAA,UAEaC,QAFb,WAEaA,QAFb;AAAA,UAEuBC,UAFvB,WAEuBA,UAFvB;AAAA,UAEmCC,WAFnC,WAEmCA,WAFnC;AAAA,UAEgDC,SAFhD,WAEgDA,SAFhD;AAAA,UAE2DC,UAF3D,WAE2DA,UAF3D;;;AAIP,aAAO;AACL,cAAM,KAAKjB,KAAL,CAAWC,aADZ;AAEL,cAAM;AAAA,iBAAKiB,EAAEC,EAAP;AAAA,SAFD;AAGL,iBAAS;AAAA,iBAAKD,EAAEE,EAAP;AAAA,SAHJ;AAIL,cAAM;AAAA,iBAAKF,EAAEG,MAAP;AAAA;AAJD,SAKD,EAACV,UAAD,EAAOC,YAAP,EAAcC,kBAAd,EAAwBC,sBAAxB,EAAoCC,wBAApC,EAAiDC,oBAAjD,EAA4DC,sBAA5D,EALC,EAAP;AAOD;;;gCAhCkB;AACjB;AACA,aAAO;AACLV,WAAG,IADE;AAELe,WAAG,CAAC,CAAD,EAAG,GAAH;AAFE,OAAP;AAID;;;;EArBoC,gBAAMC,S;;AAAxBxB,S,CACZyB,S,GAAY;AACjB;;;AAGAnB,QAAM,oBAAUoB,KAAV,CAAgBC,UAJL;AAKjBtB,YAAUN,gBAAgB6B,MALT;AAMjBd,YAAU,oBAAUe,MANH;AAOjBhB,SAAO,oBAAUgB;AAPA,C;kBADA7B,S","file":"Histogram.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {histogram} from 'd3';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {makeAccessor, domainFromRangeData} from './utils/Data';\nimport AreaBarChart from './AreaBarChart';\n\n// todo make histogram work horizontally *or* vertically\nexport default class Histogram extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n getValue: CustomPropTypes.getter,\n axisType: PropTypes.object,\n scale: PropTypes.object\n };\n\n state = {\n histogramData: null\n };\n\n static getDomain() {\n // todo implement for real\n return {\n x: null,\n y: [0,200]\n }\n }\n\n componentWillMount() {\n const {domain, getValue, data} = this.props;\n const chartHistogram = histogram()\n .domain(domain.x)\n // todo - get this working with arbitrary getValue accessor - seems to be broken -DD\n .value(makeAccessor(getValue))\n .thresholds(30);\n\n const histogramData = chartHistogram(data);\n\n this.setState({histogramData});\n }\n\n render() {\n if(!this.state.histogramData) return ;\n const {name, scale, axisType, scaleWidth, scaleHeight, plotWidth, plotHeight} = this.props;\n\n return d.x0}\n getXEnd={d => d.x1}\n getY={d => d.length}\n {...{name, scale, axisType, scaleWidth, scaleHeight, plotWidth, plotHeight}}\n />;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/Histogram.js"],"names":["CustomPropTypes","Histogram","state","histogramData","nextProps","nextState","shouldUpdate","props","domain","getValue","data","chartHistogram","x","value","thresholds","setState","name","scale","axisType","scaleWidth","scaleHeight","plotWidth","plotHeight","d","x0","x1","length","y","Component","propTypes","array","isRequired","getter","object"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;AAEA;;IAAYA,e;;AACZ;;AACA;;;;AAEA;;;;;;;;;;;;;;AAEA;IACqBC,S;;;;;;;;;;;;;;4LAWnBC,K,GAAQ;AACNC,qBAAe;AADT,K;;;;;0CAYcC,S,EAAWC,S,EAAW;AAC1C,UAAMC,eAAe,CAAC,4BAAa,KAAKC,KAAlB,EAAyBH,SAAzB,EAAoC,EAApC,CAAtB;AACA,aAAOE,YAAP;AACD;;;yCAEoB;AAAA,mBACc,KAAKC,KADnB;AAAA,UACZC,MADY,UACZA,MADY;AAAA,UACJC,QADI,UACJA,QADI;AAAA,UACMC,IADN,UACMA,IADN;;AAEnB,UAAMC,iBAAiB,oBACpBH,MADoB,CACbA,OAAOI,CADM;AAErB;AAFqB,OAGpBC,KAHoB,CAGd,wBAAaJ,QAAb,CAHc,EAIpBK,UAJoB,CAIT,EAJS,CAAvB;;AAMA,UAAMX,gBAAgBQ,eAAeD,IAAf,CAAtB;;AAEA,WAAKK,QAAL,CAAc,EAACZ,4BAAD,EAAd;AACD;;;6BAEQ;AACP,UAAG,CAAC,KAAKD,KAAL,CAAWC,aAAf,EAA8B,OAAO,wCAAP;AADvB,oBAEyE,KAAKI,KAF9E;AAAA,UAEAS,IAFA,WAEAA,IAFA;AAAA,UAEMC,KAFN,WAEMA,KAFN;AAAA,UAEaC,QAFb,WAEaA,QAFb;AAAA,UAEuBC,UAFvB,WAEuBA,UAFvB;AAAA,UAEmCC,WAFnC,WAEmCA,WAFnC;AAAA,UAEgDC,SAFhD,WAEgDA,SAFhD;AAAA,UAE2DC,UAF3D,WAE2DA,UAF3D;;;AAIP,aAAO;AACL,cAAM,KAAKpB,KAAL,CAAWC,aADZ;AAEL,cAAM;AAAA,iBAAKoB,EAAEC,EAAP;AAAA,SAFD;AAGL,iBAAS;AAAA,iBAAKD,EAAEE,EAAP;AAAA,SAHJ;AAIL,cAAM;AAAA,iBAAKF,EAAEG,MAAP;AAAA;AAJD,SAKD,EAACV,UAAD,EAAOC,YAAP,EAAcC,kBAAd,EAAwBC,sBAAxB,EAAoCC,wBAApC,EAAiDC,oBAAjD,EAA4DC,sBAA5D,EALC,EAAP;AAOD;;;gCArCkB;AACjB;AACA,aAAO;AACLV,WAAG,IADE;AAELe,WAAG,CAAC,CAAD,EAAG,GAAH;AAFE,OAAP;AAID;;;;EArBoC,gBAAMC,S;;AAAxB3B,S,CACZ4B,S,GAAY;AACjB;;;AAGAnB,QAAM,oBAAUoB,KAAV,CAAgBC,UAJL;AAKjBtB,YAAUT,gBAAgBgC,MALT;AAMjBd,YAAU,oBAAUe,MANH;AAOjBhB,SAAO,oBAAUgB;AAPA,C;kBADAhC,S","file":"Histogram.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {histogram} from 'd3';\nimport PropTypes from 'prop-types';\n\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {makeAccessor, domainFromRangeData} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\nimport AreaBarChart from './AreaBarChart';\n\n// todo make histogram work horizontally *or* vertically\nexport default class Histogram extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n getValue: CustomPropTypes.getter,\n axisType: PropTypes.object,\n scale: PropTypes.object\n };\n\n state = {\n histogramData: null\n };\n\n static getDomain() {\n // todo implement for real\n return {\n x: null,\n y: [0,200]\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, []);\n return shouldUpdate;\n }\n\n componentWillMount() {\n const {domain, getValue, data} = this.props;\n const chartHistogram = histogram()\n .domain(domain.x)\n // todo - get this working with arbitrary getValue accessor - seems to be broken -DD\n .value(makeAccessor(getValue))\n .thresholds(30);\n\n const histogramData = chartHistogram(data);\n\n this.setState({histogramData});\n }\n\n render() {\n if(!this.state.histogramData) return ;\n const {name, scale, axisType, scaleWidth, scaleHeight, plotWidth, plotHeight} = this.props;\n\n return d.x0}\n getXEnd={d => d.x1}\n getY={d => d.length}\n {...{name, scale, axisType, scaleWidth, scaleHeight, plotWidth, plotHeight}}\n />;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/KernelDensityEstimation.js b/lib/KernelDensityEstimation.js index 78ce8c58..2176a2aa 100644 --- a/lib/KernelDensityEstimation.js +++ b/lib/KernelDensityEstimation.js @@ -26,6 +26,10 @@ var _CustomPropTypes = require('./utils/CustomPropTypes'); var CustomPropTypes = _interopRequireWildcard(_CustomPropTypes); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _LineChart = require('./LineChart.js'); var _LineChart2 = _interopRequireDefault(_LineChart); @@ -60,6 +64,12 @@ var KernelDensityEstimation = function (_React$Component) { } _createClass(KernelDensityEstimation, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, []); + return shouldUpdate; + } + }, { key: 'componentWillMount', value: function componentWillMount() { this.initKDE(this.props); diff --git a/lib/KernelDensityEstimation.js.map b/lib/KernelDensityEstimation.js.map index d9a0fd11..2540187b 100644 --- a/lib/KernelDensityEstimation.js.map +++ b/lib/KernelDensityEstimation.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/KernelDensityEstimation.js"],"names":["CustomPropTypes","KernelDensityEstimation","state","kdeData","initKDE","props","newProps","data","bandwidth","sampleCount","scale","width","kernel","epanechnikovKernel","samples","x","ticks","Math","ceil","setState","kernelDensityEstimator","name","height","plotWidth","plotHeight","d","y","Component","propTypes","array","isRequired","number","getX","getter","getY","string","object","axisType","scaleWidth","scaleHeight","defaultProps","sample","map","v","u","abs"],"mappings":"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","file":"KernelDensityEstimation.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {mean} from 'd3';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport LineChart from './LineChart.js';\n\nclass KernelDensityEstimation extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n\n /**\n * Kernel bandwidth for kernel density estimator.\n * High bandwidth => oversmoothing & underfitting; low bandwidth => undersmoothing & overfitting\n */\n bandwidth: PropTypes.number,\n /**\n * Number of samples to take from the KDE,\n * ie. the resolution/smoothness of the KDE line - more samples => higher resolution, smooth line.\n * Defaults to null, which causes it to be auto-determined based on width.\n */\n sampleCount: PropTypes.number,\n\n // common props from XYPlot\n // accessor for data values\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n name: PropTypes.string,\n scale: PropTypes.object,\n axisType: PropTypes.object,\n scaleWidth: PropTypes.number,\n scaleHeight: PropTypes.number\n };\n static defaultProps = {\n bandwidth: 0.5,\n sampleCount: null, // null = auto-determined based on width\n name: ''\n };\n\n state = {\n kdeData: null\n };\n\n static getDomain() {\n // todo implement real static getDomain method\n return {\n x: null,\n y: [0,200]\n }\n }\n\n componentWillMount() {\n this.initKDE(this.props);\n }\n componentWillReceiveProps(newProps) {\n this.initKDE(newProps);\n }\n initKDE(props) {\n const {data, bandwidth, sampleCount, scale, width} = props;\n const kernel = epanechnikovKernel(bandwidth);\n const samples = scale.x.ticks(sampleCount || Math.ceil(width / 2));\n this.setState({kdeData: kernelDensityEstimator(kernel, samples)(data)});\n }\n\n render() {\n const {name, scale, width, height, plotWidth, plotHeight} = this.props;\n const {kdeData} = this.state;\n\n return d[1] * 500}\n {...{name, scale, width, height, plotWidth, plotHeight}}\n />;\n }\n}\n\nfunction kernelDensityEstimator(kernel, x) {\n return function(sample) {\n return x.map(function(x) {\n return [x, mean(sample, function(v) { return kernel(x - v); })];\n });\n };\n}\n\nfunction epanechnikovKernel(scale) {\n return function(u) {\n return Math.abs(u /= scale) <= 1 ? .75 * (1 - u * u) / scale : 0;\n };\n}\n\nexport default KernelDensityEstimation;\n"]} \ No newline at end of file +{"version":3,"sources":["../src/KernelDensityEstimation.js"],"names":["CustomPropTypes","KernelDensityEstimation","state","kdeData","nextProps","nextState","shouldUpdate","props","initKDE","newProps","data","bandwidth","sampleCount","scale","width","kernel","epanechnikovKernel","samples","x","ticks","Math","ceil","setState","kernelDensityEstimator","name","height","plotWidth","plotHeight","d","y","Component","propTypes","array","isRequired","number","getX","getter","getY","string","object","axisType","scaleWidth","scaleHeight","defaultProps","sample","map","v","u","abs"],"mappings":"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","file":"KernelDensityEstimation.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {mean} from 'd3';\nimport PropTypes from 'prop-types';\n\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\nimport LineChart from './LineChart.js';\n\nclass KernelDensityEstimation extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n\n /**\n * Kernel bandwidth for kernel density estimator.\n * High bandwidth => oversmoothing & underfitting; low bandwidth => undersmoothing & overfitting\n */\n bandwidth: PropTypes.number,\n /**\n * Number of samples to take from the KDE,\n * ie. the resolution/smoothness of the KDE line - more samples => higher resolution, smooth line.\n * Defaults to null, which causes it to be auto-determined based on width.\n */\n sampleCount: PropTypes.number,\n\n // common props from XYPlot\n // accessor for data values\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n name: PropTypes.string,\n scale: PropTypes.object,\n axisType: PropTypes.object,\n scaleWidth: PropTypes.number,\n scaleHeight: PropTypes.number\n };\n static defaultProps = {\n bandwidth: 0.5,\n sampleCount: null, // null = auto-determined based on width\n name: ''\n };\n\n state = {\n kdeData: null\n };\n\n static getDomain() {\n // todo implement real static getDomain method\n return {\n x: null,\n y: [0,200]\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, []);\n return shouldUpdate;\n }\n\n componentWillMount() {\n this.initKDE(this.props);\n }\n componentWillReceiveProps(newProps) {\n this.initKDE(newProps);\n }\n initKDE(props) {\n const {data, bandwidth, sampleCount, scale, width} = props;\n const kernel = epanechnikovKernel(bandwidth);\n const samples = scale.x.ticks(sampleCount || Math.ceil(width / 2));\n this.setState({kdeData: kernelDensityEstimator(kernel, samples)(data)});\n }\n\n render() {\n const {name, scale, width, height, plotWidth, plotHeight} = this.props;\n const {kdeData} = this.state;\n\n return d[1] * 500}\n {...{name, scale, width, height, plotWidth, plotHeight}}\n />;\n }\n}\n\nfunction kernelDensityEstimator(kernel, x) {\n return function(sample) {\n return x.map(function(x) {\n return [x, mean(sample, function(v) { return kernel(x - v); })];\n });\n };\n}\n\nfunction epanechnikovKernel(scale) {\n return function(u) {\n return Math.abs(u /= scale) <= 1 ? .75 * (1 - u * u) / scale : 0;\n };\n}\n\nexport default KernelDensityEstimation;\n"]} \ No newline at end of file diff --git a/lib/LineChart.js b/lib/LineChart.js index 93851dc9..2075fae1 100644 --- a/lib/LineChart.js +++ b/lib/LineChart.js @@ -40,7 +40,7 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } -// import {xyPropsEqualDebug} from './utils/xyPropsEqual'; +// import {xyPropsEqualDebug as xyPropsEqual} from './utils/xyPropsEqual'; var LineChart = function (_React$Component) { @@ -76,7 +76,7 @@ var LineChart = function (_React$Component) { }, { key: 'shouldComponentUpdate', value: function shouldComponentUpdate(nextProps, nextState) { - return !(0, _xyPropsEqual2.default)(this.props, nextProps); + return !(0, _xyPropsEqual2.default)(this.props, nextProps, ['lineStyle']); } }, { key: 'initBisector', diff --git a/lib/LineChart.js.map b/lib/LineChart.js.map index 6a482a23..a4e1d040 100644 --- a/lib/LineChart.js.map +++ b/lib/LineChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/LineChart.js"],"names":["LineChart","getHovered","x","y","closestDataIndex","state","bisectX","props","data","initBisector","nextProps","nextState","setState","getX","d","left","scale","getY","lineStyle","accessors","points","map","pathStr","pointsToPathStr","name","Component","propTypes","array","isRequired","any","object","defaultProps","i","command","join"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;AACA;;;;AAEA;;AACA;;;;;;;;;;;;AACA;;;IAGqBA,S;;;;;;;;;;;;;;4LA0CnBC,U,GAAa,UAACC,CAAD,EAAIC,CAAJ,EAAU;AACrB,UAAMC,mBAAmB,MAAKC,KAAL,CAAWC,OAAX,CAAmB,MAAKC,KAAL,CAAWC,IAA9B,EAAoCN,CAApC,CAAzB;AACA,aAAO,MAAKK,KAAL,CAAWC,IAAX,CAAgBJ,gBAAhB,CAAP;AACD,K;;;;;yCAlBoB;AACnB,WAAKK,YAAL,CAAkB,KAAKF,KAAvB;AACD;;;8CACyBG,S,EAAW;AACnC,WAAKD,YAAL,CAAkBC,SAAlB;AACD;;;0CAEqBA,S,EAAWC,S,EAAW;AAC1C,aAAO,CAAC,4BAAa,KAAKJ,KAAlB,EAAyBG,SAAzB,CAAR;AACD;;;iCAEYH,K,EAAO;AAClB,WAAKK,QAAL,CAAc,EAACN,SAAS,iBAAS;AAAA,iBAAK,wBAAaC,MAAMM,IAAnB,EAAyBC,CAAzB,CAAL;AAAA,SAAT,EAA2CC,IAArD,EAAd;AACD;;;6BAOQ;AAAA,mBACsC,KAAKR,KAD3C;AAAA,UACAC,IADA,UACAA,IADA;AAAA,UACMQ,KADN,UACMA,KADN;AAAA,UACaH,IADb,UACaA,IADb;AAAA,UACmBI,IADnB,UACmBA,IADnB;AAAA,UACyBC,SADzB,UACyBA,SADzB;;AAEP,UAAMC,YAAY,EAACjB,GAAG,wBAAaW,IAAb,CAAJ,EAAwBV,GAAG,wBAAac,IAAb,CAA3B,EAAlB;AACA,UAAMG,SAAS,iBAAEC,GAAF,CAAMb,IAAN,EAAY;AAAA,eAAK,CAACQ,MAAMd,CAAN,CAAQiB,UAAUjB,CAAV,CAAYY,CAAZ,CAAR,CAAD,EAA0BE,MAAMb,CAAN,CAAQgB,UAAUhB,CAAV,CAAYW,CAAZ,CAAR,CAA1B,CAAL;AAAA,OAAZ,CAAf;AACA,UAAMQ,UAAUC,gBAAgBH,MAAhB,CAAhB;;AAEA,aAAO;AAAA;AAAA,UAAG,WAAW,KAAKb,KAAL,CAAWiB,IAAzB;AACL,gDAAM,GAAGF,OAAT,EAAkB,OAAOJ,SAAzB;AADK,OAAP;AAGD;;;;EAxDoC,gBAAMO,S;;AAAxBzB,S,CACZ0B,S,GAAY;AACjB;;;AAGAlB,QAAM,oBAAUmB,KAAV,CAAgBC,UAJL;AAKjB;;;AAGAf,QAAM,oBAAUgB,GARC;AASjB;;;AAGAZ,QAAM,oBAAUY,GAZC;AAajB;;;AAGAX,aAAW,oBAAUY,MAhBJ;AAiBjB;;;AAGAd,SAAO,oBAAUc;AApBA,C;AADA9B,S,CAuBZ+B,Y,GAAe;AACpBb,aAAW;AADS,C;kBAvBHlB,S;;;AA2DrB,SAASuB,eAAT,CAAyBH,MAAzB,EAAiC;AAC/B;AACA;AACA;AACA,SAAO,iBAAEC,GAAF,CAAMD,MAAN,EAAc,iBAASY,CAAT,EAAe;AAAA;AAAA,QAAb9B,CAAa;AAAA,QAAVC,CAAU;;AAClC,QAAM8B,UAAWD,MAAM,CAAP,GAAY,GAAZ,GAAkB,GAAlC;AACA,WAAUC,OAAV,SAAqB/B,CAArB,SAA0BC,CAA1B;AACD,GAHM,EAGJ+B,IAHI,CAGC,GAHD,CAAP;AAID","file":"LineChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {bisector} from 'd3';\nimport shallowEqual from './utils/shallowEqual';\nimport PropTypes from 'prop-types';\n\nimport {makeAccessor} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\n// import {xyPropsEqualDebug} from './utils/xyPropsEqual';\n\n\nexport default class LineChart extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n /**\n * data getter for line X coordinates\n */\n getX: PropTypes.any,\n /**\n * data getter for line Y coordinates\n */\n getY: PropTypes.any,\n /**\n * inline style object to be applied to the line path\n */\n lineStyle: PropTypes.object,\n /**\n * d3 scale - provided by XYPlot\n */\n scale: PropTypes.object\n };\n static defaultProps = {\n lineStyle: {}\n };\n\n componentWillMount() {\n this.initBisector(this.props);\n }\n componentWillReceiveProps(nextProps) {\n this.initBisector(nextProps);\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n return !xyPropsEqual(this.props, nextProps);\n }\n\n initBisector(props) {\n this.setState({bisectX: bisector(d => makeAccessor(props.getX)(d)).left});\n }\n\n getHovered = (x, y) => {\n const closestDataIndex = this.state.bisectX(this.props.data, x);\n return this.props.data[closestDataIndex];\n };\n\n render() {\n const {data, scale, getX, getY, lineStyle} = this.props;\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY)};\n const points = _.map(data, d => [scale.x(accessors.x(d)), scale.y(accessors.y(d))]);\n const pathStr = pointsToPathStr(points);\n\n return \n \n ;\n }\n}\n\nfunction pointsToPathStr(points) {\n // takes array of points in [[x, y], [x, y]... ] format\n // returns SVG path string in \"M X Y L X Y\" format\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands\n return _.map(points, ([x, y], i) => {\n const command = (i === 0) ? 'M' : 'L';\n return `${command} ${x} ${y}`;\n }).join(' ');\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/LineChart.js"],"names":["LineChart","getHovered","x","y","closestDataIndex","state","bisectX","props","data","initBisector","nextProps","nextState","setState","getX","d","left","scale","getY","lineStyle","accessors","points","map","pathStr","pointsToPathStr","name","Component","propTypes","array","isRequired","any","object","defaultProps","i","command","join"],"mappings":";;;;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;AACA;;;;AAEA;;AACA;;;;;;;;;;;;AACA;;;IAGqBA,S;;;;;;;;;;;;;;4LA0CnBC,U,GAAa,UAACC,CAAD,EAAIC,CAAJ,EAAU;AACrB,UAAMC,mBAAmB,MAAKC,KAAL,CAAWC,OAAX,CAAmB,MAAKC,KAAL,CAAWC,IAA9B,EAAoCN,CAApC,CAAzB;AACA,aAAO,MAAKK,KAAL,CAAWC,IAAX,CAAgBJ,gBAAhB,CAAP;AACD,K;;;;;yCAlBoB;AACnB,WAAKK,YAAL,CAAkB,KAAKF,KAAvB;AACD;;;8CACyBG,S,EAAW;AACnC,WAAKD,YAAL,CAAkBC,SAAlB;AACD;;;0CAEqBA,S,EAAWC,S,EAAW;AAC1C,aAAO,CAAC,4BAAa,KAAKJ,KAAlB,EAAyBG,SAAzB,EAAoC,CAAC,WAAD,CAApC,CAAR;AACD;;;iCAEYH,K,EAAO;AAClB,WAAKK,QAAL,CAAc,EAACN,SAAS,iBAAS;AAAA,iBAAK,wBAAaC,MAAMM,IAAnB,EAAyBC,CAAzB,CAAL;AAAA,SAAT,EAA2CC,IAArD,EAAd;AACD;;;6BAOQ;AAAA,mBACsC,KAAKR,KAD3C;AAAA,UACAC,IADA,UACAA,IADA;AAAA,UACMQ,KADN,UACMA,KADN;AAAA,UACaH,IADb,UACaA,IADb;AAAA,UACmBI,IADnB,UACmBA,IADnB;AAAA,UACyBC,SADzB,UACyBA,SADzB;;AAEP,UAAMC,YAAY,EAACjB,GAAG,wBAAaW,IAAb,CAAJ,EAAwBV,GAAG,wBAAac,IAAb,CAA3B,EAAlB;AACA,UAAMG,SAAS,iBAAEC,GAAF,CAAMb,IAAN,EAAY;AAAA,eAAK,CAACQ,MAAMd,CAAN,CAAQiB,UAAUjB,CAAV,CAAYY,CAAZ,CAAR,CAAD,EAA0BE,MAAMb,CAAN,CAAQgB,UAAUhB,CAAV,CAAYW,CAAZ,CAAR,CAA1B,CAAL;AAAA,OAAZ,CAAf;AACA,UAAMQ,UAAUC,gBAAgBH,MAAhB,CAAhB;;AAEA,aAAO;AAAA;AAAA,UAAG,WAAW,KAAKb,KAAL,CAAWiB,IAAzB;AACL,gDAAM,GAAGF,OAAT,EAAkB,OAAOJ,SAAzB;AADK,OAAP;AAGD;;;;EAxDoC,gBAAMO,S;;AAAxBzB,S,CACZ0B,S,GAAY;AACjB;;;AAGAlB,QAAM,oBAAUmB,KAAV,CAAgBC,UAJL;AAKjB;;;AAGAf,QAAM,oBAAUgB,GARC;AASjB;;;AAGAZ,QAAM,oBAAUY,GAZC;AAajB;;;AAGAX,aAAW,oBAAUY,MAhBJ;AAiBjB;;;AAGAd,SAAO,oBAAUc;AApBA,C;AADA9B,S,CAuBZ+B,Y,GAAe;AACpBb,aAAW;AADS,C;kBAvBHlB,S;;;AA2DrB,SAASuB,eAAT,CAAyBH,MAAzB,EAAiC;AAC/B;AACA;AACA;AACA,SAAO,iBAAEC,GAAF,CAAMD,MAAN,EAAc,iBAASY,CAAT,EAAe;AAAA;AAAA,QAAb9B,CAAa;AAAA,QAAVC,CAAU;;AAClC,QAAM8B,UAAWD,MAAM,CAAP,GAAY,GAAZ,GAAkB,GAAlC;AACA,WAAUC,OAAV,SAAqB/B,CAArB,SAA0BC,CAA1B;AACD,GAHM,EAGJ+B,IAHI,CAGC,GAHD,CAAP;AAID","file":"LineChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport {bisector} from 'd3';\nimport shallowEqual from './utils/shallowEqual';\nimport PropTypes from 'prop-types';\n\nimport {makeAccessor} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\n// import {xyPropsEqualDebug as xyPropsEqual} from './utils/xyPropsEqual';\n\n\nexport default class LineChart extends React.Component {\n static propTypes = {\n /**\n * the array of data objects\n */\n data: PropTypes.array.isRequired,\n /**\n * data getter for line X coordinates\n */\n getX: PropTypes.any,\n /**\n * data getter for line Y coordinates\n */\n getY: PropTypes.any,\n /**\n * inline style object to be applied to the line path\n */\n lineStyle: PropTypes.object,\n /**\n * d3 scale - provided by XYPlot\n */\n scale: PropTypes.object\n };\n static defaultProps = {\n lineStyle: {}\n };\n\n componentWillMount() {\n this.initBisector(this.props);\n }\n componentWillReceiveProps(nextProps) {\n this.initBisector(nextProps);\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n return !xyPropsEqual(this.props, nextProps, ['lineStyle']);\n }\n\n initBisector(props) {\n this.setState({bisectX: bisector(d => makeAccessor(props.getX)(d)).left});\n }\n\n getHovered = (x, y) => {\n const closestDataIndex = this.state.bisectX(this.props.data, x);\n return this.props.data[closestDataIndex];\n };\n\n render() {\n const {data, scale, getX, getY, lineStyle} = this.props;\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY)};\n const points = _.map(data, d => [scale.x(accessors.x(d)), scale.y(accessors.y(d))]);\n const pathStr = pointsToPathStr(points);\n\n return \n \n ;\n }\n}\n\nfunction pointsToPathStr(points) {\n // takes array of points in [[x, y], [x, y]... ] format\n // returns SVG path string in \"M X Y L X Y\" format\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Line_commands\n return _.map(points, ([x, y], i) => {\n const command = (i === 0) ? 'M' : 'L';\n return `${command} ${x} ${y}`;\n }).join(' ');\n}\n"]} \ No newline at end of file diff --git a/lib/MarkerLineChart.js b/lib/MarkerLineChart.js index db98f84e..891399d4 100644 --- a/lib/MarkerLineChart.js +++ b/lib/MarkerLineChart.js @@ -32,6 +32,10 @@ var _Scale = require('./utils/Scale'); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + 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; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -149,6 +153,12 @@ var MarkerLineChart = function (_React$Component) { } _createClass(MarkerLineChart, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, []); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var tickType = getTickType(this.props); diff --git a/lib/MarkerLineChart.js.map b/lib/MarkerLineChart.js.map index a7b5065e..035f6199 100644 --- a/lib/MarkerLineChart.js.map +++ b/lib/MarkerLineChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/MarkerLineChart.js"],"names":["CustomPropTypes","getTickType","props","getXEnd","getYEnd","horizontal","isUndefined","console","warn","MarkerLineChart","onMouseEnterLine","e","d","onMouseMoveLine","onMouseLeaveLine","renderRangeValueLine","i","map","callback","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","getX","getY","scale","xVal","x","yVal","y","xEndVal","yEndVal","x1","y1","x2","y2","key","every","isFinite","renderValueValueLine","lineLength","tickType","data","top","right","bottom","left","domain","dataDomain","P","k","first","last","sortBy","domainHead","domainTail","dataDomainHead","dataDomainTail","clamp","spacingTail","spacingHead","scaleType","rangeAxis","rangeStartAccessor","rangeEndAccessor","rangeDataType","Component","propTypes","array","isRequired","getter","bool","number","object","func","defaultProps"],"mappings":"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","file":"MarkerLineChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\n\nimport {methodIfFuncProp} from './util.js';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {dataTypeFromScaleType} from './utils/Scale';\nimport {makeAccessor, domainFromRangeData, getDataDomainByAxis} from './utils/Data';\n\n/**\n * MarkerLine is similar to a bar chart,\n * except that it just draws a line at the data value, rather than a full bar.\n * If the independent variable is a range, the length of the line will represent that range,\n * otherwise all lines will be the same length.\n * The dependent variable must be a single value, not a range.\n */\n\nfunction getTickType(props) {\n const {getXEnd, getYEnd, horizontal} = props;\n // warn if a range is passed for the dependent variable, which is expected to be a value\n if((!horizontal && !_.isUndefined(getYEnd)) || (horizontal && !_.isUndefined(getXEnd)))\n console.warn(\"Warning: MarkerLineChart can only show the independent variable as a range, not the dependent variable.\");\n\n if((!horizontal && !_.isUndefined(getXEnd)) || (horizontal && !_.isUndefined(getYEnd)))\n return \"RangeValue\";\n\n return \"ValueValue\";\n}\n\n\nexport default class MarkerLineChart extends React.Component {\n static propTypes = {\n // the array of data objects\n data: PropTypes.array.isRequired,\n // accessor for X & Y coordinates\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n\n horizontal: PropTypes.bool,\n lineLength: PropTypes.number,\n\n // x & y scale types\n scaleType: PropTypes.object,\n scale: PropTypes.object,\n\n onMouseEnterLine: PropTypes.func,\n onMouseMoveLine: PropTypes.func,\n onMouseLeaveLine: PropTypes.func\n };\n static defaultProps = {\n horizontal: false,\n lineLength: 10\n };\n\n // todo reimplement padding/spacing\n /*\n static getOptions(props) {\n const {data, getX, getXEnd, getY, getYEnd, scaleType, orientation, lineLength} = props;\n const tickType = getTickType(props);\n const isVertical = (orientation === 'vertical');\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY)};\n const endAccessors = {x: makeAccessor(getXEnd), y: makeAccessor(getYEnd)};\n\n let options = {domain: {}, spacing: {}};\n\n if(tickType === 'RangeValue') { // set range domain for range type\n let rangeAxis = isVertical ? 'x' : 'y';\n options.domain[rangeAxis] =\n rangeAxisDomain(data, accessors[rangeAxis], endAccessors[rangeAxis], scaleType[rangeAxis]);\n } else {\n // the value, and therefore the center of the marker line, may fall exactly on the axis min or max,\n // therefore marker lines need (0.5*lineLength) spacing so they don't hang over the edge of the chart\n const halfLine = Math.ceil(0.5 * lineLength);\n options.spacing = isVertical ? {left: halfLine, right: halfLine} : {top: halfLine, bottom: halfLine};\n }\n\n return options;\n }\n */\n\n static getSpacing(props) {\n const tickType = getTickType(props);\n if(tickType === 'RangeValue') return {top: 0, right: 0, bottom: 0, left: 0}; //no spacing for rangeValue marker charts since line start and end are set explicitly\n const {lineLength, horizontal, scale, data, domain} = props;\n const dataDomain = getDataDomainByAxis(props);\n const P = lineLength / 2; //padding\n const k = horizontal ? 'y' : 'x';\n //find the edges of the tick domain, and map them through the scale function\n const [domainHead, domainTail] = _([_.first(domain[k]), _.last(domain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the edges of the data domain, and map them through the scale function\n const [dataDomainHead, dataDomainTail] = _([_.first(dataDomain[k]), _.last(dataDomain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the neccessary spacing (based on bar width) to push the bars completely inside the tick domain\n const [spacingTail, spacingHead] = [_.clamp(P - (domainTail - dataDomainTail), 0, P), _.clamp(P - (dataDomainHead - domainHead), 0, P)];\n if(horizontal){\n return {top: spacingHead, right: 0, bottom: spacingTail, left: 0}\n } else {\n return {top: 0, right: spacingTail, bottom: 0, left: spacingHead}\n }\n }\n\n static getDomain(props) {\n if(getTickType(props) === 'RangeValue') { // set range domain for range type\n const {data, getX, getXEnd, getY, getYEnd, scaleType, horizontal} = props;\n\n // only have to specify range axis domain, other axis uses default domainFromData\n // in this chart type, the range axis, if there is one, is always the *independent* variable\n const rangeAxis = horizontal ? 'y' : 'x';\n const rangeStartAccessor = horizontal ? makeAccessor(getY) : makeAccessor(getX);\n const rangeEndAccessor = horizontal ? makeAccessor(getYEnd) : makeAccessor(getXEnd);\n const rangeDataType = dataTypeFromScaleType(scaleType[rangeAxis]);\n\n return {\n [rangeAxis]: domainFromRangeData(data, rangeStartAccessor, rangeEndAccessor, rangeDataType)\n };\n }\n }\n\n onMouseEnterLine = (e, d) => {\n this.props.onMouseEnterLine(e, d);\n };\n onMouseMoveLine = (e, d) => {\n this.props.onMouseMoveLine(e, d);\n };\n onMouseLeaveLine = (e, d) => {\n this.props.onMouseLeaveLine(e, d);\n };\n\n render() {\n const tickType = getTickType(this.props);\n return \n {tickType === 'RangeValue' ?\n this.props.data.map(this.renderRangeValueLine) :\n this.props.data.map(this.renderValueValueLine)\n }\n \n }\n\n renderRangeValueLine = (d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterLine', 'onMouseMoveLine', 'onMouseLeaveLine'].map(eventName => {\n // partially apply this bar's data point as 2nd callback argument\n const callback = methodIfFuncProp(eventName, this.props, this);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n const {getX, getXEnd, getY, getYEnd, horizontal, scale} = this.props;\n const xVal = scale.x(makeAccessor(getX)(d));\n const yVal = scale.y(makeAccessor(getY)(d));\n const xEndVal = _.isUndefined(getXEnd) ? 0 : scale.x(makeAccessor(getXEnd)(d));\n const yEndVal = _.isUndefined(getYEnd) ? 0 : scale.y(makeAccessor(getYEnd)(d));\n const [x1, y1] = [xVal, yVal];\n const x2 = horizontal ? xVal : xEndVal;\n const y2 = horizontal ? yEndVal : yVal;\n const key = `marker-line-${i}`;\n\n if(!_.every([x1, x2, y1, y2], _.isFinite)) return null;\n return \n };\n\n renderValueValueLine = (d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterLine', 'onMouseMoveLine', 'onMouseLeaveLine'].map(eventName => {\n // partially apply this bar's data point as 2nd callback argument\n const callback = methodIfFuncProp(eventName, this.props, this);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n const {getX, getY, horizontal, lineLength, scale} = this.props;\n const xVal = scale.x(makeAccessor(getX)(d));\n const yVal = scale.y(makeAccessor(getY)(d));\n const x1 = (!horizontal) ? xVal - (lineLength / 2) : xVal;\n const x2 = (!horizontal) ? xVal + (lineLength / 2) : xVal;\n const y1 = (!horizontal) ? yVal : yVal - (lineLength / 2);\n const y2 = (!horizontal) ? yVal : yVal + (lineLength / 2);\n const key = `marker-line-${i}`;\n\n if(!_.every([x1, x2, y1, y2], _.isFinite)) return null;\n return ;\n };\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/MarkerLineChart.js"],"names":["CustomPropTypes","getTickType","props","getXEnd","getYEnd","horizontal","isUndefined","console","warn","MarkerLineChart","onMouseEnterLine","e","d","onMouseMoveLine","onMouseLeaveLine","renderRangeValueLine","i","map","callback","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","getX","getY","scale","xVal","x","yVal","y","xEndVal","yEndVal","x1","y1","x2","y2","key","every","isFinite","renderValueValueLine","lineLength","nextProps","nextState","shouldUpdate","tickType","data","top","right","bottom","left","domain","dataDomain","P","k","first","last","sortBy","domainHead","domainTail","dataDomainHead","dataDomainTail","clamp","spacingTail","spacingHead","scaleType","rangeAxis","rangeStartAccessor","rangeEndAccessor","rangeDataType","Component","propTypes","array","isRequired","getter","bool","number","object","func","defaultProps"],"mappings":"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","file":"MarkerLineChart.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\n\nimport {methodIfFuncProp} from './util.js';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {dataTypeFromScaleType} from './utils/Scale';\nimport {makeAccessor, domainFromRangeData, getDataDomainByAxis} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\n\n/**\n * MarkerLine is similar to a bar chart,\n * except that it just draws a line at the data value, rather than a full bar.\n * If the independent variable is a range, the length of the line will represent that range,\n * otherwise all lines will be the same length.\n * The dependent variable must be a single value, not a range.\n */\n\nfunction getTickType(props) {\n const {getXEnd, getYEnd, horizontal} = props;\n // warn if a range is passed for the dependent variable, which is expected to be a value\n if((!horizontal && !_.isUndefined(getYEnd)) || (horizontal && !_.isUndefined(getXEnd)))\n console.warn(\"Warning: MarkerLineChart can only show the independent variable as a range, not the dependent variable.\");\n\n if((!horizontal && !_.isUndefined(getXEnd)) || (horizontal && !_.isUndefined(getYEnd)))\n return \"RangeValue\";\n\n return \"ValueValue\";\n}\n\n\nexport default class MarkerLineChart extends React.Component {\n static propTypes = {\n // the array of data objects\n data: PropTypes.array.isRequired,\n // accessor for X & Y coordinates\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n\n horizontal: PropTypes.bool,\n lineLength: PropTypes.number,\n\n // x & y scale types\n scaleType: PropTypes.object,\n scale: PropTypes.object,\n\n onMouseEnterLine: PropTypes.func,\n onMouseMoveLine: PropTypes.func,\n onMouseLeaveLine: PropTypes.func\n };\n static defaultProps = {\n horizontal: false,\n lineLength: 10\n };\n\n // todo reimplement padding/spacing\n /*\n static getOptions(props) {\n const {data, getX, getXEnd, getY, getYEnd, scaleType, orientation, lineLength} = props;\n const tickType = getTickType(props);\n const isVertical = (orientation === 'vertical');\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY)};\n const endAccessors = {x: makeAccessor(getXEnd), y: makeAccessor(getYEnd)};\n\n let options = {domain: {}, spacing: {}};\n\n if(tickType === 'RangeValue') { // set range domain for range type\n let rangeAxis = isVertical ? 'x' : 'y';\n options.domain[rangeAxis] =\n rangeAxisDomain(data, accessors[rangeAxis], endAccessors[rangeAxis], scaleType[rangeAxis]);\n } else {\n // the value, and therefore the center of the marker line, may fall exactly on the axis min or max,\n // therefore marker lines need (0.5*lineLength) spacing so they don't hang over the edge of the chart\n const halfLine = Math.ceil(0.5 * lineLength);\n options.spacing = isVertical ? {left: halfLine, right: halfLine} : {top: halfLine, bottom: halfLine};\n }\n\n return options;\n }\n */\n\n static getSpacing(props) {\n const tickType = getTickType(props);\n if(tickType === 'RangeValue') return {top: 0, right: 0, bottom: 0, left: 0}; //no spacing for rangeValue marker charts since line start and end are set explicitly\n const {lineLength, horizontal, scale, data, domain} = props;\n const dataDomain = getDataDomainByAxis(props);\n const P = lineLength / 2; //padding\n const k = horizontal ? 'y' : 'x';\n //find the edges of the tick domain, and map them through the scale function\n const [domainHead, domainTail] = _([_.first(domain[k]), _.last(domain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the edges of the data domain, and map them through the scale function\n const [dataDomainHead, dataDomainTail] = _([_.first(dataDomain[k]), _.last(dataDomain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the neccessary spacing (based on bar width) to push the bars completely inside the tick domain\n const [spacingTail, spacingHead] = [_.clamp(P - (domainTail - dataDomainTail), 0, P), _.clamp(P - (dataDomainHead - domainHead), 0, P)];\n if(horizontal){\n return {top: spacingHead, right: 0, bottom: spacingTail, left: 0}\n } else {\n return {top: 0, right: spacingTail, bottom: 0, left: spacingHead}\n }\n }\n\n static getDomain(props) {\n if(getTickType(props) === 'RangeValue') { // set range domain for range type\n const {data, getX, getXEnd, getY, getYEnd, scaleType, horizontal} = props;\n\n // only have to specify range axis domain, other axis uses default domainFromData\n // in this chart type, the range axis, if there is one, is always the *independent* variable\n const rangeAxis = horizontal ? 'y' : 'x';\n const rangeStartAccessor = horizontal ? makeAccessor(getY) : makeAccessor(getX);\n const rangeEndAccessor = horizontal ? makeAccessor(getYEnd) : makeAccessor(getXEnd);\n const rangeDataType = dataTypeFromScaleType(scaleType[rangeAxis]);\n\n return {\n [rangeAxis]: domainFromRangeData(data, rangeStartAccessor, rangeEndAccessor, rangeDataType)\n };\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, []);\n return shouldUpdate;\n }\n\n onMouseEnterLine = (e, d) => {\n this.props.onMouseEnterLine(e, d);\n };\n onMouseMoveLine = (e, d) => {\n this.props.onMouseMoveLine(e, d);\n };\n onMouseLeaveLine = (e, d) => {\n this.props.onMouseLeaveLine(e, d);\n };\n\n render() {\n const tickType = getTickType(this.props);\n return \n {tickType === 'RangeValue' ?\n this.props.data.map(this.renderRangeValueLine) :\n this.props.data.map(this.renderValueValueLine)\n }\n \n }\n\n renderRangeValueLine = (d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterLine', 'onMouseMoveLine', 'onMouseLeaveLine'].map(eventName => {\n // partially apply this bar's data point as 2nd callback argument\n const callback = methodIfFuncProp(eventName, this.props, this);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n const {getX, getXEnd, getY, getYEnd, horizontal, scale} = this.props;\n const xVal = scale.x(makeAccessor(getX)(d));\n const yVal = scale.y(makeAccessor(getY)(d));\n const xEndVal = _.isUndefined(getXEnd) ? 0 : scale.x(makeAccessor(getXEnd)(d));\n const yEndVal = _.isUndefined(getYEnd) ? 0 : scale.y(makeAccessor(getYEnd)(d));\n const [x1, y1] = [xVal, yVal];\n const x2 = horizontal ? xVal : xEndVal;\n const y2 = horizontal ? yEndVal : yVal;\n const key = `marker-line-${i}`;\n\n if(!_.every([x1, x2, y1, y2], _.isFinite)) return null;\n return \n };\n\n renderValueValueLine = (d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterLine', 'onMouseMoveLine', 'onMouseLeaveLine'].map(eventName => {\n // partially apply this bar's data point as 2nd callback argument\n const callback = methodIfFuncProp(eventName, this.props, this);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n const {getX, getY, horizontal, lineLength, scale} = this.props;\n const xVal = scale.x(makeAccessor(getX)(d));\n const yVal = scale.y(makeAccessor(getY)(d));\n const x1 = (!horizontal) ? xVal - (lineLength / 2) : xVal;\n const x2 = (!horizontal) ? xVal + (lineLength / 2) : xVal;\n const y1 = (!horizontal) ? yVal : yVal - (lineLength / 2);\n const y2 = (!horizontal) ? yVal : yVal + (lineLength / 2);\n const key = `marker-line-${i}`;\n\n if(!_.every([x1, x2, y1, y2], _.isFinite)) return null;\n return ;\n };\n}\n"]} \ No newline at end of file diff --git a/lib/RangeBarChart.js b/lib/RangeBarChart.js index 4d6a0e63..de959e6c 100644 --- a/lib/RangeBarChart.js +++ b/lib/RangeBarChart.js @@ -30,6 +30,10 @@ var _Scale = require('./utils/Scale'); var _Data = require('./utils/Data'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _Bar = require('./Bar'); var _Bar2 = _interopRequireDefault(_Bar); @@ -56,6 +60,12 @@ var RangeBarChart = function (_React$Component) { } _createClass(RangeBarChart, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['barStyle']); + return shouldUpdate; + } + }, { key: 'render', value: function render() { var _this2 = this; diff --git a/lib/RangeBarChart.js.map b/lib/RangeBarChart.js.map index e9824476..9e93d7c4 100644 --- a/lib/RangeBarChart.js.map +++ b/lib/RangeBarChart.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/RangeBarChart.js"],"names":["CustomPropTypes","RangeBarChart","props","scale","data","horizontal","getX","getXEnd","getY","getYEnd","barThickness","barClassName","barStyle","getClass","accessors","x","y","endAccessors","map","d","i","callback","_","get","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","barProps","thickness","className","style","thisBarProps","xValue","yValue","key","scaleType","rangeAxis","rangeStartAccessor","rangeEndAccessor","rangeDataType","domain","dataDomain","P","k","first","last","sortBy","domainHead","domainTail","dataDomainHead","dataDomainTail","clamp","spacingTail","spacingHead","top","right","bottom","left","Component","propTypes","xyObjectOf","func","isRequired","array","bool","getter","number","string","object","onMouseEnterBar","onMouseMoveBar","onMouseLeaveBar","defaultProps"],"mappings":"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","file":"RangeBarChart.js","sourcesContent":["import React from 'react';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {hasXYScales, dataTypeFromScaleType} from './utils/Scale';\nimport {makeAccessor, domainFromRangeData, domainFromData, getDataDomainByAxis} from './utils/Data';\nimport Bar from './Bar';\n\nexport default class RangeBarChart extends React.Component {\n static propTypes = {\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n data: PropTypes.array,\n horizontal: PropTypes.bool,\n\n getX: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n\n barThickness: PropTypes.number,\n barClassName: PropTypes.string,\n barStyle: PropTypes.object,\n getClass: CustomPropTypes.getter,\n\n onMouseEnterBar: PropTypes.func,\n onMouseMoveBar: PropTypes.func,\n onMouseLeaveBar: PropTypes.func\n };\n static defaultProps = {\n data: [],\n horizontal: false,\n barThickness: 8,\n barClassName: '',\n barStyle: {}\n };\n\n static getDomain(props) {\n const {scaleType, horizontal, data, getX, getXEnd, getY, getYEnd} = props;\n\n // only have to specify range axis domain, other axis uses default domainFromData\n const rangeAxis = horizontal ? 'x' : 'y';\n const rangeStartAccessor = horizontal ? makeAccessor(getX) : makeAccessor(getY);\n const rangeEndAccessor = horizontal ? makeAccessor(getXEnd) : makeAccessor(getYEnd);\n const rangeDataType = dataTypeFromScaleType(scaleType[rangeAxis]);\n\n return {\n [rangeAxis]: domainFromRangeData(data, rangeStartAccessor, rangeEndAccessor, rangeDataType)\n };\n }\n static getSpacing(props) {\n const {barThickness, horizontal, scale, data, domain} = props;\n const dataDomain = getDataDomainByAxis(props);\n const P = barThickness / 2; //padding\n const k = horizontal ? 'y' : 'x';\n //find the edges of the tick domain, and map them through the scale function\n const [domainHead, domainTail] = _([_.first(domain[k]), _.last(domain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the edges of the data domain, and map them through the scale function\n const [dataDomainHead, dataDomainTail] = _([_.first(dataDomain[k]), _.last(dataDomain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the neccessary spacing (based on bar width) to push the bars completely inside the tick domain\n const [spacingTail, spacingHead] = [_.clamp(P - (domainTail - dataDomainTail), 0, P), _.clamp(P - (dataDomainHead - domainHead), 0, P)];\n if(horizontal){\n return {top: spacingHead, right: 0, bottom: spacingTail, left: 0}\n } else {\n return {top: 0, right: spacingTail, bottom: 0, left: spacingHead}\n }\n }\n render() {\n const {scale, data, horizontal, getX, getXEnd, getY, getYEnd, barThickness, barClassName, barStyle, getClass} = this.props;\n invariant(hasXYScales(scale), `RangeBarChart.props.scale.x and scale.y must both be valid d3 scales`);\n // invariant(hasOneOfTwo(getXEnd, getYEnd), `RangeBarChart expects a getXEnd *or* getYEnd prop, but not both.`);\n\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY)};\n const endAccessors = {x: makeAccessor(getXEnd), y: makeAccessor(getYEnd)};\n \n\n\n return \n {data.map((d, i) => {\n\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterBar', 'onMouseMoveBar', 'onMouseLeaveBar'].map(eventName => {\n\n // partially apply this bar's data point as 2nd callback argument\n const callback = _.get(this.props, eventName);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n const barProps = {\n scale,\n thickness: barThickness,\n className: `chart-bar ${barClassName} ${getClass ? getClass(d) : ''}`,\n style: barStyle\n };\n\n const thisBarProps = {\n xValue: accessors.x(d),\n yValue: accessors.y(d),\n key: `chart-bar-${i}`,\n onMouseEnter, \n onMouseMove, \n onMouseLeave,\n ...barProps\n };\n\n return horizontal ?\n :\n ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/RangeBarChart.js"],"names":["CustomPropTypes","RangeBarChart","nextProps","nextState","shouldUpdate","props","scale","data","horizontal","getX","getXEnd","getY","getYEnd","barThickness","barClassName","barStyle","getClass","accessors","x","y","endAccessors","map","d","i","callback","_","get","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","barProps","thickness","className","style","thisBarProps","xValue","yValue","key","scaleType","rangeAxis","rangeStartAccessor","rangeEndAccessor","rangeDataType","domain","dataDomain","P","k","first","last","sortBy","domainHead","domainTail","dataDomainHead","dataDomainTail","clamp","spacingTail","spacingHead","top","right","bottom","left","Component","propTypes","xyObjectOf","func","isRequired","array","bool","getter","number","string","object","onMouseEnterBar","onMouseMoveBar","onMouseLeaveBar","defaultProps"],"mappings":"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","file":"RangeBarChart.js","sourcesContent":["import React from 'react';\nimport invariant from 'invariant';\nimport PropTypes from 'prop-types';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\nimport {hasXYScales, dataTypeFromScaleType} from './utils/Scale';\nimport {makeAccessor, domainFromRangeData, domainFromData, getDataDomainByAxis} from './utils/Data';\nimport xyPropsEqual from './utils/xyPropsEqual';\nimport Bar from './Bar';\n\nexport default class RangeBarChart extends React.Component {\n static propTypes = {\n scale: CustomPropTypes.xyObjectOf(PropTypes.func.isRequired),\n data: PropTypes.array,\n horizontal: PropTypes.bool,\n\n getX: CustomPropTypes.getter,\n getXEnd: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n getYEnd: CustomPropTypes.getter,\n\n barThickness: PropTypes.number,\n barClassName: PropTypes.string,\n barStyle: PropTypes.object,\n getClass: CustomPropTypes.getter,\n\n onMouseEnterBar: PropTypes.func,\n onMouseMoveBar: PropTypes.func,\n onMouseLeaveBar: PropTypes.func\n };\n static defaultProps = {\n data: [],\n horizontal: false,\n barThickness: 8,\n barClassName: '',\n barStyle: {}\n };\n\n static getDomain(props) {\n const {scaleType, horizontal, data, getX, getXEnd, getY, getYEnd} = props;\n\n // only have to specify range axis domain, other axis uses default domainFromData\n const rangeAxis = horizontal ? 'x' : 'y';\n const rangeStartAccessor = horizontal ? makeAccessor(getX) : makeAccessor(getY);\n const rangeEndAccessor = horizontal ? makeAccessor(getXEnd) : makeAccessor(getYEnd);\n const rangeDataType = dataTypeFromScaleType(scaleType[rangeAxis]);\n\n return {\n [rangeAxis]: domainFromRangeData(data, rangeStartAccessor, rangeEndAccessor, rangeDataType)\n };\n }\n static getSpacing(props) {\n const {barThickness, horizontal, scale, data, domain} = props;\n const dataDomain = getDataDomainByAxis(props);\n const P = barThickness / 2; //padding\n const k = horizontal ? 'y' : 'x';\n //find the edges of the tick domain, and map them through the scale function\n const [domainHead, domainTail] = _([_.first(domain[k]), _.last(domain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the edges of the data domain, and map them through the scale function\n const [dataDomainHead, dataDomainTail] = _([_.first(dataDomain[k]), _.last(dataDomain[k])]).map(scale[k]).sortBy(); //sort the pixel values return by the domain extents\n //find the neccessary spacing (based on bar width) to push the bars completely inside the tick domain\n const [spacingTail, spacingHead] = [_.clamp(P - (domainTail - dataDomainTail), 0, P), _.clamp(P - (dataDomainHead - domainHead), 0, P)];\n if(horizontal){\n return {top: spacingHead, right: 0, bottom: spacingTail, left: 0}\n } else {\n return {top: 0, right: spacingTail, bottom: 0, left: spacingHead}\n }\n }\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['barStyle']);\n return shouldUpdate;\n }\n\n render() {\n const {scale, data, horizontal, getX, getXEnd, getY, getYEnd, barThickness, barClassName, barStyle, getClass} = this.props;\n invariant(hasXYScales(scale), `RangeBarChart.props.scale.x and scale.y must both be valid d3 scales`);\n // invariant(hasOneOfTwo(getXEnd, getYEnd), `RangeBarChart expects a getXEnd *or* getYEnd prop, but not both.`);\n\n const accessors = {x: makeAccessor(getX), y: makeAccessor(getY)};\n const endAccessors = {x: makeAccessor(getXEnd), y: makeAccessor(getYEnd)};\n \n\n\n return \n {data.map((d, i) => {\n\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterBar', 'onMouseMoveBar', 'onMouseLeaveBar'].map(eventName => {\n\n // partially apply this bar's data point as 2nd callback argument\n const callback = _.get(this.props, eventName);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n\n const barProps = {\n scale,\n thickness: barThickness,\n className: `chart-bar ${barClassName} ${getClass ? getClass(d) : ''}`,\n style: barStyle\n };\n\n const thisBarProps = {\n xValue: accessors.x(d),\n yValue: accessors.y(d),\n key: `chart-bar-${i}`,\n onMouseEnter, \n onMouseMove, \n onMouseLeave,\n ...barProps\n };\n\n return horizontal ?\n :\n ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/ScatterPlot.js b/lib/ScatterPlot.js index 846eac0c..a3402ce0 100644 --- a/lib/ScatterPlot.js +++ b/lib/ScatterPlot.js @@ -26,6 +26,10 @@ var _Data = require('./utils/Data'); var _util = require('./util.js'); +var _xyPropsEqual = require('./utils/xyPropsEqual'); + +var _xyPropsEqual2 = _interopRequireDefault(_xyPropsEqual); + var _CustomPropTypes = require('./utils/CustomPropTypes'); var CustomPropTypes = _interopRequireWildcard(_CustomPropTypes); @@ -115,6 +119,12 @@ var ScatterPlot = function (_React$Component) { // todo: implement getSpacing or getPadding static _createClass(ScatterPlot, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps, nextState) { + var shouldUpdate = !(0, _xyPropsEqual2.default)(this.props, nextProps, ['pointStyle']); + return shouldUpdate; + } + }, { key: 'render', value: function render() { return _react2.default.createElement( diff --git a/lib/ScatterPlot.js.map b/lib/ScatterPlot.js.map index fe6779f1..570992c3 100644 --- a/lib/ScatterPlot.js.map +++ b/lib/ScatterPlot.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/ScatterPlot.js"],"names":["CustomPropTypes","ScatterPlot","onMouseEnterPoint","e","d","props","onMouseMovePoint","onMouseLeavePoint","renderPoint","i","map","callback","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","scale","getX","getY","pointRadius","pointOffset","pointStyle","getClass","pointSymbol","className","symbolProps","key","isString","isNumber","type","isUndefined","r","cx","x","cy","y","assign","style","textAnchor","dominantBaseline","transform","cloneElement","name","data","Component","propTypes","array","isRequired","getter","scaleType","object","number","oneOfType","node","func","arrayOf","defaultProps"],"mappings":"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","file":"ScatterPlot.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport _ from 'lodash';\n\nimport {makeAccessor} from './utils/Data';\nimport {methodIfFuncProp} from './util.js';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\n\nexport default class ScatterPlot extends React.Component {\n static propTypes = {\n // the array of data objects\n data: PropTypes.array.isRequired,\n // accessors for X & Y coordinates\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n // allow user to pass an accessor for setting the class of a point\n getClass: CustomPropTypes.getter,\n\n scaleType: PropTypes.object,\n scale: PropTypes.object,\n\n // used with the default point symbol (circle), defines the circle radius\n pointRadius: PropTypes.number,\n // text or SVG node to use as custom point symbol, or function which returns text/SVG\n pointSymbol: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),\n // manual x and y offset applied to the point to center it, for custom point symbols which can't be auto-centered\n pointOffset: PropTypes.arrayOf(PropTypes.number),\n // inline styles for points\n pointStyle: PropTypes.object,\n\n onMouseEnterPoint: PropTypes.func,\n onMouseMovePoint: PropTypes.func,\n onMouseLeavePoint: PropTypes.func\n };\n static defaultProps = {\n pointRadius: 3,\n pointSymbol: ,\n pointOffset: [0,0],\n pointStyle: {}\n };\n\n // todo: implement getSpacing or getPadding static\n\n onMouseEnterPoint = (e, d) => {\n this.props.onMouseEnterPoint(e, d);\n };\n onMouseMovePoint = (e, d) => {\n this.props.onMouseMovePoint(e, d);\n };\n onMouseLeavePoint = (e, d) => {\n this.props.onMouseLeavePoint(e, d);\n };\n\n render() {\n return \n {this.props.data.map(this.renderPoint)}\n \n }\n renderPoint = (d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterPoint', 'onMouseMovePoint', 'onMouseLeavePoint'].map(eventName => {\n // partially apply this bar's data point as 2nd callback argument\n const callback = methodIfFuncProp(eventName, this.props, this);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n const {scale, getX, getY, pointRadius, pointOffset, pointStyle, getClass} = this.props;\n let {pointSymbol} = this.props;\n const className = `chart-scatterplot-point ${getClass ? makeAccessor(getClass)(d) : ''}`;\n let symbolProps = {className, onMouseEnter, onMouseMove, onMouseLeave, key: `scatter-point-${i}`};\n\n // resolve symbol-generating functions into real symbols\n if(_.isFunction(pointSymbol)) pointSymbol = pointSymbol(d, i);\n // wrap string/number symbols in container\n if(_.isString(pointSymbol) || _.isNumber(pointSymbol)) pointSymbol = {pointSymbol};\n // use props.pointRadius for circle radius\n if(pointSymbol.type === 'circle' && _.isUndefined(pointSymbol.props.r)) symbolProps.r = pointRadius;\n\n // x,y coords of center of symbol\n const cx = scale.x(makeAccessor(getX)(d)) + pointOffset[0];\n const cy = scale.y(makeAccessor(getY)(d)) + pointOffset[1];\n\n // set positioning attributes based on symbol type\n if(pointSymbol.type === 'circle' || pointSymbol.type === 'ellipse') {\n _.assign(symbolProps, {cx, cy, style: pointStyle});\n } else if(pointSymbol.type === 'text') {\n _.assign(symbolProps, {x: cx, y: cy, style: {textAnchor: 'middle', dominantBaseline: 'central', ...pointStyle}});\n } else {\n _.assign(symbolProps, {x: cx, y: cy, style: {transform: \"translate(-50%, -50%)\", ...pointStyle}});\n }\n\n return React.cloneElement(pointSymbol, symbolProps);\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/ScatterPlot.js"],"names":["CustomPropTypes","ScatterPlot","onMouseEnterPoint","e","d","props","onMouseMovePoint","onMouseLeavePoint","renderPoint","i","map","callback","eventName","isFunction","partial","onMouseEnter","onMouseMove","onMouseLeave","scale","getX","getY","pointRadius","pointOffset","pointStyle","getClass","pointSymbol","className","symbolProps","key","isString","isNumber","type","isUndefined","r","cx","x","cy","y","assign","style","textAnchor","dominantBaseline","transform","cloneElement","nextProps","nextState","shouldUpdate","name","data","Component","propTypes","array","isRequired","getter","scaleType","object","number","oneOfType","node","func","arrayOf","defaultProps"],"mappings":"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","file":"ScatterPlot.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport _ from 'lodash';\n\nimport {makeAccessor} from './utils/Data';\nimport {methodIfFuncProp} from './util.js';\nimport xyPropsEqual from './utils/xyPropsEqual';\nimport * as CustomPropTypes from './utils/CustomPropTypes';\n\nexport default class ScatterPlot extends React.Component {\n static propTypes = {\n // the array of data objects\n data: PropTypes.array.isRequired,\n // accessors for X & Y coordinates\n getX: CustomPropTypes.getter,\n getY: CustomPropTypes.getter,\n // allow user to pass an accessor for setting the class of a point\n getClass: CustomPropTypes.getter,\n\n scaleType: PropTypes.object,\n scale: PropTypes.object,\n\n // used with the default point symbol (circle), defines the circle radius\n pointRadius: PropTypes.number,\n // text or SVG node to use as custom point symbol, or function which returns text/SVG\n pointSymbol: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),\n // manual x and y offset applied to the point to center it, for custom point symbols which can't be auto-centered\n pointOffset: PropTypes.arrayOf(PropTypes.number),\n // inline styles for points\n pointStyle: PropTypes.object,\n\n onMouseEnterPoint: PropTypes.func,\n onMouseMovePoint: PropTypes.func,\n onMouseLeavePoint: PropTypes.func\n };\n static defaultProps = {\n pointRadius: 3,\n pointSymbol: ,\n pointOffset: [0,0],\n pointStyle: {}\n };\n\n // todo: implement getSpacing or getPadding static\n\n onMouseEnterPoint = (e, d) => {\n this.props.onMouseEnterPoint(e, d);\n };\n onMouseMovePoint = (e, d) => {\n this.props.onMouseMovePoint(e, d);\n };\n onMouseLeavePoint = (e, d) => {\n this.props.onMouseLeavePoint(e, d);\n };\n\n shouldComponentUpdate(nextProps, nextState) {\n const shouldUpdate = !xyPropsEqual(this.props, nextProps, ['pointStyle']);\n return shouldUpdate;\n }\n\n render() {\n return \n {this.props.data.map(this.renderPoint)}\n \n }\n renderPoint = (d, i) => {\n const [onMouseEnter, onMouseMove, onMouseLeave] =\n ['onMouseEnterPoint', 'onMouseMovePoint', 'onMouseLeavePoint'].map(eventName => {\n // partially apply this bar's data point as 2nd callback argument\n const callback = methodIfFuncProp(eventName, this.props, this);\n return _.isFunction(callback) ? _.partial(callback, _, d) : null;\n });\n const {scale, getX, getY, pointRadius, pointOffset, pointStyle, getClass} = this.props;\n let {pointSymbol} = this.props;\n const className = `chart-scatterplot-point ${getClass ? makeAccessor(getClass)(d) : ''}`;\n let symbolProps = {className, onMouseEnter, onMouseMove, onMouseLeave, key: `scatter-point-${i}`};\n\n // resolve symbol-generating functions into real symbols\n if(_.isFunction(pointSymbol)) pointSymbol = pointSymbol(d, i);\n // wrap string/number symbols in container\n if(_.isString(pointSymbol) || _.isNumber(pointSymbol)) pointSymbol = {pointSymbol};\n // use props.pointRadius for circle radius\n if(pointSymbol.type === 'circle' && _.isUndefined(pointSymbol.props.r)) symbolProps.r = pointRadius;\n\n // x,y coords of center of symbol\n const cx = scale.x(makeAccessor(getX)(d)) + pointOffset[0];\n const cy = scale.y(makeAccessor(getY)(d)) + pointOffset[1];\n\n // set positioning attributes based on symbol type\n if(pointSymbol.type === 'circle' || pointSymbol.type === 'ellipse') {\n _.assign(symbolProps, {cx, cy, style: pointStyle});\n } else if(pointSymbol.type === 'text') {\n _.assign(symbolProps, {x: cx, y: cy, style: {textAnchor: 'middle', dominantBaseline: 'central', ...pointStyle}});\n } else {\n _.assign(symbolProps, {x: cx, y: cy, style: {transform: \"translate(-50%, -50%)\", ...pointStyle}});\n }\n\n return React.cloneElement(pointSymbol, symbolProps);\n }\n}\n"]} \ No newline at end of file diff --git a/lib/XTicks.js b/lib/XTicks.js index 31784b89..3cd5cac8 100644 --- a/lib/XTicks.js +++ b/lib/XTicks.js @@ -100,7 +100,11 @@ var XTicks = function (_React$Component) { }(_react2.default.Component); XTicks.propTypes = { - scale: _propTypes2.default.shape({ x: _propTypes2.default.func.isRequired }) + scale: _propTypes2.default.shape({ x: _propTypes2.default.func.isRequired }), + position: _propTypes2.default.oneOf(['bottom', 'top']), + placement: _propTypes2.default.oneOf(['above', 'below']), + tickLength: _propTypes2.default.number, + tickStyle: _propTypes2.default.object }; XTicks.defaultProps = { position: 'bottom', diff --git a/lib/XTicks.js.map b/lib/XTicks.js.map index 8a8f0e00..c880de50 100644 --- a/lib/XTicks.js.map +++ b/lib/XTicks.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/XTicks.js"],"names":["XTicks","props","height","tickCount","position","tickLength","tickStyle","tickClassName","spacing","scale","x","placement","ticks","className","transform","bottom","top","map","tick","i","x1","y2","x2","y1","style","key","get","defaults","defaultProps","zeroMargin","left","right","Component","propTypes","shape","func","isRequired","nice"],"mappings":"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","file":"XTicks.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\n\nimport {getScaleTicks, getTickDomain} from './utils/Scale';\n\nexport default class XTicks extends React.Component {\n static propTypes = {\n scale: PropTypes.shape({x: PropTypes.func.isRequired})\n };\n static defaultProps = {\n position: 'bottom',\n nice: true,\n tickLength: 5,\n tickStyle: {},\n spacing: {top: 0, bottom: 0, left: 0, right: 0}\n };\n\n static getTickDomain(props) {\n if(!_.get(props, 'scale.x')) return;\n props = _.defaults({}, props, XTicks.defaultProps);\n return {x: getTickDomain(props.scale.x, props)};\n }\n\n static getMargin(props) {\n const {tickLength, position} = _.defaults({}, props, XTicks.defaultProps);\n const placement = props.placement || ((position === 'top') ? 'above' : 'below');\n const zeroMargin = {top: 0, bottom: 0, left: 0, right: 0};\n\n if((position === 'bottom' && placement === 'above') || (position == 'top' && placement === 'below'))\n return zeroMargin;\n\n return _.defaults({[position]: tickLength || 0}, zeroMargin);\n }\n\n render() {\n const {height, tickCount, position, tickLength, tickStyle, tickClassName, spacing} = this.props;\n const scale = this.props.scale.x;\n const placement = this.props.placement || ((position === 'top') ? 'above' : 'below');\n const ticks = this.props.ticks || getScaleTicks(scale, null, tickCount);\n const className = `chart-tick chart-tick-x ${tickClassName || ''}`;\n const transform = (position === 'bottom') ?\n `translate(0, ${height + spacing.bottom})` : `translate(0, ${-spacing.top})`;\n\n return \n {ticks.map((tick, i) => {\n const x1 = scale(tick);\n const y2 = (placement === 'above') ? -tickLength : tickLength;\n\n return ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/XTicks.js"],"names":["XTicks","props","height","tickCount","position","tickLength","tickStyle","tickClassName","spacing","scale","x","placement","ticks","className","transform","bottom","top","map","tick","i","x1","y2","x2","y1","style","key","get","defaults","defaultProps","zeroMargin","left","right","Component","propTypes","shape","func","isRequired","oneOf","number","object","nice"],"mappings":"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","file":"XTicks.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\n\nimport {getScaleTicks, getTickDomain} from './utils/Scale';\n\nexport default class XTicks extends React.Component {\n static propTypes = {\n scale: PropTypes.shape({x: PropTypes.func.isRequired}),\n position: PropTypes.oneOf(['bottom', 'top']),\n placement: PropTypes.oneOf(['above', 'below']),\n tickLength: PropTypes.number,\n tickStyle: PropTypes.object\n };\n static defaultProps = {\n position: 'bottom',\n nice: true,\n tickLength: 5,\n tickStyle: {},\n spacing: {top: 0, bottom: 0, left: 0, right: 0}\n };\n\n static getTickDomain(props) {\n if(!_.get(props, 'scale.x')) return;\n props = _.defaults({}, props, XTicks.defaultProps);\n return {x: getTickDomain(props.scale.x, props)};\n }\n\n static getMargin(props) {\n const {tickLength, position} = _.defaults({}, props, XTicks.defaultProps);\n const placement = props.placement || ((position === 'top') ? 'above' : 'below');\n const zeroMargin = {top: 0, bottom: 0, left: 0, right: 0};\n\n if((position === 'bottom' && placement === 'above') || (position == 'top' && placement === 'below'))\n return zeroMargin;\n\n return _.defaults({[position]: tickLength || 0}, zeroMargin);\n }\n\n render() {\n const {height, tickCount, position, tickLength, tickStyle, tickClassName, spacing} = this.props;\n const scale = this.props.scale.x;\n const placement = this.props.placement || ((position === 'top') ? 'above' : 'below');\n const ticks = this.props.ticks || getScaleTicks(scale, null, tickCount);\n const className = `chart-tick chart-tick-x ${tickClassName || ''}`;\n const transform = (position === 'bottom') ?\n `translate(0, ${height + spacing.bottom})` : `translate(0, ${-spacing.top})`;\n\n return \n {ticks.map((tick, i) => {\n const x1 = scale(tick);\n const y2 = (placement === 'above') ? -tickLength : tickLength;\n\n return ;\n })}\n ;\n }\n}\n"]} \ No newline at end of file diff --git a/lib/XYPlot.js b/lib/XYPlot.js index 781b4bad..7fa21c06 100644 --- a/lib/XYPlot.js +++ b/lib/XYPlot.js @@ -181,7 +181,7 @@ XYPlot.defaultProps = { }; -var xyKeys = ['scaleType', 'domain', 'invertScale']; +var xyKeys = ['scaleType', 'domain', 'invertScale', 'nice']; var dirKeys = ['margin', 'padding', 'spacing']; var XYPlotResolved = _lodash2.default.flow([_resolveXYScales2.default, _lodash2.default.partial(_resolveObjectProps2.default, _lodash2.default, xyKeys, ['x', 'y']), _lodash2.default.partial(_resolveObjectProps2.default, _lodash2.default, dirKeys, ['top', 'bottom', 'left', 'right'])])(XYPlot); diff --git a/lib/XYPlot.js.map b/lib/XYPlot.js.map index 77b04b93..d8d96727 100644 --- a/lib/XYPlot.js.map +++ b/lib/XYPlot.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/XYPlot.js"],"names":["indexOfClosestNumberInList","number","list","reduce","closestI","current","i","Math","abs","invertPointScale","scale","rangeValue","rangePoints","domain","map","domainValue","nearestPointIndex","getMouseOptions","event","height","width","margin","chartBB","currentTarget","getBoundingClientRect","outerX","round","clientX","left","outerY","clientY","top","innerX","innerY","chartSize","scaleType","x","y","xValue","inRange","invert","yValue","XYPlot","onXYMouseEvent","callbackKey","callback","props","isFunction","options","onMouseMove","partial","onMouseDown","onMouseUp","onClick","onMouseEnter","onMouseLeave","spacing","panelSize","handlerNames","handlers","fromPairs","n","propsToPass","omit","className","Children","children","isNull","child","isUndefined","cloneElement","Component","propTypes","object","padding","nice","invertScale","func","defaultProps","xyKeys","dirKeys","XYPlotResolved","flow"],"mappings":"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","file":"XYPlot.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\n\nimport resolveObjectProps from './utils/resolveObjectProps';\nimport resolveXYScales from './utils/resolveXYScales';\nimport {innerSize} from './utils/Margin';\nimport {inferScaleType} from './utils/Scale';\nimport {methodIfFuncProp} from './util';\n\nfunction indexOfClosestNumberInList(number, list) {\n return list.reduce((closestI, current, i) => {\n return Math.abs(current - number) < Math.abs(list[closestI] - number) ? i : closestI;\n }, 0);\n}\n\nfunction invertPointScale(scale, rangeValue) {\n // shim until d3.scalePoint.invert() is implemented for real\n // given a value from the output range, returns the *nearest* corresponding value in the input domain\n const rangePoints = scale.domain().map(domainValue => scale(domainValue));\n const nearestPointIndex = indexOfClosestNumberInList(rangeValue, rangePoints);\n return scale.domain()[nearestPointIndex];\n}\n\nfunction getMouseOptions(event, {scale, height, width, margin}) {\n const chartBB = event.currentTarget.getBoundingClientRect();\n const outerX = Math.round(event.clientX - chartBB.left);\n const outerY = Math.round(event.clientY - chartBB.top);\n const innerX = (outerX - (margin.left || 0));\n const innerY = (outerY -(margin.top || 0));\n const chartSize = innerSize({width, height}, margin);\n const scaleType = {x: inferScaleType(scale.x), y: inferScaleType(scale.y)};\n\n const xValue = (!_.inRange(innerX, 0, chartSize.width /* + padding.left + padding.right */)) ? null :\n (scaleType.x === 'ordinal') ?\n invertPointScale(scale.x, innerX) :\n scale.x.invert(innerX);\n const yValue = (!_.inRange(innerY, 0, chartSize.height /* + padding.top + padding.bottom */)) ? null :\n (scaleType.y === 'ordinal') ?\n invertPointScale(scale.y, innerY) :\n scale.y.invert(innerY);\n\n return {event, outerX, outerY, innerX, innerY, xValue, yValue, scale, margin};\n}\n\nclass XYPlot extends React.Component {\n static propTypes = {\n width: PropTypes.number,\n height: PropTypes.number,\n scale: PropTypes.object,\n scaleType: PropTypes.object,\n domain: PropTypes.object,\n margin: PropTypes.object,\n spacing: PropTypes.object,\n // todo spacing & padding...\n padding: PropTypes.object,\n nice: PropTypes.object,\n invertScale: PropTypes.object,\n\n onMouseMove: PropTypes.func,\n onMouseEnter: PropTypes.func,\n onMouseLeave: PropTypes.func,\n onMouseDown: PropTypes.func,\n onMouseUp: PropTypes.func\n };\n\n static defaultProps = {\n width: 400,\n height: 250,\n // nice: {x: true, y: true},\n invertScale: {x: false, y: false},\n // emptyLabel: \"Unknown\",\n\n // these values are inferred from data if not provided, therefore empty defaults\n // scaleType: {},\n // domain: {},\n // margin: {},\n //spacing: {top: 0, bottom: 0, left: 0, right: 0}\n };\n\n onXYMouseEvent = (callbackKey, event) => {\n const callback = this.props[callbackKey];\n if(!_.isFunction(callback)) return;\n const options = getMouseOptions(event, this.props);\n callback(options);\n };\n onMouseMove = _.partial(this.onXYMouseEvent, 'onMouseMove');\n onMouseDown = _.partial(this.onXYMouseEvent, 'onMouseDown');\n onMouseUp = _.partial(this.onXYMouseEvent, 'onMouseUp');\n onClick = _.partial(this.onXYMouseEvent, 'onClick');\n onMouseEnter = (event) => this.props.onMouseEnter({event});\n onMouseLeave = (event) => this.props.onMouseLeave({event});\n\n render() {\n const {width, height, margin, spacing} = this.props;\n // subtract margin + spacing from width/height to obtain inner width/height of panel & chart area\n // panelSize is the area including chart + spacing but NOT margin\n // chartSize is smaller, chart *only*, not including margin or spacing\n const panelSize = innerSize({width, height}, margin);\n const chartSize = innerSize(panelSize, spacing);\n\n const handlerNames = ['onMouseMove', 'onMouseEnter', 'onMouseLeave', 'onMouseDown', 'onMouseUp', 'onClick'];\n const handlers = _.fromPairs(handlerNames.map(n => [n, methodIfFuncProp(n, this.props, this)]));\n\n const propsToPass = {\n ..._.omit(this.props, ['children']),\n ...chartSize\n };\n\n return \n \n \n \n {React.Children.map(this.props.children, child => {\n return (_.isNull(child) || _.isUndefined(child)) ? null :\n React.cloneElement(child, propsToPass);\n })}\n \n \n }\n}\n\nconst xyKeys = ['scaleType', 'domain', 'invertScale'];\nconst dirKeys = ['margin', 'padding', 'spacing'];\n\nconst XYPlotResolved = _.flow([\n resolveXYScales,\n _.partial(resolveObjectProps, _, xyKeys, ['x', 'y']),\n _.partial(resolveObjectProps, _, dirKeys, ['top', 'bottom', 'left', 'right'])\n])(XYPlot);\n\nexport default XYPlotResolved;\n"]} \ No newline at end of file +{"version":3,"sources":["../src/XYPlot.js"],"names":["indexOfClosestNumberInList","number","list","reduce","closestI","current","i","Math","abs","invertPointScale","scale","rangeValue","rangePoints","domain","map","domainValue","nearestPointIndex","getMouseOptions","event","height","width","margin","chartBB","currentTarget","getBoundingClientRect","outerX","round","clientX","left","outerY","clientY","top","innerX","innerY","chartSize","scaleType","x","y","xValue","inRange","invert","yValue","XYPlot","onXYMouseEvent","callbackKey","callback","props","isFunction","options","onMouseMove","partial","onMouseDown","onMouseUp","onClick","onMouseEnter","onMouseLeave","spacing","panelSize","handlerNames","handlers","fromPairs","n","propsToPass","omit","className","Children","children","isNull","child","isUndefined","cloneElement","Component","propTypes","object","padding","nice","invertScale","func","defaultProps","xyKeys","dirKeys","XYPlotResolved","flow"],"mappings":"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","file":"XYPlot.js","sourcesContent":["import React from 'react';\nimport _ from 'lodash';\nimport PropTypes from 'prop-types';\n\nimport resolveObjectProps from './utils/resolveObjectProps';\nimport resolveXYScales from './utils/resolveXYScales';\nimport {innerSize} from './utils/Margin';\nimport {inferScaleType} from './utils/Scale';\nimport {methodIfFuncProp} from './util';\n\nfunction indexOfClosestNumberInList(number, list) {\n return list.reduce((closestI, current, i) => {\n return Math.abs(current - number) < Math.abs(list[closestI] - number) ? i : closestI;\n }, 0);\n}\n\nfunction invertPointScale(scale, rangeValue) {\n // shim until d3.scalePoint.invert() is implemented for real\n // given a value from the output range, returns the *nearest* corresponding value in the input domain\n const rangePoints = scale.domain().map(domainValue => scale(domainValue));\n const nearestPointIndex = indexOfClosestNumberInList(rangeValue, rangePoints);\n return scale.domain()[nearestPointIndex];\n}\n\nfunction getMouseOptions(event, {scale, height, width, margin}) {\n const chartBB = event.currentTarget.getBoundingClientRect();\n const outerX = Math.round(event.clientX - chartBB.left);\n const outerY = Math.round(event.clientY - chartBB.top);\n const innerX = (outerX - (margin.left || 0));\n const innerY = (outerY -(margin.top || 0));\n const chartSize = innerSize({width, height}, margin);\n const scaleType = {x: inferScaleType(scale.x), y: inferScaleType(scale.y)};\n\n const xValue = (!_.inRange(innerX, 0, chartSize.width /* + padding.left + padding.right */)) ? null :\n (scaleType.x === 'ordinal') ?\n invertPointScale(scale.x, innerX) :\n scale.x.invert(innerX);\n const yValue = (!_.inRange(innerY, 0, chartSize.height /* + padding.top + padding.bottom */)) ? null :\n (scaleType.y === 'ordinal') ?\n invertPointScale(scale.y, innerY) :\n scale.y.invert(innerY);\n\n return {event, outerX, outerY, innerX, innerY, xValue, yValue, scale, margin};\n}\n\nclass XYPlot extends React.Component {\n static propTypes = {\n width: PropTypes.number,\n height: PropTypes.number,\n scale: PropTypes.object,\n scaleType: PropTypes.object,\n domain: PropTypes.object,\n margin: PropTypes.object,\n spacing: PropTypes.object,\n // todo spacing & padding...\n padding: PropTypes.object,\n nice: PropTypes.object,\n invertScale: PropTypes.object,\n\n onMouseMove: PropTypes.func,\n onMouseEnter: PropTypes.func,\n onMouseLeave: PropTypes.func,\n onMouseDown: PropTypes.func,\n onMouseUp: PropTypes.func\n };\n\n static defaultProps = {\n width: 400,\n height: 250,\n // nice: {x: true, y: true},\n invertScale: {x: false, y: false},\n // emptyLabel: \"Unknown\",\n\n // these values are inferred from data if not provided, therefore empty defaults\n // scaleType: {},\n // domain: {},\n // margin: {},\n //spacing: {top: 0, bottom: 0, left: 0, right: 0}\n };\n\n onXYMouseEvent = (callbackKey, event) => {\n const callback = this.props[callbackKey];\n if(!_.isFunction(callback)) return;\n const options = getMouseOptions(event, this.props);\n callback(options);\n };\n onMouseMove = _.partial(this.onXYMouseEvent, 'onMouseMove');\n onMouseDown = _.partial(this.onXYMouseEvent, 'onMouseDown');\n onMouseUp = _.partial(this.onXYMouseEvent, 'onMouseUp');\n onClick = _.partial(this.onXYMouseEvent, 'onClick');\n onMouseEnter = (event) => this.props.onMouseEnter({event});\n onMouseLeave = (event) => this.props.onMouseLeave({event});\n\n render() {\n const {width, height, margin, spacing} = this.props;\n // subtract margin + spacing from width/height to obtain inner width/height of panel & chart area\n // panelSize is the area including chart + spacing but NOT margin\n // chartSize is smaller, chart *only*, not including margin or spacing\n const panelSize = innerSize({width, height}, margin);\n const chartSize = innerSize(panelSize, spacing);\n\n const handlerNames = ['onMouseMove', 'onMouseEnter', 'onMouseLeave', 'onMouseDown', 'onMouseUp', 'onClick'];\n const handlers = _.fromPairs(handlerNames.map(n => [n, methodIfFuncProp(n, this.props, this)]));\n\n const propsToPass = {\n ..._.omit(this.props, ['children']),\n ...chartSize\n };\n\n return \n \n \n \n {React.Children.map(this.props.children, child => {\n return (_.isNull(child) || _.isUndefined(child)) ? null :\n React.cloneElement(child, propsToPass);\n })}\n \n \n }\n}\n\nconst xyKeys = ['scaleType', 'domain', 'invertScale', 'nice'];\nconst dirKeys = ['margin', 'padding', 'spacing'];\n\nconst XYPlotResolved = _.flow([\n resolveXYScales,\n _.partial(resolveObjectProps, _, xyKeys, ['x', 'y']),\n _.partial(resolveObjectProps, _, dirKeys, ['top', 'bottom', 'left', 'right'])\n])(XYPlot);\n\nexport default XYPlotResolved;\n"]} \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index e505bd39..aa4eb61f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); +exports.utils = exports.resolveXYScales = exports.resolveObjectProps = exports.YTicks = exports.YGrid = exports.YAxisTitle = exports.YAxisLabels = exports.YAxis = exports.XTicks = exports.XGrid = exports.XAxisTitle = exports.XAxisLabels = exports.XAxis = exports.YLine = exports.XLine = exports.RangeRect = exports.Bar = exports.FunnelChart = exports.KernelDensityEstimation = exports.Histogram = exports.AreaHeatmap = exports.ColorHeatmap = exports.AreaChart = exports.MarkerLineChart = exports.AreaBarChart = exports.RangeBarChart = exports.BarChart = exports.ScatterPlot = exports.LineChart = exports.XYPlot = exports.TreeMap = exports.PieChart = undefined; var _PieChart = require('./PieChart'); @@ -130,6 +131,15 @@ Object.defineProperty(exports, 'KernelDensityEstimation', { } }); +var _FunnelChart = require('./FunnelChart'); + +Object.defineProperty(exports, 'FunnelChart', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_FunnelChart).default; + } +}); + var _Bar = require('./Bar'); Object.defineProperty(exports, 'Bar', { @@ -274,5 +284,23 @@ Object.defineProperty(exports, 'resolveXYScales', { } }); +var _Data = require('./utils/Data'); + +var Data = _interopRequireWildcard(_Data); + +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; } } + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var utils = exports.utils = { Data: Data }; +// export {utils}; + + +// ### Utilities +// * Data +// * Scale +// * Axis +// * Label +// * Margin +// * depthEqual //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/index.js.map b/lib/index.js.map index 39601f6d..1a5e78f0 100644 --- a/lib/index.js.map +++ b/lib/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.js"],"names":["default"],"mappings":";;;;;;;;;;;6CACQA,O;;;;;;;;;4CACAA,O;;;;;;;;;2CAGAA,O;;;;;;;;;8CACAA,O;;;;;;;;;gDACAA,O;;;;;;;;;6CACAA,O;;;;;;;;;kDACAA,O;;;;;;;;;iDACAA,O;;;;;;;;;oDACAA,O;;;;;;;;;8CACAA,O;;;;;;;;;iDACAA,O;;;;;;;;;gDACAA,O;;;;;;;;;8CACAA,O;;;;;;;;;4DACAA,O;;;;;;;;;wCAGAA,O;;;;;;;;;8CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;0CAGAA,O;;;;;;;;;gDACAA,O;;;;;;;;;+CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;2CACAA,O;;;;;;;;;0CAEAA,O;;;;;;;;;gDACAA,O;;;;;;;;;+CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;2CACAA,O;;;;;;;;;uDAGAA,O;;;;;;;;;oDACAA,O","file":"index.js","sourcesContent":["// Non-XY charts\nexport {default as PieChart} from './PieChart';\nexport {default as TreeMap} from './TreeMap';\n\n// XYPlot & XY charts\nexport {default as XYPlot} from './XYPlot';\nexport {default as LineChart} from './LineChart';\nexport {default as ScatterPlot} from './ScatterPlot';\nexport {default as BarChart} from './BarChart';\nexport {default as RangeBarChart} from './RangeBarChart';\nexport {default as AreaBarChart} from './AreaBarChart';\nexport {default as MarkerLineChart} from './MarkerLineChart';\nexport {default as AreaChart} from './AreaChart';\nexport {default as ColorHeatmap} from './ColorHeatmap';\nexport {default as AreaHeatmap} from './AreaHeatmap';\nexport {default as Histogram} from './Histogram';\nexport {default as KernelDensityEstimation} from './KernelDensityEstimation';\n\n// XY datum components (used by charts & axes)\nexport {default as Bar} from './Bar';\nexport {default as RangeRect} from './RangeRect';\nexport {default as XLine} from './XLine';\nexport {default as YLine} from './YLine';\n\n// XY Axis Components\nexport {default as XAxis} from './XAxis';\nexport {default as XAxisLabels} from './XAxisLabels';\nexport {default as XAxisTitle} from './XAxisTitle';\nexport {default as XGrid} from './XGrid';\nexport {default as XTicks} from './XTicks';\n\nexport {default as YAxis} from './YAxis';\nexport {default as YAxisLabels} from './YAxisLabels';\nexport {default as YAxisTitle} from './YAxisTitle';\nexport {default as YGrid} from './YGrid';\nexport {default as YTicks} from './YTicks';\n\n// ### Higher-order components\nexport {default as resolveObjectProps} from './utils/resolveObjectProps';\nexport {default as resolveXYScales} from './utils/resolveXYScales';\n\n// ### Utilities\n// * Data\n// * Scale\n// * Axis\n// * Label\n// * Margin\n// * depthEqual\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"]} \ No newline at end of file +{"version":3,"sources":["../src/index.js"],"names":["default","Data","utils"],"mappings":";;;;;;;;;;;;6CACQA,O;;;;;;;;;4CACAA,O;;;;;;;;;2CAGAA,O;;;;;;;;;8CACAA,O;;;;;;;;;gDACAA,O;;;;;;;;;6CACAA,O;;;;;;;;;kDACAA,O;;;;;;;;;iDACAA,O;;;;;;;;;oDACAA,O;;;;;;;;;8CACAA,O;;;;;;;;;iDACAA,O;;;;;;;;;gDACAA,O;;;;;;;;;8CACAA,O;;;;;;;;;4DACAA,O;;;;;;;;;gDACAA,O;;;;;;;;;wCAGAA,O;;;;;;;;;8CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;0CAGAA,O;;;;;;;;;gDACAA,O;;;;;;;;;+CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;2CACAA,O;;;;;;;;;0CAEAA,O;;;;;;;;;gDACAA,O;;;;;;;;;+CACAA,O;;;;;;;;;0CACAA,O;;;;;;;;;2CACAA,O;;;;;;;;;uDAGAA,O;;;;;;;;;oDACAA,O;;;;AAER;;IAAYC,I;;;;;;AACL,IAAMC,wBAAQ,EAACD,UAAD,EAAd;AACP;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["// Non-XY charts\nexport {default as PieChart} from './PieChart';\nexport {default as TreeMap} from './TreeMap';\n\n// XYPlot & XY charts\nexport {default as XYPlot} from './XYPlot';\nexport {default as LineChart} from './LineChart';\nexport {default as ScatterPlot} from './ScatterPlot';\nexport {default as BarChart} from './BarChart';\nexport {default as RangeBarChart} from './RangeBarChart';\nexport {default as AreaBarChart} from './AreaBarChart';\nexport {default as MarkerLineChart} from './MarkerLineChart';\nexport {default as AreaChart} from './AreaChart';\nexport {default as ColorHeatmap} from './ColorHeatmap';\nexport {default as AreaHeatmap} from './AreaHeatmap';\nexport {default as Histogram} from './Histogram';\nexport {default as KernelDensityEstimation} from './KernelDensityEstimation';\nexport {default as FunnelChart} from './FunnelChart';\n\n// XY datum components (used by charts & axes)\nexport {default as Bar} from './Bar';\nexport {default as RangeRect} from './RangeRect';\nexport {default as XLine} from './XLine';\nexport {default as YLine} from './YLine';\n\n// XY Axis Components\nexport {default as XAxis} from './XAxis';\nexport {default as XAxisLabels} from './XAxisLabels';\nexport {default as XAxisTitle} from './XAxisTitle';\nexport {default as XGrid} from './XGrid';\nexport {default as XTicks} from './XTicks';\n\nexport {default as YAxis} from './YAxis';\nexport {default as YAxisLabels} from './YAxisLabels';\nexport {default as YAxisTitle} from './YAxisTitle';\nexport {default as YGrid} from './YGrid';\nexport {default as YTicks} from './YTicks';\n\n// ### Higher-order components\nexport {default as resolveObjectProps} from './utils/resolveObjectProps';\nexport {default as resolveXYScales} from './utils/resolveXYScales';\n\nimport * as Data from './utils/Data';\nexport const utils = {Data};\n// export {utils};\n\n\n// ### Utilities\n// * Data\n// * Scale\n// * Axis\n// * Label\n// * Margin\n// * depthEqual\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"]} \ No newline at end of file diff --git a/lib/utils/resolveXYScales.js b/lib/utils/resolveXYScales.js index 8fb81f62..679f053e 100644 --- a/lib/utils/resolveXYScales.js +++ b/lib/utils/resolveXYScales.js @@ -209,7 +209,8 @@ function resolveXYScales(ComposedComponent) { // todo - ticks, nice and getDomain should be an axis prop instead, and axis should have getDomain // set `nice` option to round scale domains to nicer numbers - // if(nice[k] && _.isFunction(kScale.nice)) kScale.nice(tickCount[k] || 10); + // const kTickCount = tickCount ? tickCount[k] : 10; + // if(nice && nice[k] && _.isFunction(kScale.nice)) kScale.nice(kTickCount); // extend scale domain to include custom `ticks` if passed // @@ -220,7 +221,7 @@ function resolveXYScales(ComposedComponent) { // } // reverse scale domain if `invertScale` is passed - if (invertScale[k]) kScale.domain(kScale.domain().reverse()); + // if(invertScale[k]) kScale.domain(kScale.domain().reverse()); return [k, kScale]; })); @@ -301,7 +302,7 @@ function resolveXYScales(ComposedComponent) { var propsDomain = props.domain || {}; // short-circuit if all domains provided - if (hasXYDomains(propsDomain)) return propsDomain; + if (hasXYDomains(propsDomain)) return { x: propsDomain.x, y: propsDomain.y }; // start with any domains in props, and try to resolve the rest var domain = omitNullUndefined(propsDomain); @@ -435,7 +436,7 @@ function resolveXYScales(ComposedComponent) { var props = this.props; var width = props.width, height = props.height, - nice = props.nice; + invertScale = props.invertScale; var scaleFromProps = this.props.scale || {}; @@ -447,6 +448,12 @@ function resolveXYScales(ComposedComponent) { // first resolve scale types and domains var scaleType = this._resolveScaleType(props, ComposedComponent); var domain = this._resolveDomain(props, ComposedComponent, scaleType); + if (_lodash2.default.isObject(invertScale)) { + ['x', 'y'].forEach(function (k) { + if (invertScale[k]) domain[k] = domain[k].slice().reverse(); + }); + } + var scaleOptions = { width: width, height: height, scaleType: scaleType, domain: domain, margin: props.margin, scale: props.scale, padding: props.padding, spacing: props.spacing }; // create a temporary scale with size & domain, which may be used by the Component to calculate margin/tickDomain // (eg. to create and measure labels for the scales) diff --git a/lib/utils/resolveXYScales.js.map b/lib/utils/resolveXYScales.js.map index 0b564d9f..eca334f5 100644 --- a/lib/utils/resolveXYScales.js.map +++ b/lib/utils/resolveXYScales.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/utils/resolveXYScales.js"],"names":["resolveXYScales","errs","getDomain","C","componentName","Component","displayName","hasScaleFor","scalesObj","key","isObject","hasPaddingFor","paddingObj","isNumber","hasXYScales","scale","x","y","hasXYDomains","domain","hasXYScaleTypes","scaleType","isString","hasAllMargins","margin","marginKeys","every","has","k","hasAllSpacing","spacing","spacingKeys","mapOverChildren","children","iteratee","iterateeArgs","isFunction","Error","compact","Children","map","child","isValidElement","props","type","omitNullUndefined","obj","omitBy","isUndefined","v","isNull","ComposedComponent","_makeScales","width","height","invertScale","nice","tickCount","ticks","innerChartWidth","innerChartHeight","range","left","top","fromPairs","kScale","reverse","propsScaleType","getScaleType","componentScaleType","assign","domainScaleType","undefined","isArray","data","datasets","datasetScaleType","kAccessor","get","toUpperCase","kDataType","kScaleType","count","childScaleTypes","_resolveScaleType","bind","childScaleType","kScaleTypes","uniq","length","propsDomain","componentDomain","datasetDomain","dataType","kDomain","childDomains","_resolveDomain","childDomain","getTickDomain","childTickDomains","_resolveTickDomain","tickDomain","kChildTickDomains","kTickDomain","propsSpacing","getSpacing","componentSpacing","childSpacings","_resolveSpacing","childSpacing","propsMargin","getMargin","componentMargin","childMargins","_resolveMargin","childMargin","scaleFromProps","scaleOptions","padding","tempScale","forEach","defaults","bottom","right","passedProps","defaultProps"],"mappings":"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","file":"resolveXYScales.js","sourcesContent":["import _ from 'lodash';\nimport {scalePoint} from 'd3';\nimport React from 'react';\nimport invariant from 'invariant';\n\nimport {\n makeAccessor,\n domainFromDatasets,\n domainFromData,\n inferDatasetsType,\n datasetsFromPropsOrDescendants,\n combineDomains,\n combineBorderObjects,\n isValidDomain\n} from './Data';\n\nimport {\n scaleTypeFromDataType,\n dataTypeFromScaleType,\n inferDataTypeFromDomain,\n initScale,\n isValidScale\n} from './Scale';\n\nimport {innerRangeX, innerRangeY, innerWidth, innerHeight} from './Margin';\n\n/**\n * `resolveXYScales` is a higher-order-component.\n *\n * @param {Component} Component - The React Component (class) which should be wrapped by this HOC\n * @returns {Component} - A Component which auto-resolves XY scales from given props\n*/\n\nconst errs = {\n getDomain: (C) =>\n `Components enhanced by resolveXYScales must have a static getDomain method, ${componentName(C)} does not have one`\n};\nfunction componentName(Component) {\n return Component.displayName || \"Component wrapped by resolveXYScales\";\n}\nfunction hasScaleFor(scalesObj, key) {\n return _.isObject(scalesObj) && isValidScale(scalesObj[key]);\n}\nfunction hasPaddingFor(paddingObj, key) {\n return _.isObject(paddingObj) && _.isNumber(paddingObj[key]);\n}\nfunction hasXYScales(scale) {\n return _.isObject(scale) && isValidScale(scale.x) && isValidScale(scale.y);\n}\nfunction hasXYDomains(domain) {\n return _.isObject(domain) && isValidDomain(domain.x) && isValidDomain(domain.y);\n}\nfunction hasXYScaleTypes(scaleType) {\n return _.isObject(scaleType) && _.isString(scaleType.x) && _.isString(scaleType.y);\n}\nfunction hasAllMargins(margin) {\n const marginKeys = ['top', 'bottom', 'left', 'right'];\n return _.isObject(margin) && _.every(marginKeys, k => _.has(margin, k));\n}\nfunction hasAllSpacing(spacing) {\n const spacingKeys = ['top', 'bottom', 'left', 'right'];\n return _.isObject(spacing) && _.every(spacingKeys, k => _.has(spacing, k));\n}\n\nfunction mapOverChildren(children, iteratee, ...iterateeArgs) {\n // loop over all children (react elements) and call iteratee (a function) on each one\n // iteratee is called with parameters (child.props, child.type, ...iterateeArgs)\n if(!_.isFunction(iteratee)) throw new Error('mapOverChildren iteratee must be a function');\n\n return _.compact(React.Children.map(children, child => {\n if(!child || !React.isValidElement(child)) return null;\n return iteratee(child.props, child.type, ...iterateeArgs);\n }));\n}\nfunction omitNullUndefined(obj) {\n return _.omitBy(obj, v => _.isUndefined(v) || _.isNull(v));\n}\n\n// not currently being used but potentially has some learnings\n// function resolveXYPropsOnComponentOrChildren(propKeys, props, reducers = {}, validators = {}, result = {}) {\n// const isDone = (o) => (_.every(propKeys, k => _.isObject(o[k]) && _.every(['x', 'y'], xy => _.has(o[k][xy]))));\n// result = _.pick({...props, ...result}, propKeys);\n\n// let resolved = {};\n// _.forEach(propKeys, propKey => {\n// _.forEach(['x', 'y'], k => {\n// const isValid = validators[propKey] || (() => true);\n// if(_.isObject(props[propKey]) && _.has(props[propKey], k) && isValid(props[propKey][k])) {\n// if(!_.has(result, propKey)) result[propKey] = {};\n// result[propKey][k] = props[propKey][k];\n// }\n// });\n// });\n\n// if(isDone(result)) return result;\n\n// if(React.Children.count(props.children)) {\n// let childProps = mapOverChildren(props.children, resolveXYPropsOnComponentOrChildren, propKeys, 'props', result);\n// React.Children.forEach(props.children, child => {\n// if(!child) return;\n// childProps.push(resolveXYPropsOnComponentOrChildren(propKeys, child.props, result));\n// });\n// let childDomains = [];\n// React.Children.forEach(props.children, child => {\n// childDomains = childDomains.concat(this._resolveDomain(child.props, child.type, scaleType));\n// });\n\n// console.log('combining domains', childDomains);\n// const childDomain = _.fromPairs(['x', 'y'].map(k => {\n// console.log(_.compact(_.map(childDomains, k)), scaleType[k]);\n// const kDomain = combineDomains(_.compact(_.map(childDomains, k)), dataTypeFromScaleType(scaleType[k]));\n// console.log(kDomain);\n// return [k, kDomain];\n// }));\n// console.log('combined domains', childDomain);\n\n// domain = _.assign(childDomain, domain);\n// return domain;\n// }\n\n// propKeys.forEach(k => {\n// result[propKeys] = props\n// })\n// }\n\n\n\nexport default function resolveXYScales(ComposedComponent) {\n return class extends React.Component {\n static defaultProps = _.defaults(ComposedComponent.defaultProps, {\n invertScale: {x: false, y: false},\n });\n\n // todo better way for HOC's to pass statics through?\n static getScaleType = ComposedComponent.getScaleType; \n static getSpacing = ComposedComponent.getSpacing;\n static getDomain = ComposedComponent.getDomain;\n static getMargin = ComposedComponent.getMargin;\n\n _resolveScaleType(props, Component) {\n const propsScaleType = props.scaleType || {};\n\n // short-circuit if all scale types provided\n if(hasXYScaleTypes(propsScaleType)) return propsScaleType;\n\n // start with any scale types in props, try to resolve the rest\n let scaleType = omitNullUndefined(propsScaleType);\n\n // if Component provides a custom static getScaleType method\n // use it to determine remaining scale types\n if(_.isFunction(Component.getScaleType)) {\n const componentScaleType = omitNullUndefined(Component.getScaleType(props));\n scaleType = _.assign(componentScaleType, scaleType);\n if(hasXYScaleTypes(scaleType)) return scaleType;\n }\n\n // todo infer scaleType from domain?\n // if component has domain props,\n // infer the data type, & use that to get scale type\n if(_.isObject(props.domain) && (isValidDomain(props.domain.x) || isValidDomain(props.domain.y))) {\n // console.log('inferring scale type from domain');\n const domainScaleType = _.fromPairs(['x', 'y'].map(k => {\n const domain = props.domain[k];\n return isValidDomain(domain) ?\n [k, scaleTypeFromDataType(inferDataTypeFromDomain(domain))] :\n [k, undefined];\n }));\n scaleType = _.assign(domainScaleType, scaleType);\n if(hasXYScaleTypes(scaleType)) return scaleType;\n }\n\n // if Component has data or datasets props,\n // infer the data type, & use that to get scale type\n if(_.isArray(props.data) || _.isArray(props.datasets)) {\n const datasets = _.isArray(props.datasets) ? props.datasets : [props.data];\n const datasetScaleType = _.fromPairs(['x', 'y'].map(k => {\n // const kAccessor = makeAccessor(_.get(props, `getValue.${k}`));\n const kAccessor = makeAccessor(_.get(props, `get${k.toUpperCase()}`));\n const kDataType = inferDatasetsType(datasets, kAccessor);\n const kScaleType = scaleTypeFromDataType(kDataType);\n return [k, kScaleType];\n }));\n\n scaleType = _.assign(datasetScaleType, scaleType);\n return scaleType;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their scale types the same way\n if(React.Children.count(props.children)) {\n // console.log('get scaletype from children')\n let childScaleTypes = mapOverChildren(props.children, this._resolveScaleType.bind(this));\n\n const childScaleType = _.fromPairs(['x', 'y'].map(k => {\n // todo warn on multiple scale types, probably not what you want\n const kScaleTypes = _.compact(_.uniq(_.map(childScaleTypes, k)));\n const kScaleType = (kScaleTypes.length === 1) ? kScaleTypes[0] : \"ordinal\";\n return [k, kScaleType];\n }));\n\n scaleType = _.assign(childScaleType, scaleType);\n return scaleType;\n }\n }\n\n _resolveDomain(props, Component, scaleType) {\n const propsDomain = props.domain || {};\n\n // short-circuit if all domains provided\n if(hasXYDomains(propsDomain)) return propsDomain;\n\n // start with any domains in props, and try to resolve the rest\n let domain = omitNullUndefined(propsDomain);\n\n // if Component provides a custom static getDomain method\n // use it to determine remaining domains\n if(_.isFunction(Component.getDomain)) {\n const componentDomain = omitNullUndefined(Component.getDomain({scaleType, ...props}));\n domain = _.assign(componentDomain, domain);\n if(hasXYDomains(domain)) return domain;\n }\n\n // if Component has data or datasets props,\n // use the default domainFromDatasets function to determine a domain from them\n if(_.isArray(props.data) || _.isArray(props.datasets)) {\n const datasets = _.isArray(props.datasets) ? props.datasets : [props.data];\n const datasetDomain = _.fromPairs(['x', 'y'].map(k => {\n // const kAccessor = makeAccessor(_.get(props, `getValue.${k}`));\n const kAccessor = makeAccessor(_.get(props, `get${k.toUpperCase()}`));\n const dataType = dataTypeFromScaleType(scaleType[k]);\n const kDomain = domainFromDatasets(datasets, kAccessor, dataType);\n return [k, kDomain];\n }));\n\n domain = _.assign(datasetDomain, domain);\n if(hasXYDomains(domain)) return domain;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their domains the same way,\n // and combine them into a single domain, if there are multiple\n if(React.Children.count(props.children)) {\n let childDomains = mapOverChildren(props.children, this._resolveDomain.bind(this), scaleType);\n\n const childDomain = _.fromPairs(['x', 'y'].map(k => {\n const kDomain = combineDomains(_.compact(_.map(childDomains, k)), dataTypeFromScaleType(scaleType[k]));\n return [k, kDomain];\n }));\n\n domain = _.assign(childDomain, domain);\n return domain;\n }\n }\n\n _resolveTickDomain(props, Component, scaleType, domain, scale) {\n // todo resolve directly from ticks/tickCount props?\n if(_.isFunction(Component.getTickDomain)) {\n return omitNullUndefined(Component.getTickDomain({scaleType, domain, scale, ...props}));\n }\n\n if(React.Children.count(props.children)) {\n let childTickDomains =\n mapOverChildren(props.children, this._resolveTickDomain.bind(this), scaleType, domain, scale);\n\n const tickDomain = _.fromPairs(['x', 'y'].map(k => {\n const kChildTickDomains = _.compact(childTickDomains.map(v => _.get(v, k)));\n const kTickDomain = kChildTickDomains.length ?\n combineDomains(kChildTickDomains, dataTypeFromScaleType(scaleType[k])) : undefined;\n return [k, kTickDomain];\n }));\n return omitNullUndefined(tickDomain);\n }\n }\n\n _resolveLabels(props) {\n\n }\n _resolveSpacing(props, Component, scaleType, domain, scale){\n const propsSpacing = props.spacing || {};\n\n // short-circuit if all spacings provided\n if(hasAllSpacing(propsSpacing)) return propsSpacing; \n\n let spacing = omitNullUndefined(propsSpacing);\n\n if(_.isFunction(Component.getSpacing)) {\n const componentSpacing = omitNullUndefined(Component.getSpacing({scaleType, domain, scale, ...props}));\n spacing = _.assign(componentSpacing, spacing);\n if(hasAllSpacing(spacing)) return spacing;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their spacings the same way,\n // and combine them into a single spacing, if there are multiple\n if(React.Children.count(props.children)) {\n let childSpacings = mapOverChildren(props.children, this._resolveSpacing.bind(this), scaleType, domain, scale);\n\n const childSpacing = combineBorderObjects(childSpacings);\n\n spacing = _.assign(childSpacing, spacing);\n }\n return spacing;\n\n }\n _resolveMargin(props, Component, scaleType, domain, scale) {\n const propsMargin = props.margin || {};\n\n // short-circuit if all margins provided\n if(hasAllMargins(propsMargin)) return propsMargin;\n\n // start with any margins in props, and try to resolve the rest\n let margin = omitNullUndefined(propsMargin);\n\n // if Component provides a custom static getMargin method\n // use it to determine remaining domains\n if(_.isFunction(Component.getMargin)) {\n const componentMargin = omitNullUndefined(Component.getMargin({scaleType, domain, scale, ...props}));\n margin = _.assign(componentMargin, margin);\n if(hasAllMargins(margin)) return margin;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their margins the same way,\n // and combine them into a single margin, if there are multiple\n if(React.Children.count(props.children)) {\n let childMargins = mapOverChildren(props.children, this._resolveMargin.bind(this), scaleType, domain, scale);\n\n // console.log('combining child margins', childMargins);\n const childMargin = combineBorderObjects(childMargins);\n\n margin = _.assign(childMargin, margin);\n }\n return margin;\n }\n\n _makeScales = ({width, height, scaleType={}, domain={}, margin={}, scale={}, spacing={}}) => {\n const {invertScale, nice, tickCount, ticks} = this.props;\n \n const innerChartWidth = innerWidth(width, margin);\n const innerChartHeight = innerHeight(height, margin);\n\n const range = {\n x: innerRangeX(innerChartWidth, spacing).map(v => v - (spacing.left || 0)),\n y: innerRangeY(innerChartHeight, spacing).map(v => v - (spacing.top || 0))\n };\n //innerRange functions produce range (i.e. [5,20]) and map function normalizes to 0 (i.e. [0,15])\n\n return _.fromPairs(['x', 'y'].map(k => {\n // use existing scales if provided, otherwise create new\n if(hasScaleFor(scale, k)) return [k, scale[k]];\n\n // create scale from domain/range\n const kScale = initScale(scaleType[k]).domain(domain[k]).range(range[k]);\n\n // todo - ticks, nice and getDomain should be an axis prop instead, and axis should have getDomain\n\n // set `nice` option to round scale domains to nicer numbers\n // if(nice[k] && _.isFunction(kScale.nice)) kScale.nice(tickCount[k] || 10);\n\n // extend scale domain to include custom `ticks` if passed\n //\n // if(ticks[k]) {\n // const dataType = dataTypeFromScaleType(scaleType[k]);\n // const tickDomain = domainFromData(ticks[k], _.identity, dataType);\n // kScale.domain(combineDomains([kScale.domain(), tickDomain]), dataType);\n // }\n\n // reverse scale domain if `invertScale` is passed\n if(invertScale[k]) kScale.domain(kScale.domain().reverse());\n\n return [k, kScale];\n }));\n };\n\n render() {\n const {props} = this;\n const {width, height, nice} = props;\n const scaleFromProps = this.props.scale || {};\n\n // short-circuit if scales provided\n // todo warn/throw if bad scales are passed\n if(hasXYScales(scaleFromProps))\n return ;\n\n // scales not provided, so we have to resolve them\n // first resolve scale types and domains\n const scaleType = this._resolveScaleType(props, ComposedComponent);\n const domain = this._resolveDomain(props, ComposedComponent, scaleType);\n let scaleOptions = {width, height, scaleType, domain, margin: props.margin, scale: props.scale, padding: props.padding, spacing: props.spacing};\n // create a temporary scale with size & domain, which may be used by the Component to calculate margin/tickDomain\n // (eg. to create and measure labels for the scales)\n let tempScale = this._makeScales(scaleOptions);\n\n // getTickDomain gives children the opportunity to modify the domain to include their scale ticks\n // (can't happen in getDomain, because it can't be done until the base domain/tempScale has been created)\n //nice-ing happens in the getTickDomain function inside of _resolveTickDomain\n const tickDomain = this._resolveTickDomain(props, ComposedComponent, scaleType, domain, tempScale);\n if(_.isObject(tickDomain)) {\n ['x', 'y'].forEach(k => {\n const dataType = dataTypeFromScaleType(scaleType[k]);\n if(isValidDomain(tickDomain[k], dataType))\n domain[k] = combineDomains([domain[k], tickDomain[k]], dataType);\n })\n }\n // update tempScale to use new domain before creating margins\n tempScale = this._makeScales(scaleOptions);\n\n // then resolve the margins\n const margin = _.defaults(\n this._resolveMargin(props, ComposedComponent, scaleType, domain, tempScale),\n {top: 0, bottom: 0, left: 0, right: 0}\n );\n\n const spacing = _.defaults(\n this._resolveSpacing(props, ComposedComponent, scaleType, domain, tempScale),\n {top: 0, bottom: 0, left: 0, right: 0}\n );\n\n // create real scales from resolved margins\n scaleOptions = {...scaleOptions, margin, spacing};\n const scale = this._makeScales(scaleOptions);\n \n const passedProps = _.assign({}, this.props, {scale, scaleType, margin, domain, spacing});\n return ;\n\n // todo spacing/padding\n // todo includeZero\n // todo purerender/shouldcomponentupdate?\n // todo resolve margins if scales are present\n // todo use zero for any margins which can't be resolved\n // todo throw if cannot resolve scaleType\n // todo throw if cannot resolve domain\n // todo check to make sure margins didn't change after scales resolved?\n }\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/utils/resolveXYScales.js"],"names":["resolveXYScales","errs","getDomain","C","componentName","Component","displayName","hasScaleFor","scalesObj","key","isObject","hasPaddingFor","paddingObj","isNumber","hasXYScales","scale","x","y","hasXYDomains","domain","hasXYScaleTypes","scaleType","isString","hasAllMargins","margin","marginKeys","every","has","k","hasAllSpacing","spacing","spacingKeys","mapOverChildren","children","iteratee","iterateeArgs","isFunction","Error","compact","Children","map","child","isValidElement","props","type","omitNullUndefined","obj","omitBy","isUndefined","v","isNull","ComposedComponent","_makeScales","width","height","invertScale","nice","tickCount","ticks","innerChartWidth","innerChartHeight","range","left","top","fromPairs","kScale","propsScaleType","getScaleType","componentScaleType","assign","domainScaleType","undefined","isArray","data","datasets","datasetScaleType","kAccessor","get","toUpperCase","kDataType","kScaleType","count","childScaleTypes","_resolveScaleType","bind","childScaleType","kScaleTypes","uniq","length","propsDomain","componentDomain","datasetDomain","dataType","kDomain","childDomains","_resolveDomain","childDomain","getTickDomain","childTickDomains","_resolveTickDomain","tickDomain","kChildTickDomains","kTickDomain","propsSpacing","getSpacing","componentSpacing","childSpacings","_resolveSpacing","childSpacing","propsMargin","getMargin","componentMargin","childMargins","_resolveMargin","childMargin","scaleFromProps","forEach","slice","reverse","scaleOptions","padding","tempScale","defaults","bottom","right","passedProps","defaultProps"],"mappings":"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","file":"resolveXYScales.js","sourcesContent":["import _ from 'lodash';\nimport {scalePoint} from 'd3';\nimport React from 'react';\nimport invariant from 'invariant';\n\nimport {\n makeAccessor,\n domainFromDatasets,\n domainFromData,\n inferDatasetsType,\n datasetsFromPropsOrDescendants,\n combineDomains,\n combineBorderObjects,\n isValidDomain\n} from './Data';\n\nimport {\n scaleTypeFromDataType,\n dataTypeFromScaleType,\n inferDataTypeFromDomain,\n initScale,\n isValidScale\n} from './Scale';\n\nimport {innerRangeX, innerRangeY, innerWidth, innerHeight} from './Margin';\n\n/**\n * `resolveXYScales` is a higher-order-component.\n *\n * @param {Component} Component - The React Component (class) which should be wrapped by this HOC\n * @returns {Component} - A Component which auto-resolves XY scales from given props\n*/\n\nconst errs = {\n getDomain: (C) =>\n `Components enhanced by resolveXYScales must have a static getDomain method, ${componentName(C)} does not have one`\n};\nfunction componentName(Component) {\n return Component.displayName || \"Component wrapped by resolveXYScales\";\n}\nfunction hasScaleFor(scalesObj, key) {\n return _.isObject(scalesObj) && isValidScale(scalesObj[key]);\n}\nfunction hasPaddingFor(paddingObj, key) {\n return _.isObject(paddingObj) && _.isNumber(paddingObj[key]);\n}\nfunction hasXYScales(scale) {\n return _.isObject(scale) && isValidScale(scale.x) && isValidScale(scale.y);\n}\nfunction hasXYDomains(domain) {\n return _.isObject(domain) && isValidDomain(domain.x) && isValidDomain(domain.y);\n}\nfunction hasXYScaleTypes(scaleType) {\n return _.isObject(scaleType) && _.isString(scaleType.x) && _.isString(scaleType.y);\n}\nfunction hasAllMargins(margin) {\n const marginKeys = ['top', 'bottom', 'left', 'right'];\n return _.isObject(margin) && _.every(marginKeys, k => _.has(margin, k));\n}\nfunction hasAllSpacing(spacing) {\n const spacingKeys = ['top', 'bottom', 'left', 'right'];\n return _.isObject(spacing) && _.every(spacingKeys, k => _.has(spacing, k));\n}\n\nfunction mapOverChildren(children, iteratee, ...iterateeArgs) {\n // loop over all children (react elements) and call iteratee (a function) on each one\n // iteratee is called with parameters (child.props, child.type, ...iterateeArgs)\n if(!_.isFunction(iteratee)) throw new Error('mapOverChildren iteratee must be a function');\n\n return _.compact(React.Children.map(children, child => {\n if(!child || !React.isValidElement(child)) return null;\n return iteratee(child.props, child.type, ...iterateeArgs);\n }));\n}\nfunction omitNullUndefined(obj) {\n return _.omitBy(obj, v => _.isUndefined(v) || _.isNull(v));\n}\n\n// not currently being used but potentially has some learnings\n// function resolveXYPropsOnComponentOrChildren(propKeys, props, reducers = {}, validators = {}, result = {}) {\n// const isDone = (o) => (_.every(propKeys, k => _.isObject(o[k]) && _.every(['x', 'y'], xy => _.has(o[k][xy]))));\n// result = _.pick({...props, ...result}, propKeys);\n\n// let resolved = {};\n// _.forEach(propKeys, propKey => {\n// _.forEach(['x', 'y'], k => {\n// const isValid = validators[propKey] || (() => true);\n// if(_.isObject(props[propKey]) && _.has(props[propKey], k) && isValid(props[propKey][k])) {\n// if(!_.has(result, propKey)) result[propKey] = {};\n// result[propKey][k] = props[propKey][k];\n// }\n// });\n// });\n\n// if(isDone(result)) return result;\n\n// if(React.Children.count(props.children)) {\n// let childProps = mapOverChildren(props.children, resolveXYPropsOnComponentOrChildren, propKeys, 'props', result);\n// React.Children.forEach(props.children, child => {\n// if(!child) return;\n// childProps.push(resolveXYPropsOnComponentOrChildren(propKeys, child.props, result));\n// });\n// let childDomains = [];\n// React.Children.forEach(props.children, child => {\n// childDomains = childDomains.concat(this._resolveDomain(child.props, child.type, scaleType));\n// });\n\n// console.log('combining domains', childDomains);\n// const childDomain = _.fromPairs(['x', 'y'].map(k => {\n// console.log(_.compact(_.map(childDomains, k)), scaleType[k]);\n// const kDomain = combineDomains(_.compact(_.map(childDomains, k)), dataTypeFromScaleType(scaleType[k]));\n// console.log(kDomain);\n// return [k, kDomain];\n// }));\n// console.log('combined domains', childDomain);\n\n// domain = _.assign(childDomain, domain);\n// return domain;\n// }\n\n// propKeys.forEach(k => {\n// result[propKeys] = props\n// })\n// }\n\n\n\nexport default function resolveXYScales(ComposedComponent) {\n return class extends React.Component {\n static defaultProps = _.defaults(ComposedComponent.defaultProps, {\n invertScale: {x: false, y: false},\n });\n\n // todo better way for HOC's to pass statics through?\n static getScaleType = ComposedComponent.getScaleType; \n static getSpacing = ComposedComponent.getSpacing;\n static getDomain = ComposedComponent.getDomain;\n static getMargin = ComposedComponent.getMargin;\n\n _resolveScaleType(props, Component) {\n const propsScaleType = props.scaleType || {};\n\n // short-circuit if all scale types provided\n if(hasXYScaleTypes(propsScaleType)) return propsScaleType;\n\n // start with any scale types in props, try to resolve the rest\n let scaleType = omitNullUndefined(propsScaleType);\n\n // if Component provides a custom static getScaleType method\n // use it to determine remaining scale types\n if(_.isFunction(Component.getScaleType)) {\n const componentScaleType = omitNullUndefined(Component.getScaleType(props));\n scaleType = _.assign(componentScaleType, scaleType);\n if(hasXYScaleTypes(scaleType)) return scaleType;\n }\n\n // todo infer scaleType from domain?\n // if component has domain props,\n // infer the data type, & use that to get scale type\n if(_.isObject(props.domain) && (isValidDomain(props.domain.x) || isValidDomain(props.domain.y))) {\n // console.log('inferring scale type from domain');\n const domainScaleType = _.fromPairs(['x', 'y'].map(k => {\n const domain = props.domain[k];\n return isValidDomain(domain) ?\n [k, scaleTypeFromDataType(inferDataTypeFromDomain(domain))] :\n [k, undefined];\n }));\n scaleType = _.assign(domainScaleType, scaleType);\n if(hasXYScaleTypes(scaleType)) return scaleType;\n }\n\n // if Component has data or datasets props,\n // infer the data type, & use that to get scale type\n if(_.isArray(props.data) || _.isArray(props.datasets)) {\n const datasets = _.isArray(props.datasets) ? props.datasets : [props.data];\n const datasetScaleType = _.fromPairs(['x', 'y'].map(k => {\n // const kAccessor = makeAccessor(_.get(props, `getValue.${k}`));\n const kAccessor = makeAccessor(_.get(props, `get${k.toUpperCase()}`));\n const kDataType = inferDatasetsType(datasets, kAccessor);\n const kScaleType = scaleTypeFromDataType(kDataType);\n return [k, kScaleType];\n }));\n\n scaleType = _.assign(datasetScaleType, scaleType);\n return scaleType;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their scale types the same way\n if(React.Children.count(props.children)) {\n // console.log('get scaletype from children')\n let childScaleTypes = mapOverChildren(props.children, this._resolveScaleType.bind(this));\n\n const childScaleType = _.fromPairs(['x', 'y'].map(k => {\n // todo warn on multiple scale types, probably not what you want\n const kScaleTypes = _.compact(_.uniq(_.map(childScaleTypes, k)));\n const kScaleType = (kScaleTypes.length === 1) ? kScaleTypes[0] : \"ordinal\";\n return [k, kScaleType];\n }));\n\n scaleType = _.assign(childScaleType, scaleType);\n return scaleType;\n }\n }\n\n _resolveDomain(props, Component, scaleType) {\n const propsDomain = props.domain || {};\n\n // short-circuit if all domains provided\n if(hasXYDomains(propsDomain)) return {x: propsDomain.x, y: propsDomain.y};\n\n // start with any domains in props, and try to resolve the rest\n let domain = omitNullUndefined(propsDomain);\n\n // if Component provides a custom static getDomain method\n // use it to determine remaining domains\n if(_.isFunction(Component.getDomain)) {\n const componentDomain = omitNullUndefined(Component.getDomain({scaleType, ...props}));\n domain = _.assign(componentDomain, domain);\n if(hasXYDomains(domain)) return domain;\n }\n\n // if Component has data or datasets props,\n // use the default domainFromDatasets function to determine a domain from them\n if(_.isArray(props.data) || _.isArray(props.datasets)) {\n const datasets = _.isArray(props.datasets) ? props.datasets : [props.data];\n const datasetDomain = _.fromPairs(['x', 'y'].map(k => {\n // const kAccessor = makeAccessor(_.get(props, `getValue.${k}`));\n const kAccessor = makeAccessor(_.get(props, `get${k.toUpperCase()}`));\n const dataType = dataTypeFromScaleType(scaleType[k]);\n const kDomain = domainFromDatasets(datasets, kAccessor, dataType);\n return [k, kDomain];\n }));\n\n domain = _.assign(datasetDomain, domain);\n if(hasXYDomains(domain)) return domain;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their domains the same way,\n // and combine them into a single domain, if there are multiple\n if(React.Children.count(props.children)) {\n let childDomains = mapOverChildren(props.children, this._resolveDomain.bind(this), scaleType);\n\n const childDomain = _.fromPairs(['x', 'y'].map(k => {\n const kDomain = combineDomains(_.compact(_.map(childDomains, k)), dataTypeFromScaleType(scaleType[k]));\n return [k, kDomain];\n }));\n\n domain = _.assign(childDomain, domain);\n return domain;\n }\n }\n\n _resolveTickDomain(props, Component, scaleType, domain, scale) {\n // todo resolve directly from ticks/tickCount props?\n if(_.isFunction(Component.getTickDomain)) {\n return omitNullUndefined(Component.getTickDomain({scaleType, domain, scale, ...props}));\n }\n\n if(React.Children.count(props.children)) {\n let childTickDomains =\n mapOverChildren(props.children, this._resolveTickDomain.bind(this), scaleType, domain, scale);\n\n const tickDomain = _.fromPairs(['x', 'y'].map(k => {\n const kChildTickDomains = _.compact(childTickDomains.map(v => _.get(v, k)));\n const kTickDomain = kChildTickDomains.length ?\n combineDomains(kChildTickDomains, dataTypeFromScaleType(scaleType[k])) : undefined;\n return [k, kTickDomain];\n }));\n return omitNullUndefined(tickDomain);\n }\n }\n\n _resolveLabels(props) {\n\n }\n _resolveSpacing(props, Component, scaleType, domain, scale){\n const propsSpacing = props.spacing || {};\n\n // short-circuit if all spacings provided\n if(hasAllSpacing(propsSpacing)) return propsSpacing; \n\n let spacing = omitNullUndefined(propsSpacing);\n\n if(_.isFunction(Component.getSpacing)) {\n const componentSpacing = omitNullUndefined(Component.getSpacing({scaleType, domain, scale, ...props}));\n spacing = _.assign(componentSpacing, spacing);\n if(hasAllSpacing(spacing)) return spacing;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their spacings the same way,\n // and combine them into a single spacing, if there are multiple\n if(React.Children.count(props.children)) {\n let childSpacings = mapOverChildren(props.children, this._resolveSpacing.bind(this), scaleType, domain, scale);\n\n const childSpacing = combineBorderObjects(childSpacings);\n\n spacing = _.assign(childSpacing, spacing);\n }\n return spacing;\n\n }\n _resolveMargin(props, Component, scaleType, domain, scale) {\n const propsMargin = props.margin || {};\n\n // short-circuit if all margins provided\n if(hasAllMargins(propsMargin)) return propsMargin;\n\n // start with any margins in props, and try to resolve the rest\n let margin = omitNullUndefined(propsMargin);\n\n // if Component provides a custom static getMargin method\n // use it to determine remaining domains\n if(_.isFunction(Component.getMargin)) {\n const componentMargin = omitNullUndefined(Component.getMargin({scaleType, domain, scale, ...props}));\n margin = _.assign(componentMargin, margin);\n if(hasAllMargins(margin)) return margin;\n }\n\n // if Component has children,\n // recurse through descendants to resolve their margins the same way,\n // and combine them into a single margin, if there are multiple\n if(React.Children.count(props.children)) {\n let childMargins = mapOverChildren(props.children, this._resolveMargin.bind(this), scaleType, domain, scale);\n\n // console.log('combining child margins', childMargins);\n const childMargin = combineBorderObjects(childMargins);\n\n margin = _.assign(childMargin, margin);\n }\n return margin;\n }\n\n _makeScales = ({width, height, scaleType={}, domain={}, margin={}, scale={}, spacing={}}) => {\n const {invertScale, nice, tickCount, ticks} = this.props;\n \n const innerChartWidth = innerWidth(width, margin);\n const innerChartHeight = innerHeight(height, margin);\n\n const range = {\n x: innerRangeX(innerChartWidth, spacing).map(v => v - (spacing.left || 0)),\n y: innerRangeY(innerChartHeight, spacing).map(v => v - (spacing.top || 0))\n };\n //innerRange functions produce range (i.e. [5,20]) and map function normalizes to 0 (i.e. [0,15])\n\n return _.fromPairs(['x', 'y'].map(k => {\n // use existing scales if provided, otherwise create new\n if(hasScaleFor(scale, k)) return [k, scale[k]];\n\n // create scale from domain/range\n const kScale = initScale(scaleType[k]).domain(domain[k]).range(range[k]);\n\n // todo - ticks, nice and getDomain should be an axis prop instead, and axis should have getDomain\n\n // set `nice` option to round scale domains to nicer numbers\n // const kTickCount = tickCount ? tickCount[k] : 10;\n // if(nice && nice[k] && _.isFunction(kScale.nice)) kScale.nice(kTickCount);\n\n // extend scale domain to include custom `ticks` if passed\n //\n // if(ticks[k]) {\n // const dataType = dataTypeFromScaleType(scaleType[k]);\n // const tickDomain = domainFromData(ticks[k], _.identity, dataType);\n // kScale.domain(combineDomains([kScale.domain(), tickDomain]), dataType);\n // }\n\n // reverse scale domain if `invertScale` is passed\n // if(invertScale[k]) kScale.domain(kScale.domain().reverse());\n\n return [k, kScale];\n }));\n };\n\n render() {\n const {props} = this;\n const {width, height, invertScale} = props;\n const scaleFromProps = this.props.scale || {};\n\n // short-circuit if scales provided\n // todo warn/throw if bad scales are passed\n if(hasXYScales(scaleFromProps))\n return ;\n\n // scales not provided, so we have to resolve them\n // first resolve scale types and domains\n const scaleType = this._resolveScaleType(props, ComposedComponent);\n const domain = this._resolveDomain(props, ComposedComponent, scaleType);\n if(_.isObject(invertScale)) {\n ['x', 'y'].forEach(k => {\n if(invertScale[k]) domain[k] = domain[k].slice().reverse();\n })\n }\n\n let scaleOptions = {width, height, scaleType, domain, margin: props.margin, scale: props.scale, padding: props.padding, spacing: props.spacing};\n // create a temporary scale with size & domain, which may be used by the Component to calculate margin/tickDomain\n // (eg. to create and measure labels for the scales)\n let tempScale = this._makeScales(scaleOptions);\n\n // getTickDomain gives children the opportunity to modify the domain to include their scale ticks\n // (can't happen in getDomain, because it can't be done until the base domain/tempScale has been created)\n //nice-ing happens in the getTickDomain function inside of _resolveTickDomain\n const tickDomain = this._resolveTickDomain(props, ComposedComponent, scaleType, domain, tempScale);\n if(_.isObject(tickDomain)) {\n ['x', 'y'].forEach(k => {\n const dataType = dataTypeFromScaleType(scaleType[k]);\n if(isValidDomain(tickDomain[k], dataType))\n domain[k] = combineDomains([domain[k], tickDomain[k]], dataType);\n })\n }\n // update tempScale to use new domain before creating margins\n tempScale = this._makeScales(scaleOptions);\n\n // then resolve the margins\n const margin = _.defaults(\n this._resolveMargin(props, ComposedComponent, scaleType, domain, tempScale),\n {top: 0, bottom: 0, left: 0, right: 0}\n );\n\n const spacing = _.defaults(\n this._resolveSpacing(props, ComposedComponent, scaleType, domain, tempScale),\n {top: 0, bottom: 0, left: 0, right: 0}\n );\n\n // create real scales from resolved margins\n scaleOptions = {...scaleOptions, margin, spacing};\n const scale = this._makeScales(scaleOptions);\n \n const passedProps = _.assign({}, this.props, {scale, scaleType, margin, domain, spacing});\n return ;\n\n // todo spacing/padding\n // todo includeZero\n // todo purerender/shouldcomponentupdate?\n // todo resolve margins if scales are present\n // todo use zero for any margins which can't be resolved\n // todo throw if cannot resolve scaleType\n // todo throw if cannot resolve domain\n // todo check to make sure margins didn't change after scales resolved?\n }\n }\n}\n"]} \ No newline at end of file diff --git a/lib/utils/xyPropsEqual.js b/lib/utils/xyPropsEqual.js index 80ed3278..52027a57 100644 --- a/lib/utils/xyPropsEqual.js +++ b/lib/utils/xyPropsEqual.js @@ -28,10 +28,13 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de // default list of props to check for *deep equality* using _.isEqual // can be overridden by components by passing `propKeysToDeepCheck` argument // todo: decide whether data really belongs on this list? deep-checking data can be slow, but re-rendering is even slower -var defaultPropKeysToDeepCheck = exports.defaultPropKeysToDeepCheck = ['margin', 'scaleType', 'spacing', 'domain', 'style', 'lineStyle', 'data']; +var defaultPropKeysToDeepCheck = exports.defaultPropKeysToDeepCheck = ['margin', 'scaleType', 'spacing', 'domain', 'style', 'data']; function xyPropsEqual(propsA, propsB) { - var propKeysToDeepCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultPropKeysToDeepCheck; + var customKeysToDeepCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; + var includeDefaults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + + var propKeysToDeepCheck = includeDefaults ? defaultPropKeysToDeepCheck.concat(customKeysToDeepCheck) : customKeysToDeepCheck; var propKeysToSkipShallowCheck = propKeysToDeepCheck.concat('scale'); @@ -51,15 +54,17 @@ function xyPropsEqual(propsA, propsB) { } function xyPropsEqualDebug(propsA, propsB) { - var propKeysToDeepCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultPropKeysToDeepCheck; + var customKeysToDeepCheck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; + var includeDefaults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; + var propKeysToDeepCheck = includeDefaults ? defaultPropKeysToDeepCheck.concat(customKeysToDeepCheck) : customKeysToDeepCheck; // debug version of xyPropsEqual which console.logs, for figuring out which props are failing equality check // const start = performance.now(); var propKeysToSkipShallowCheck = propKeysToDeepCheck.concat('scale'); var isEqual = // most keys just get shallow-equality checked - (0, _shallowEqual2.default)(_lodash2.default.omit(propsA, propKeysToSkipShallowCheck), _lodash2.default.omit(propsB, propKeysToSkipShallowCheck)) && _lodash2.default.every(deeperProps, function (key) { + (0, _shallowEqual2.default)(_lodash2.default.omit(propsA, propKeysToSkipShallowCheck), _lodash2.default.omit(propsB, propKeysToSkipShallowCheck)) && _lodash2.default.every(propKeysToDeepCheck, function (key) { var isDeepEqual = _lodash2.default.isEqual(propsA[key], propsB[key]); if (!isDeepEqual) console.log('xyProps: ' + key + ' not equal'); return isDeepEqual; diff --git a/lib/utils/xyPropsEqual.js.map b/lib/utils/xyPropsEqual.js.map index e68c1175..13ab2b5f 100644 --- a/lib/utils/xyPropsEqual.js.map +++ b/lib/utils/xyPropsEqual.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../src/utils/xyPropsEqual.js"],"names":["xyPropsEqual","xyPropsEqualDebug","defaultPropKeysToDeepCheck","propsA","propsB","propKeysToDeepCheck","propKeysToSkipShallowCheck","concat","isEqual","omit","every","key","get","deeperProps","isDeepEqual","console","log","isScaleEqual","scale"],"mappings":";;;;;;kBAiBwBA,Y;QAgBRC,iB,GAAAA,iB;;AAjChB;;;;AACA;;;;AACA;;;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACO,IAAMC,kEAA6B,CACxC,QADwC,EAC9B,WAD8B,EACjB,SADiB,EACN,QADM,EACI,OADJ,EACa,WADb,EAC0B,MAD1B,CAAnC;;AAIQ,SAASF,YAAT,CAAsBG,MAAtB,EAA8BC,MAA9B,EAAwF;AAAA,MAAlDC,mBAAkD,uEAA5BH,0BAA4B;;AACrG,MAAMI,6BAA6BD,oBAAoBE,MAApB,CAA2B,OAA3B,CAAnC;;AAEA,MAAMC;AACJ;AACA,8BAAa,iBAAEC,IAAF,CAAON,MAAP,EAAeG,0BAAf,CAAb,EAAyD,iBAAEG,IAAF,CAAOL,MAAP,EAAeE,0BAAf,CAAzD;AACA;AACA,mBAAEI,KAAF,CAAQL,mBAAR,EAA6B,UAACM,GAAD;AAAA,WAAS,iBAAEH,OAAF,CAAUL,OAAOQ,GAAP,CAAV,EAAuBP,OAAOO,GAAP,CAAvB,CAAT;AAAA,GAA7B,CAFA;AAGA;AACA,mBAAED,KAAF,CAAQ,CAAC,GAAD,EAAM,GAAN,CAAR,EAAoB,UAACC,GAAD,EAAS;AAC3B,WAAO,uBAAW,iBAAEC,GAAF,CAAMT,MAAN,aAAuBQ,GAAvB,OAAX,EAA2C,iBAAEC,GAAF,CAAMT,MAAN,aAAuBQ,GAAvB,OAA3C,CAAP;AACD,GAFD,CANF;;AAUA,SAAOH,OAAP;AACD;;AAEM,SAASP,iBAAT,CAA2BE,MAA3B,EAAmCC,MAAnC,EAA6F;AAAA,MAAlDC,mBAAkD,uEAA5BH,0BAA4B;;AAClG;AACA;AACA,MAAMI,6BAA6BD,oBAAoBE,MAApB,CAA2B,OAA3B,CAAnC;;AAEA,MAAMC;AACJ;AACA,8BAAa,iBAAEC,IAAF,CAAON,MAAP,EAAeG,0BAAf,CAAb,EAAyD,iBAAEG,IAAF,CAAOL,MAAP,EAAeE,0BAAf,CAAzD,KACA,iBAAEI,KAAF,CAAQG,WAAR,EAAqB,UAACF,GAAD,EAAS;AAC5B,QAAMG,cAAc,iBAAEN,OAAF,CAAUL,OAAOQ,GAAP,CAAV,EAAuBP,OAAOO,GAAP,CAAvB,CAApB;AACA,QAAG,CAACG,WAAJ,EAAiBC,QAAQC,GAAR,eAAwBL,GAAxB;AACjB,WAAOG,WAAP;AACD,GAJD,CADA,IAMA,iBAAEJ,KAAF,CAAQ,CAAC,GAAD,EAAM,GAAN,CAAR,EAAoB,UAACC,GAAD,EAAS;AAC3B,QAAMM,eAAe,uBAAWd,OAAOe,KAAP,CAAaP,GAAb,CAAX,EAA8BP,OAAOc,KAAP,CAAaP,GAAb,CAA9B,CAArB;AACA,QAAG,CAACM,YAAJ,EAAkBF,QAAQC,GAAR,qBAA8BL,GAA9B;AAClB,WAAOM,YAAP;AACD,GAJD,CARF;;AAcA;AACA;AACA,SAAOT,OAAP;AACD","file":"xyPropsEqual.js","sourcesContent":["import _ from 'lodash';\nimport shallowEqual from './shallowEqual';\nimport {scaleEqual} from './Scale';\n\n// xyPropsEqual is a function used by XYPlot-type charts,\n// in their `shouldComponentUpdate` methods, for determining whether next props are the same as previous props.\n// in a perfect world this would just be a simple shallow equality check,\n// however some props are almost always passed as object/array literals (so they never ===)\n// or require special equality checks (eg. d3 scales)\n\n// default list of props to check for *deep equality* using _.isEqual\n// can be overridden by components by passing `propKeysToDeepCheck` argument\n// todo: decide whether data really belongs on this list? deep-checking data can be slow, but re-rendering is even slower\nexport const defaultPropKeysToDeepCheck = [\n 'margin', 'scaleType', 'spacing', 'domain', 'style', 'lineStyle', 'data'\n];\n\nexport default function xyPropsEqual(propsA, propsB, propKeysToDeepCheck = defaultPropKeysToDeepCheck) {\n const propKeysToSkipShallowCheck = propKeysToDeepCheck.concat('scale');\n\n const isEqual =\n // most keys just get shallow-equality checked\n shallowEqual(_.omit(propsA, propKeysToSkipShallowCheck), _.omit(propsB, propKeysToSkipShallowCheck)) &&\n // propKeysToDeepCheck get deep-equality checked using _.isEqual\n _.every(propKeysToDeepCheck, (key) => _.isEqual(propsA[key], propsB[key])) &&\n // d3 scales are special, get deep-checked using custom `scaleEqual` utility\n _.every(['x', 'y'], (key) => {\n return scaleEqual(_.get(propsA, `scale[${key}]`), _.get(propsA, `scale[${key}]`));\n });\n\n return isEqual;\n}\n\nexport function xyPropsEqualDebug(propsA, propsB, propKeysToDeepCheck = defaultPropKeysToDeepCheck) {\n // debug version of xyPropsEqual which console.logs, for figuring out which props are failing equality check\n // const start = performance.now();\n const propKeysToSkipShallowCheck = propKeysToDeepCheck.concat('scale');\n\n const isEqual =\n // most keys just get shallow-equality checked\n shallowEqual(_.omit(propsA, propKeysToSkipShallowCheck), _.omit(propsB, propKeysToSkipShallowCheck)) &&\n _.every(deeperProps, (key) => {\n const isDeepEqual = _.isEqual(propsA[key], propsB[key]);\n if(!isDeepEqual) console.log(`xyProps: ${key} not equal`);\n return isDeepEqual;\n }) &&\n _.every(['x', 'y'], (key) => {\n const isScaleEqual = scaleEqual(propsA.scale[key], propsB.scale[key]);\n if(!isScaleEqual) console.log(`xyProps: scale.${key} not equal`);\n return isScaleEqual;\n });\n\n // console.log('xyProps isEqual', isEqual);\n // console.log('took', performance.now() - start);\n return isEqual;\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../src/utils/xyPropsEqual.js"],"names":["xyPropsEqual","xyPropsEqualDebug","defaultPropKeysToDeepCheck","propsA","propsB","customKeysToDeepCheck","includeDefaults","propKeysToDeepCheck","concat","propKeysToSkipShallowCheck","isEqual","omit","every","key","get","isDeepEqual","console","log","isScaleEqual","scale"],"mappings":";;;;;;kBAiBwBA,Y;QAoBRC,iB,GAAAA,iB;;AArChB;;;;AACA;;;;AACA;;;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACO,IAAMC,kEAA6B,CACxC,QADwC,EAC9B,WAD8B,EACjB,SADiB,EACN,QADM,EACI,OADJ,EACa,MADb,CAAnC;;AAIQ,SAASF,YAAT,CAAsBG,MAAtB,EAA8BC,MAA9B,EAA0F;AAAA,MAApDC,qBAAoD,uEAA5B,EAA4B;AAAA,MAAxBC,eAAwB,uEAAN,IAAM;;AACvG,MAAMC,sBAAsBD,kBAC1BJ,2BAA2BM,MAA3B,CAAkCH,qBAAlC,CAD0B,GAE1BA,qBAFF;;AAIA,MAAMI,6BAA6BF,oBAAoBC,MAApB,CAA2B,OAA3B,CAAnC;;AAEA,MAAME;AACJ;AACA,8BAAa,iBAAEC,IAAF,CAAOR,MAAP,EAAeM,0BAAf,CAAb,EAAyD,iBAAEE,IAAF,CAAOP,MAAP,EAAeK,0BAAf,CAAzD;AACA;AACA,mBAAEG,KAAF,CAAQL,mBAAR,EAA6B,UAACM,GAAD;AAAA,WAAS,iBAAEH,OAAF,CAAUP,OAAOU,GAAP,CAAV,EAAuBT,OAAOS,GAAP,CAAvB,CAAT;AAAA,GAA7B,CAFA;AAGA;AACA,mBAAED,KAAF,CAAQ,CAAC,GAAD,EAAM,GAAN,CAAR,EAAoB,UAACC,GAAD,EAAS;AAC3B,WAAO,uBAAW,iBAAEC,GAAF,CAAMX,MAAN,aAAuBU,GAAvB,OAAX,EAA2C,iBAAEC,GAAF,CAAMX,MAAN,aAAuBU,GAAvB,OAA3C,CAAP;AACD,GAFD,CANF;;AAUA,SAAOH,OAAP;AACD;;AAEM,SAAST,iBAAT,CAA2BE,MAA3B,EAAmCC,MAAnC,EAA+F;AAAA,MAApDC,qBAAoD,uEAA5B,EAA4B;AAAA,MAAxBC,eAAwB,uEAAN,IAAM;;AACpG,MAAMC,sBAAsBD,kBAC1BJ,2BAA2BM,MAA3B,CAAkCH,qBAAlC,CAD0B,GAE1BA,qBAFF;AAGA;AACA;AACA,MAAMI,6BAA6BF,oBAAoBC,MAApB,CAA2B,OAA3B,CAAnC;;AAEA,MAAME;AACJ;AACA,8BAAa,iBAAEC,IAAF,CAAOR,MAAP,EAAeM,0BAAf,CAAb,EAAyD,iBAAEE,IAAF,CAAOP,MAAP,EAAeK,0BAAf,CAAzD,KACA,iBAAEG,KAAF,CAAQL,mBAAR,EAA6B,UAACM,GAAD,EAAS;AACpC,QAAME,cAAc,iBAAEL,OAAF,CAAUP,OAAOU,GAAP,CAAV,EAAuBT,OAAOS,GAAP,CAAvB,CAApB;AACA,QAAG,CAACE,WAAJ,EAAiBC,QAAQC,GAAR,eAAwBJ,GAAxB;AACjB,WAAOE,WAAP;AACD,GAJD,CADA,IAMA,iBAAEH,KAAF,CAAQ,CAAC,GAAD,EAAM,GAAN,CAAR,EAAoB,UAACC,GAAD,EAAS;AAC3B,QAAMK,eAAe,uBAAWf,OAAOgB,KAAP,CAAaN,GAAb,CAAX,EAA8BT,OAAOe,KAAP,CAAaN,GAAb,CAA9B,CAArB;AACA,QAAG,CAACK,YAAJ,EAAkBF,QAAQC,GAAR,qBAA8BJ,GAA9B;AAClB,WAAOK,YAAP;AACD,GAJD,CARF;;AAcA;AACA;AACA,SAAOR,OAAP;AACD","file":"xyPropsEqual.js","sourcesContent":["import _ from 'lodash';\nimport shallowEqual from './shallowEqual';\nimport {scaleEqual} from './Scale';\n\n// xyPropsEqual is a function used by XYPlot-type charts,\n// in their `shouldComponentUpdate` methods, for determining whether next props are the same as previous props.\n// in a perfect world this would just be a simple shallow equality check,\n// however some props are almost always passed as object/array literals (so they never ===)\n// or require special equality checks (eg. d3 scales)\n\n// default list of props to check for *deep equality* using _.isEqual\n// can be overridden by components by passing `propKeysToDeepCheck` argument\n// todo: decide whether data really belongs on this list? deep-checking data can be slow, but re-rendering is even slower\nexport const defaultPropKeysToDeepCheck = [\n 'margin', 'scaleType', 'spacing', 'domain', 'style', 'data'\n];\n\nexport default function xyPropsEqual(propsA, propsB, customKeysToDeepCheck = [], includeDefaults = true) {\n const propKeysToDeepCheck = includeDefaults ?\n defaultPropKeysToDeepCheck.concat(customKeysToDeepCheck) :\n customKeysToDeepCheck;\n\n const propKeysToSkipShallowCheck = propKeysToDeepCheck.concat('scale');\n\n const isEqual =\n // most keys just get shallow-equality checked\n shallowEqual(_.omit(propsA, propKeysToSkipShallowCheck), _.omit(propsB, propKeysToSkipShallowCheck)) &&\n // propKeysToDeepCheck get deep-equality checked using _.isEqual\n _.every(propKeysToDeepCheck, (key) => _.isEqual(propsA[key], propsB[key])) &&\n // d3 scales are special, get deep-checked using custom `scaleEqual` utility\n _.every(['x', 'y'], (key) => {\n return scaleEqual(_.get(propsA, `scale[${key}]`), _.get(propsA, `scale[${key}]`));\n });\n\n return isEqual;\n}\n\nexport function xyPropsEqualDebug(propsA, propsB, customKeysToDeepCheck = [], includeDefaults = true) {\n const propKeysToDeepCheck = includeDefaults ?\n defaultPropKeysToDeepCheck.concat(customKeysToDeepCheck) :\n customKeysToDeepCheck;\n // debug version of xyPropsEqual which console.logs, for figuring out which props are failing equality check\n // const start = performance.now();\n const propKeysToSkipShallowCheck = propKeysToDeepCheck.concat('scale');\n\n const isEqual =\n // most keys just get shallow-equality checked\n shallowEqual(_.omit(propsA, propKeysToSkipShallowCheck), _.omit(propsB, propKeysToSkipShallowCheck)) &&\n _.every(propKeysToDeepCheck, (key) => {\n const isDeepEqual = _.isEqual(propsA[key], propsB[key]);\n if(!isDeepEqual) console.log(`xyProps: ${key} not equal`);\n return isDeepEqual;\n }) &&\n _.every(['x', 'y'], (key) => {\n const isScaleEqual = scaleEqual(propsA.scale[key], propsB.scale[key]);\n if(!isScaleEqual) console.log(`xyProps: scale.${key} not equal`);\n return isScaleEqual;\n });\n\n // console.log('xyProps isEqual', isEqual);\n // console.log('took', performance.now() - start);\n return isEqual;\n}\n"]} \ No newline at end of file diff --git a/package.json b/package.json index 3f3df145..fc924026 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "dev": "webpack-dev-server --config webpack.config.base.js", "build-lib": "rm -rf lib/ && babel src --out-dir lib --source-maps", "build-docs": "BABEL_ENV=production webpack --config webpack.config.build.js", - "build-tests": "webpack --config webpack.config.test.js", - "build": "npm run build-lib && npm run build-docs && npm run build-tests", + "build": "npm run build-lib && npm run make-docs && npm run build-docs", + "make-docs": "node scripts/makeDocs.js", "serve": "python -m SimpleHTTPServer", "test": "npm run test-jsdom", "test-browser": "webpack-dev-server --config tests/browser/webpack.config.test.js",