index.esm.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /**
  2. * Flatten array, one level deep.
  3. *
  4. * @param {Array<?>} arr
  5. *
  6. * @return {Array<?>}
  7. */
  8. function flatten(arr) {
  9. return Array.prototype.concat.apply([], arr);
  10. }
  11. var nativeToString = Object.prototype.toString;
  12. var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
  13. function isUndefined(obj) {
  14. return obj === undefined;
  15. }
  16. function isDefined(obj) {
  17. return obj !== undefined;
  18. }
  19. function isNil(obj) {
  20. return obj == null;
  21. }
  22. function isArray(obj) {
  23. return nativeToString.call(obj) === '[object Array]';
  24. }
  25. function isObject(obj) {
  26. return nativeToString.call(obj) === '[object Object]';
  27. }
  28. function isNumber(obj) {
  29. return nativeToString.call(obj) === '[object Number]';
  30. }
  31. function isFunction(obj) {
  32. var tag = nativeToString.call(obj);
  33. return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object AsyncGeneratorFunction]' || tag === '[object Proxy]';
  34. }
  35. function isString(obj) {
  36. return nativeToString.call(obj) === '[object String]';
  37. }
  38. /**
  39. * Ensure collection is an array.
  40. *
  41. * @param {Object} obj
  42. */
  43. function ensureArray(obj) {
  44. if (isArray(obj)) {
  45. return;
  46. }
  47. throw new Error('must supply array');
  48. }
  49. /**
  50. * Return true, if target owns a property with the given key.
  51. *
  52. * @param {Object} target
  53. * @param {String} key
  54. *
  55. * @return {Boolean}
  56. */
  57. function has(target, key) {
  58. return nativeHasOwnProperty.call(target, key);
  59. }
  60. /**
  61. * Find element in collection.
  62. *
  63. * @param {Array|Object} collection
  64. * @param {Function|Object} matcher
  65. *
  66. * @return {Object}
  67. */
  68. function find(collection, matcher) {
  69. matcher = toMatcher(matcher);
  70. var match;
  71. forEach(collection, function (val, key) {
  72. if (matcher(val, key)) {
  73. match = val;
  74. return false;
  75. }
  76. });
  77. return match;
  78. }
  79. /**
  80. * Find element index in collection.
  81. *
  82. * @param {Array|Object} collection
  83. * @param {Function} matcher
  84. *
  85. * @return {Object}
  86. */
  87. function findIndex(collection, matcher) {
  88. matcher = toMatcher(matcher);
  89. var idx = isArray(collection) ? -1 : undefined;
  90. forEach(collection, function (val, key) {
  91. if (matcher(val, key)) {
  92. idx = key;
  93. return false;
  94. }
  95. });
  96. return idx;
  97. }
  98. /**
  99. * Find element in collection.
  100. *
  101. * @param {Array|Object} collection
  102. * @param {Function} matcher
  103. *
  104. * @return {Array} result
  105. */
  106. function filter(collection, matcher) {
  107. var result = [];
  108. forEach(collection, function (val, key) {
  109. if (matcher(val, key)) {
  110. result.push(val);
  111. }
  112. });
  113. return result;
  114. }
  115. /**
  116. * Iterate over collection; returning something
  117. * (non-undefined) will stop iteration.
  118. *
  119. * @param {Array|Object} collection
  120. * @param {Function} iterator
  121. *
  122. * @return {Object} return result that stopped the iteration
  123. */
  124. function forEach(collection, iterator) {
  125. var val, result;
  126. if (isUndefined(collection)) {
  127. return;
  128. }
  129. var convertKey = isArray(collection) ? toNum : identity;
  130. for (var key in collection) {
  131. if (has(collection, key)) {
  132. val = collection[key];
  133. result = iterator(val, convertKey(key));
  134. if (result === false) {
  135. return val;
  136. }
  137. }
  138. }
  139. }
  140. /**
  141. * Return collection without element.
  142. *
  143. * @param {Array} arr
  144. * @param {Function} matcher
  145. *
  146. * @return {Array}
  147. */
  148. function without(arr, matcher) {
  149. if (isUndefined(arr)) {
  150. return [];
  151. }
  152. ensureArray(arr);
  153. matcher = toMatcher(matcher);
  154. return arr.filter(function (el, idx) {
  155. return !matcher(el, idx);
  156. });
  157. }
  158. /**
  159. * Reduce collection, returning a single result.
  160. *
  161. * @param {Object|Array} collection
  162. * @param {Function} iterator
  163. * @param {Any} result
  164. *
  165. * @return {Any} result returned from last iterator
  166. */
  167. function reduce(collection, iterator, result) {
  168. forEach(collection, function (value, idx) {
  169. result = iterator(result, value, idx);
  170. });
  171. return result;
  172. }
  173. /**
  174. * Return true if every element in the collection
  175. * matches the criteria.
  176. *
  177. * @param {Object|Array} collection
  178. * @param {Function} matcher
  179. *
  180. * @return {Boolean}
  181. */
  182. function every(collection, matcher) {
  183. return !!reduce(collection, function (matches, val, key) {
  184. return matches && matcher(val, key);
  185. }, true);
  186. }
  187. /**
  188. * Return true if some elements in the collection
  189. * match the criteria.
  190. *
  191. * @param {Object|Array} collection
  192. * @param {Function} matcher
  193. *
  194. * @return {Boolean}
  195. */
  196. function some(collection, matcher) {
  197. return !!find(collection, matcher);
  198. }
  199. /**
  200. * Transform a collection into another collection
  201. * by piping each member through the given fn.
  202. *
  203. * @param {Object|Array} collection
  204. * @param {Function} fn
  205. *
  206. * @return {Array} transformed collection
  207. */
  208. function map(collection, fn) {
  209. var result = [];
  210. forEach(collection, function (val, key) {
  211. result.push(fn(val, key));
  212. });
  213. return result;
  214. }
  215. /**
  216. * Get the collections keys.
  217. *
  218. * @param {Object|Array} collection
  219. *
  220. * @return {Array}
  221. */
  222. function keys(collection) {
  223. return collection && Object.keys(collection) || [];
  224. }
  225. /**
  226. * Shorthand for `keys(o).length`.
  227. *
  228. * @param {Object|Array} collection
  229. *
  230. * @return {Number}
  231. */
  232. function size(collection) {
  233. return keys(collection).length;
  234. }
  235. /**
  236. * Get the values in the collection.
  237. *
  238. * @param {Object|Array} collection
  239. *
  240. * @return {Array}
  241. */
  242. function values(collection) {
  243. return map(collection, function (val) {
  244. return val;
  245. });
  246. }
  247. /**
  248. * Group collection members by attribute.
  249. *
  250. * @param {Object|Array} collection
  251. * @param {Function} extractor
  252. *
  253. * @return {Object} map with { attrValue => [ a, b, c ] }
  254. */
  255. function groupBy(collection, extractor) {
  256. var grouped = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  257. extractor = toExtractor(extractor);
  258. forEach(collection, function (val) {
  259. var discriminator = extractor(val) || '_';
  260. var group = grouped[discriminator];
  261. if (!group) {
  262. group = grouped[discriminator] = [];
  263. }
  264. group.push(val);
  265. });
  266. return grouped;
  267. }
  268. function uniqueBy(extractor) {
  269. extractor = toExtractor(extractor);
  270. var grouped = {};
  271. for (var _len = arguments.length, collections = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  272. collections[_key - 1] = arguments[_key];
  273. }
  274. forEach(collections, function (c) {
  275. return groupBy(c, extractor, grouped);
  276. });
  277. var result = map(grouped, function (val, key) {
  278. return val[0];
  279. });
  280. return result;
  281. }
  282. var unionBy = uniqueBy;
  283. /**
  284. * Sort collection by criteria.
  285. *
  286. * @param {Object|Array} collection
  287. * @param {String|Function} extractor
  288. *
  289. * @return {Array}
  290. */
  291. function sortBy(collection, extractor) {
  292. extractor = toExtractor(extractor);
  293. var sorted = [];
  294. forEach(collection, function (value, key) {
  295. var disc = extractor(value, key);
  296. var entry = {
  297. d: disc,
  298. v: value
  299. };
  300. for (var idx = 0; idx < sorted.length; idx++) {
  301. var d = sorted[idx].d;
  302. if (disc < d) {
  303. sorted.splice(idx, 0, entry);
  304. return;
  305. }
  306. } // not inserted, append (!)
  307. sorted.push(entry);
  308. });
  309. return map(sorted, function (e) {
  310. return e.v;
  311. });
  312. }
  313. /**
  314. * Create an object pattern matcher.
  315. *
  316. * @example
  317. *
  318. * const matcher = matchPattern({ id: 1 });
  319. *
  320. * let element = find(elements, matcher);
  321. *
  322. * @param {Object} pattern
  323. *
  324. * @return {Function} matcherFn
  325. */
  326. function matchPattern(pattern) {
  327. return function (el) {
  328. return every(pattern, function (val, key) {
  329. return el[key] === val;
  330. });
  331. };
  332. }
  333. function toExtractor(extractor) {
  334. return isFunction(extractor) ? extractor : function (e) {
  335. return e[extractor];
  336. };
  337. }
  338. function toMatcher(matcher) {
  339. return isFunction(matcher) ? matcher : function (e) {
  340. return e === matcher;
  341. };
  342. }
  343. function identity(arg) {
  344. return arg;
  345. }
  346. function toNum(arg) {
  347. return Number(arg);
  348. }
  349. /**
  350. * Debounce fn, calling it only once if the given time
  351. * elapsed between calls.
  352. *
  353. * Lodash-style the function exposes methods to `#clear`
  354. * and `#flush` to control internal behavior.
  355. *
  356. * @param {Function} fn
  357. * @param {Number} timeout
  358. *
  359. * @return {Function} debounced function
  360. */
  361. function debounce(fn, timeout) {
  362. var timer;
  363. var lastArgs;
  364. var lastThis;
  365. var lastNow;
  366. function fire(force) {
  367. var now = Date.now();
  368. var scheduledDiff = force ? 0 : lastNow + timeout - now;
  369. if (scheduledDiff > 0) {
  370. return schedule(scheduledDiff);
  371. }
  372. fn.apply(lastThis, lastArgs);
  373. clear();
  374. }
  375. function schedule(timeout) {
  376. timer = setTimeout(fire, timeout);
  377. }
  378. function clear() {
  379. if (timer) {
  380. clearTimeout(timer);
  381. }
  382. timer = lastNow = lastArgs = lastThis = undefined;
  383. }
  384. function flush() {
  385. if (timer) {
  386. fire(true);
  387. }
  388. clear();
  389. }
  390. function callback() {
  391. lastNow = Date.now();
  392. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  393. args[_key] = arguments[_key];
  394. }
  395. lastArgs = args;
  396. lastThis = this; // ensure an execution is scheduled
  397. if (!timer) {
  398. schedule(timeout);
  399. }
  400. }
  401. callback.flush = flush;
  402. callback.cancel = clear;
  403. return callback;
  404. }
  405. /**
  406. * Throttle fn, calling at most once
  407. * in the given interval.
  408. *
  409. * @param {Function} fn
  410. * @param {Number} interval
  411. *
  412. * @return {Function} throttled function
  413. */
  414. function throttle(fn, interval) {
  415. var throttling = false;
  416. return function () {
  417. if (throttling) {
  418. return;
  419. }
  420. fn.apply(void 0, arguments);
  421. throttling = true;
  422. setTimeout(function () {
  423. throttling = false;
  424. }, interval);
  425. };
  426. }
  427. /**
  428. * Bind function against target <this>.
  429. *
  430. * @param {Function} fn
  431. * @param {Object} target
  432. *
  433. * @return {Function} bound function
  434. */
  435. function bind(fn, target) {
  436. return fn.bind(target);
  437. }
  438. function _typeof(obj) {
  439. "@babel/helpers - typeof";
  440. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  441. _typeof = function (obj) {
  442. return typeof obj;
  443. };
  444. } else {
  445. _typeof = function (obj) {
  446. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  447. };
  448. }
  449. return _typeof(obj);
  450. }
  451. function _extends() {
  452. _extends = Object.assign || function (target) {
  453. for (var i = 1; i < arguments.length; i++) {
  454. var source = arguments[i];
  455. for (var key in source) {
  456. if (Object.prototype.hasOwnProperty.call(source, key)) {
  457. target[key] = source[key];
  458. }
  459. }
  460. }
  461. return target;
  462. };
  463. return _extends.apply(this, arguments);
  464. }
  465. /**
  466. * Convenience wrapper for `Object.assign`.
  467. *
  468. * @param {Object} target
  469. * @param {...Object} others
  470. *
  471. * @return {Object} the target
  472. */
  473. function assign(target) {
  474. for (var _len = arguments.length, others = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  475. others[_key - 1] = arguments[_key];
  476. }
  477. return _extends.apply(void 0, [target].concat(others));
  478. }
  479. /**
  480. * Sets a nested property of a given object to the specified value.
  481. *
  482. * This mutates the object and returns it.
  483. *
  484. * @param {Object} target The target of the set operation.
  485. * @param {(string|number)[]} path The path to the nested value.
  486. * @param {any} value The value to set.
  487. */
  488. function set(target, path, value) {
  489. var currentTarget = target;
  490. forEach(path, function (key, idx) {
  491. if (typeof key !== 'number' && typeof key !== 'string') {
  492. throw new Error('illegal key type: ' + _typeof(key) + '. Key should be of type number or string.');
  493. }
  494. if (key === 'constructor') {
  495. throw new Error('illegal key: constructor');
  496. }
  497. if (key === '__proto__') {
  498. throw new Error('illegal key: __proto__');
  499. }
  500. var nextKey = path[idx + 1];
  501. var nextTarget = currentTarget[key];
  502. if (isDefined(nextKey) && isNil(nextTarget)) {
  503. nextTarget = currentTarget[key] = isNaN(+nextKey) ? {} : [];
  504. }
  505. if (isUndefined(nextKey)) {
  506. if (isUndefined(value)) {
  507. delete currentTarget[key];
  508. } else {
  509. currentTarget[key] = value;
  510. }
  511. } else {
  512. currentTarget = nextTarget;
  513. }
  514. });
  515. return target;
  516. }
  517. /**
  518. * Gets a nested property of a given object.
  519. *
  520. * @param {Object} target The target of the get operation.
  521. * @param {(string|number)[]} path The path to the nested value.
  522. * @param {any} [defaultValue] The value to return if no value exists.
  523. */
  524. function get(target, path, defaultValue) {
  525. var currentTarget = target;
  526. forEach(path, function (key) {
  527. // accessing nil property yields <undefined>
  528. if (isNil(currentTarget)) {
  529. currentTarget = undefined;
  530. return false;
  531. }
  532. currentTarget = currentTarget[key];
  533. });
  534. return isUndefined(currentTarget) ? defaultValue : currentTarget;
  535. }
  536. /**
  537. * Pick given properties from the target object.
  538. *
  539. * @param {Object} target
  540. * @param {Array} properties
  541. *
  542. * @return {Object} target
  543. */
  544. function pick(target, properties) {
  545. var result = {};
  546. var obj = Object(target);
  547. forEach(properties, function (prop) {
  548. if (prop in obj) {
  549. result[prop] = target[prop];
  550. }
  551. });
  552. return result;
  553. }
  554. /**
  555. * Pick all target properties, excluding the given ones.
  556. *
  557. * @param {Object} target
  558. * @param {Array} properties
  559. *
  560. * @return {Object} target
  561. */
  562. function omit(target, properties) {
  563. var result = {};
  564. var obj = Object(target);
  565. forEach(obj, function (prop, key) {
  566. if (properties.indexOf(key) === -1) {
  567. result[key] = prop;
  568. }
  569. });
  570. return result;
  571. }
  572. /**
  573. * Recursively merge `...sources` into given target.
  574. *
  575. * Does support merging objects; does not support merging arrays.
  576. *
  577. * @param {Object} target
  578. * @param {...Object} sources
  579. *
  580. * @return {Object} the target
  581. */
  582. function merge(target) {
  583. for (var _len2 = arguments.length, sources = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  584. sources[_key2 - 1] = arguments[_key2];
  585. }
  586. if (!sources.length) {
  587. return target;
  588. }
  589. forEach(sources, function (source) {
  590. // skip non-obj sources, i.e. null
  591. if (!source || !isObject(source)) {
  592. return;
  593. }
  594. forEach(source, function (sourceVal, key) {
  595. if (key === '__proto__') {
  596. return;
  597. }
  598. var targetVal = target[key];
  599. if (isObject(sourceVal)) {
  600. if (!isObject(targetVal)) {
  601. // override target[key] with object
  602. targetVal = {};
  603. }
  604. target[key] = merge(targetVal, sourceVal);
  605. } else {
  606. target[key] = sourceVal;
  607. }
  608. });
  609. });
  610. return target;
  611. }
  612. export { assign, bind, debounce, ensureArray, every, filter, find, findIndex, flatten, forEach, get, groupBy, has, isArray, isDefined, isFunction, isNil, isNumber, isObject, isString, isUndefined, keys, map, matchPattern, merge, omit, pick, reduce, set, size, some, sortBy, throttle, unionBy, uniqueBy, values, without };