@webalternatif/js-core 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/dom.js CHANGED
@@ -8,6 +8,7 @@ var _is = require("./is.js");
8
8
  var _string = require("./string.js");
9
9
  var _traversal = require("./traversal.js");
10
10
  var _array = require("./array.js");
11
+ const cssNumber = ['animationIterationCount', 'aspectRatio', 'borderImageSlice', 'columnCount', 'flexGrow', 'flexShrink', 'fontWeight', 'gridArea', 'gridColumn', 'gridColumnEnd', 'gridColumnStart', 'gridRow', 'gridRowEnd', 'gridRowStart', 'lineHeight', 'opacity', 'order', 'orphans', 'scale', 'widows', 'zIndex', 'zoom', 'fillOpacity', 'floodOpacity', 'stopOpacity', 'strokeMiterlimit', 'strokeOpacity'];
11
12
  const isWindow = function (o) {
12
13
  return !!o && o === o.window;
13
14
  };
@@ -45,56 +46,66 @@ var _default = exports.default = {
45
46
  return this.first(this.children(el, selector));
46
47
  },
47
48
  /**
48
- * @param {Element|Document|string} refEl
49
- * @param {string} [selector='*']
50
- * @returns {NodeList}
49
+ * @param {Element|Document} refEl
50
+ * @param {string|Element|NodeList|Array<Element>} [selector]
51
+ * @returns {Element|null}
51
52
  */
52
- find(refEl, selector = '*') {
53
- if ((0, _is.isString)(refEl)) {
54
- selector = refEl;
55
- refEl = document;
56
- }
57
- try {
58
- return refEl.querySelectorAll(selector);
59
- } catch (e) {
60
- return document.querySelectorAll(':not(*)');
61
- }
53
+ findOne(refEl, selector) {
54
+ return this.find(refEl, selector)[0] ?? null;
62
55
  },
63
56
  /**
64
- * @param {Element|Document|string} refEl
65
- * @param {string} [selector='*']
66
- * @returns {Element|null}
57
+ * @param {Element|Document} refEl
58
+ * @param {string|Element|NodeList|Array<Element>} selector
59
+ * @returns {Array<Element>}
67
60
  */
68
- findOne(refEl, selector = '*') {
69
- if ((0, _is.isString)(refEl)) {
61
+ find(refEl, selector) {
62
+ if (undefined === selector) {
70
63
  selector = refEl;
71
64
  refEl = document;
72
65
  }
73
- try {
74
- return refEl.querySelector(selector);
75
- } catch (e) {
76
- return null;
66
+ if (selector instanceof Element) {
67
+ selector = [selector];
68
+ }
69
+ if ((0, _is.isArrayLike)(selector)) {
70
+ return (0, _traversal.map)(Array.from(selector), (i, el) => {
71
+ if (el instanceof Element) {
72
+ return refEl === el || refEl.contains(el) ? el : null;
73
+ }
74
+ return null;
75
+ });
77
76
  }
77
+ return Array.from(refEl.querySelectorAll(selector));
78
78
  },
79
79
  /**
80
- * @param {Element} el
80
+ * @param {Element|NodeList|Array<Element>} el
81
81
  * @param {string} className
82
- * @returns {Element}
82
+ * @returns {Element|NodeList|Array<Element>}
83
83
  */
84
84
  addClass(el, className) {
85
85
  if (!className) return el;
86
86
  const classNames = className.split(' ').map(c => c.trim()).filter(Boolean);
87
- el.classList.add(...classNames);
87
+ const elements = el instanceof Element ? [el] : Array.from(el);
88
+ elements.forEach(e => {
89
+ if (e instanceof Element) {
90
+ e.classList.add(...classNames);
91
+ }
92
+ });
88
93
  return el;
89
94
  },
90
95
  /**
91
- * @param {Element} el
92
- * @param {string} classNames
93
- * @returns {Element}
96
+ * @param {Element|NodeList|Array<Element>} el
97
+ * @param {string} className
98
+ * @returns {Element|NodeList|Array<Element>}
94
99
  */
95
- removeClass(el, classNames) {
96
- if (!classNames) return el;
97
- el.classList.remove(...classNames.split(' ').map(c => c.trim()).filter(Boolean));
100
+ removeClass(el, className) {
101
+ if (!className) return;
102
+ const classNames = className.split(' ').map(c => c.trim()).filter(Boolean);
103
+ const elements = el instanceof Element ? [el] : Array.from(el);
104
+ elements.forEach(e => {
105
+ if (e instanceof Element) {
106
+ e.classList.remove(...classNames);
107
+ }
108
+ });
98
109
  return el;
99
110
  },
100
111
  /**
@@ -104,7 +115,7 @@ var _default = exports.default = {
104
115
  * @returns {Element}
105
116
  */
106
117
  toggleClass(el, classNames, force) {
107
- (0, _traversal.each)(classNames.split(' ').map(c => c.trim()).filter(Boolean), (i, c) => el.classList.toggle(c, force));
118
+ (0, _traversal.foreach)(classNames.split(' ').map(c => c.trim()).filter(Boolean), c => el.classList.toggle(c, force));
108
119
  return el;
109
120
  },
110
121
  /**
@@ -113,39 +124,69 @@ var _default = exports.default = {
113
124
  * @returns {boolean}
114
125
  */
115
126
  hasClass(el, classNames) {
116
- return (0, _array.compareArray)([...el.classList], classNames.split(' ').map(c => c.trim()).filter(Boolean));
127
+ if (!classNames) return false;
128
+ let foundClasses = true;
129
+ (0, _traversal.foreach)(classNames.split(' ').map(c => c.trim()).filter(Boolean), c => {
130
+ if (el.classList.contains(c)) {
131
+ return true;
132
+ }
133
+ foundClasses = false;
134
+ return false;
135
+ });
136
+ return foundClasses;
117
137
  },
118
138
  /**
119
- * @param {Element} el
120
- * @param {Element} child
121
- * @returns {Element}
139
+ * @param {Node} node
140
+ * @param {...Node} children
141
+ * @returns {Node}
122
142
  */
123
- append(el, child) {
124
- el.append(child);
125
- return el;
143
+ append(node, ...children) {
144
+ node.append(...children);
145
+ return node;
126
146
  },
127
147
  /**
128
- * @param {Element} el
129
- * @param {Element} child
130
- * @returns {Element}
148
+ * @param {Node} node
149
+ * @param {...Node} children
150
+ * @returns {Node}
131
151
  */
132
- prepend(el, child) {
133
- el.prepend(child);
134
- return el;
152
+ prepend(node, ...children) {
153
+ node.prepend(...children);
154
+ return node;
135
155
  },
136
156
  /**
137
- * @param {Element} el
157
+ * @param {Element|NodeList|Array<Element>|string} els
138
158
  * @returns {void}
139
159
  */
140
- remove(el) {
141
- el.remove();
160
+ remove(...els) {
161
+ els.forEach(el => {
162
+ if (el instanceof Element) {
163
+ el.remove();
164
+ } else if (el instanceof NodeList || (0, _is.isArray)(el)) {
165
+ Array.from(el).forEach(e => e.remove());
166
+ } else {
167
+ this.remove(this.find(el));
168
+ }
169
+ });
142
170
  },
143
171
  /**
144
172
  * @param {Element} el
145
- * @param {string} [selector]
173
+ * @param {string|Element} selector
146
174
  * @returns {Element|null}
147
175
  */
148
176
  closest(el, selector) {
177
+ if (selector instanceof Element) {
178
+ if (el === selector) {
179
+ return el;
180
+ }
181
+ let parentEl = el.parentElement;
182
+ while (parentEl) {
183
+ if (parentEl === selector) {
184
+ return parentEl;
185
+ }
186
+ parentEl = parentEl.parentElement;
187
+ }
188
+ return null;
189
+ }
149
190
  return el.closest(selector);
150
191
  },
151
192
  /**
@@ -159,7 +200,7 @@ var _default = exports.default = {
159
200
  if (sibling && sibling.matches(selector)) {
160
201
  return sibling;
161
202
  }
162
- return sibling;
203
+ return null;
163
204
  },
164
205
  /**
165
206
  * @param {Element} el
@@ -206,6 +247,46 @@ var _default = exports.default = {
206
247
  }
207
248
  return siblings;
208
249
  },
250
+ /**
251
+ * @param {Element} el
252
+ * @param {Element|string} selector
253
+ * @returns {Element[]}
254
+ */
255
+ nextUntil(el, selector) {
256
+ let selectorIsElement = false;
257
+ const list = [];
258
+ if (selector instanceof Element) {
259
+ selectorIsElement = true;
260
+ }
261
+ let nextSibling = el.nextElementSibling;
262
+ while (nextSibling) {
263
+ const found = selectorIsElement ? nextSibling === selector : nextSibling.matches(selector);
264
+ if (found) break;
265
+ list.push(nextSibling);
266
+ nextSibling = nextSibling.nextElementSibling;
267
+ }
268
+ return list;
269
+ },
270
+ /**
271
+ * @param {Element} el
272
+ * @param {Element|string} selector
273
+ * @returns {Element[]}
274
+ */
275
+ prevUntil(el, selector) {
276
+ let selectorIsElement = false;
277
+ const list = [];
278
+ if (selector instanceof Element) {
279
+ selectorIsElement = true;
280
+ }
281
+ let prevSibling = el.previousElementSibling;
282
+ while (prevSibling) {
283
+ const found = selectorIsElement ? prevSibling === selector : prevSibling.matches(selector);
284
+ if (found) break;
285
+ list.push(prevSibling);
286
+ prevSibling = prevSibling.previousElementSibling;
287
+ }
288
+ return list;
289
+ },
209
290
  /**
210
291
  * @param {Element} el
211
292
  * @param {Element} wrappingElement
@@ -303,17 +384,23 @@ var _default = exports.default = {
303
384
  * @param {Element} el
304
385
  * @param {Object<string, string>|string} name
305
386
  * @param {string} [value]
306
- * @returns {Element}
387
+ * @returns {Element|DOMStringMap}
307
388
  */
308
389
  data(el, name, value) {
309
- if ((0, _is.isPlainObject)(name)) {
310
- (0, _traversal.each)(name, (k, v) => this.data(el, k, v));
390
+ if (undefined === name && undefined === value) {
391
+ return el.dataset;
392
+ }
393
+ if (webf.isPlainObject(name)) {
394
+ webf.each(name, (k, v) => this.data(el, k, v));
311
395
  return el;
312
396
  }
313
397
  const isAttr = /^data-/.test(name + '');
314
398
  const key = (0, _string.camelCase)(isAttr ? (name + '').replace(/^data-/, '') : name + '');
315
399
  if (undefined === value) return el.dataset[key];
316
- if (null === value) this.removeData(el, key);
400
+ if (null === value) {
401
+ this.removeData(el, key);
402
+ return el;
403
+ }
317
404
  el.dataset[key] = value;
318
405
  return el;
319
406
  },
@@ -323,7 +410,7 @@ var _default = exports.default = {
323
410
  * @returns {Element|*}
324
411
  */
325
412
  removeData(el, name) {
326
- const key = (name + '').replace(/^data-/, '').camelCase();
413
+ const key = (0, _string.camelCase)((name + '').replace(/^data-/, ''));
327
414
  delete el.dataset[key];
328
415
  return el;
329
416
  },
@@ -351,29 +438,27 @@ var _default = exports.default = {
351
438
  },
352
439
  /**
353
440
  * @param {HTMLElement} el
354
- * @param {Object<string, string>|string} styles
441
+ * @param {Object<string, string>|string} style
355
442
  * @param {string} [value]
356
443
  * @returns {Element}
357
444
  */
358
- css(el, styles, value) {
359
- if ((0, _is.isString)(styles)) {
445
+ css(el, style, value) {
446
+ if ((0, _is.isString)(style)) {
447
+ const prop = style.startsWith('--') ? style : (0, _string.camelCase)(style);
360
448
  if (undefined === value) {
361
- return styles.startsWith('--') ? el.style.getPropertyValue(styles) : el.style[styles];
449
+ return getStyle(el, prop);
362
450
  }
363
- if (styles.startsWith('--')) {
364
- el.style.setProperty(styles, String(value));
451
+ if (prop.startsWith('--')) {
452
+ el.style.setProperty(prop, String(value));
365
453
  } else {
366
- el.style[styles] = value;
454
+ if (typeof value === "number" && !(0, _array.inArray)(prop, cssNumber)) value += 'px';
455
+ el.style[prop] = value;
367
456
  }
368
- return el;
457
+ } else {
458
+ (0, _traversal.each)(style, (name, v) => {
459
+ this.css(el, name, v);
460
+ });
369
461
  }
370
- (0, _traversal.each)(styles, (name, v) => {
371
- if (name.startsWith('--')) {
372
- el.style.setProperty(name, String(v));
373
- } else {
374
- el.style[name] = v;
375
- }
376
- });
377
462
  return el;
378
463
  },
379
464
  /**
@@ -410,20 +495,21 @@ var _default = exports.default = {
410
495
  return nodeList?.length ? nodeList.item(0) : null;
411
496
  },
412
497
  /**
413
- * @param {NodeList} nodeList
498
+ * @param {NodeList|Array<Element>} nodeList
414
499
  * @returns {Element|null}
415
500
  */
416
501
  last(nodeList) {
417
- return nodeList.length ? nodeList.item(nodeList.length - 1) : null;
502
+ const arr = Array.from(nodeList)[0];
503
+ return arr[arr.length - 1];
418
504
  },
419
505
  /**
420
506
  * @param {string} html
421
- * @returns {Element}
507
+ * @returns {Element|null}
422
508
  */
423
509
  create(html) {
424
510
  const tpl = document.createElement('template');
425
511
  tpl.innerHTML = html.trim();
426
- return tpl.content.firstElementChild;
512
+ return tpl.content.firstElementChild ?? null;
427
513
  },
428
514
  /**
429
515
  * @param {NodeList} nodeList
@@ -462,5 +548,18 @@ var _default = exports.default = {
462
548
  el.removeChild(el.firstChild);
463
549
  }
464
550
  return el;
551
+ },
552
+ /**
553
+ * @param {Element|NodeList} el
554
+ * @param {string|Element} selector
555
+ * @return {Element[]}
556
+ */
557
+ not(el, selector) {
558
+ const elements = el instanceof Element ? [el] : Array.from(el);
559
+ const selectorIsString = webf.isString(selector);
560
+ return elements.filter(e => {
561
+ if (!(e instanceof Element)) return false;
562
+ return selectorIsString ? !e.matches(selector) : e !== selector;
563
+ });
465
564
  }
466
565
  };
package/dist/cjs/is.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isUndefined = exports.isTouchDevice = exports.isString = exports.isScalar = exports.isPlainObject = exports.isObject = exports.isInteger = exports.isInt = exports.isFunction = exports.isFloat = exports.isEventSupported = exports.isEvent = exports.isDate = exports.isBoolean = exports.isBool = exports.isArray = void 0;
6
+ exports.isUndefined = exports.isTouchDevice = exports.isString = exports.isScalar = exports.isPlainObject = exports.isObject = exports.isInteger = exports.isInt = exports.isFunction = exports.isFloat = exports.isEventSupported = exports.isEvent = exports.isDate = exports.isBoolean = exports.isBool = exports.isArrayLike = exports.isArray = void 0;
7
7
  var _array = require("./array.js");
8
8
  const isString = function (str) {
9
9
  return typeof str == 'string' || Object.prototype.toString.call(str) === '[object String]';
@@ -34,6 +34,10 @@ const isUndefined = function (v) {
34
34
  return typeof v === 'undefined';
35
35
  };
36
36
  exports.isUndefined = isUndefined;
37
+ const isArrayLike = function (o) {
38
+ return null !== o && !isString(o) && !isFunction(o) && isInt(o.length) && o.length >= 0 && Number.isFinite(o.length);
39
+ };
40
+ exports.isArrayLike = isArrayLike;
37
41
  const isArray = function (a) {
38
42
  return Array.isArray(a);
39
43
  };
@@ -7,54 +7,128 @@ exports.reduce = exports.merge = exports.map = exports.foreach = exports.extend
7
7
  var _is = require("./is.js");
8
8
  var _dom = require("./dom.js");
9
9
  var _utils = require("./utils.js");
10
+ /**
11
+ * @template T
12
+ * @typedef {Array<T> | Set<T> | Map<any, T> | Object<string, T> | string} Collection
13
+ */
14
+
15
+ /**
16
+ * Iterates over Arrays, Strings, Maps, Sets and plain Objects.
17
+ *
18
+ * The callback receives:
19
+ * (keyOrIndex, value, o, index)
20
+ *
21
+ * If the callback returns `false`, the iteration stops.
22
+ *
23
+ * @template T
24
+ * @param {Collection<T>} o
25
+ * @param {(key: number|string, value: T, o: Collection<T>, index: number) => (void|boolean)} callback
26
+ * @param {any} [context] Optional "this" binding for the callback
27
+ * @returns {typeof o} Returns the original input
28
+ */
10
29
  const each = function (o, callback, context) {
11
- const oToString = Object.prototype.toString.call(o);
12
- if (oToString === '[object Set]') {
13
- o = [...o];
14
- } else if (oToString === '[object Map]') {
15
- o = Object.fromEntries(o);
16
- }
17
- if ((0, _is.isArray)(o)) {
18
- for (let i = 0; i < o.length; i++) if (false === callback.call(context || o[i], i, o[i], o, i)) return;
19
- } else if ((0, _is.isObject)(o)) {
30
+ if ((0, _is.isPlainObject)(o)) {
20
31
  let index = -1;
21
- for (let i in o) if (o.hasOwnProperty(i) && false === callback.call(context || o[i], i, o[i], o, ++index)) return;
32
+ for (let i in o) if (o.hasOwnProperty(i) && false === callback.call(context ?? o[i], i, o[i], o, ++index)) return;
22
33
  } else if ((0, _is.isString)(o)) {
23
34
  const arr = o.split('');
24
- for (let i = 0; i < arr.length; i++) if (false === callback.call(context || arr[i], i, arr[i], o, i)) return;
35
+ for (let i = 0; i < arr.length; i++) if (false === callback.call(context ?? arr[i], i, arr[i], o, i)) return;
36
+ return o;
37
+ } else if (o instanceof Map) {
38
+ let index = 0;
39
+ for (const [key, value] of o.entries()) {
40
+ if (false === callback.call(context ?? value, key, value, o, index++)) return;
41
+ }
42
+ } else if (o instanceof Set) {
43
+ let index = 0;
44
+ for (const value of o.values()) {
45
+ if (false === callback.call(context ?? value, index, value, o, index)) return;
46
+ index++;
47
+ }
48
+ } else if ((0, _is.isArrayLike)(o)) {
49
+ o = Array.from(o);
50
+ for (let i = 0; i < o.length; i++) if (false === callback.call(context || o[i], i, o[i], o, i)) return;
25
51
  }
26
52
  return o;
27
53
  };
54
+
55
+ /**
56
+ * Same as each except that key and value are reversed in callback
57
+ *
58
+ * The callback receives:
59
+ * (value, keyOrIndex, o, index)
60
+ *
61
+ * @template T
62
+ * @param {Collection<T>} o
63
+ * @param {(value: T, key: number|string, o: Collection<T>, index: number) => (void|boolean)} callback
64
+ * @param {any} [context] Optional "this" binding for the callback
65
+ * @returns {typeof o} Returns the original input
66
+ */
28
67
  exports.each = each;
29
68
  const foreach = function (o, callback, context) {
30
69
  return each(o, (key, value, o, index) => callback.apply(context || value, [value, key, o, index]), context);
31
70
  };
71
+
72
+ /**
73
+ * Iterates over Arrays, Strings, Maps, Sets and plain Objects.
74
+ * Returns an array from the callback results.
75
+ * Values strictly equal to `null` are skipped.
76
+ * Values strictly equal to `false` stops the iteration.
77
+ *
78
+ * The callback receives:
79
+ * (keyOrIndex, value, o, index)
80
+ *
81
+ * @template T,R
82
+ * @param {Collection<T>} o
83
+ * @param {(key: number|string, value: T, o: Collection<T>, index: number) => (R|null|false)} callback
84
+ * @param {any} [context] Optional "this" binding for the callback
85
+ * @returns {Array} Returns the resulted array
86
+ */
32
87
  exports.foreach = foreach;
33
88
  const map = function (o, callback, context) {
34
89
  let results = [];
35
90
  each(o, function (index, value, o, i) {
36
91
  const response = callback.call(context, index, value, o, i);
37
- if (response !== null) {
38
- results.push(response);
39
- }
92
+ if (false === response) return false;
93
+ if (null !== response) results.push(response);
40
94
  });
41
95
  return results;
42
96
  };
97
+
98
+ /**
99
+ * Reduces a collection to a single value
100
+ *
101
+ * The reducer receives:
102
+ * (accumulator, value, index, source)
103
+ *
104
+ * @template T,R
105
+ * @param {Collection<T>} o
106
+ * @param {(accumulator: R|T, value: T, key: any, index: number, o: Collection<T>) => R} callback
107
+ * @param {R} [initialValue] la valeur initiale
108
+ * @returns {R} Returns the accumulated value
109
+ */
43
110
  exports.map = map;
44
111
  const reduce = function (o, callback, initialValue) {
45
112
  const isInitialValueDefined = !(0, _is.isUndefined)(initialValue);
46
113
  if (!(0, _utils.sizeOf)(o) && !isInitialValueDefined) {
47
114
  throw new Error('Nothing to reduce and no initial value');
48
115
  }
49
- let accumulator = !isInitialValueDefined ? map(o, (i, v) => i === 0 ? v : null)[0] : initialValue;
50
- each(o, (i, v) => {
51
- if (i === 0 && !isInitialValueDefined) {
52
- return true;
53
- }
54
- accumulator = callback(accumulator, v, i, o);
116
+ let accumulator = !isInitialValueDefined ? map(o, (key, v, o, i) => i === 0 ? v : null)[0] : initialValue;
117
+ each(o, (key, v, o, i) => {
118
+ if (i === 0 && !isInitialValueDefined) return;
119
+ accumulator = callback(accumulator, v, key, i, o);
55
120
  });
56
121
  return accumulator;
57
122
  };
123
+
124
+ /**
125
+ * Creates a shallow or deep copy of one or more objects or arrays
126
+ * If the first argument is `true`, nested plain objects are merged recursively.
127
+ *
128
+ * @template T
129
+ * @param {...(boolean|T)} args
130
+ * @returns {T} A copy of the merged result
131
+ */
58
132
  exports.reduce = reduce;
59
133
  const extend = function (...args) {
60
134
  let deep = false;
@@ -68,9 +142,9 @@ const extend = function (...args) {
68
142
  if (!(0, _is.isObject)(dest)) {
69
143
  args[0] = dest = {};
70
144
  }
71
- each(args.slice(1), (i, src) => {
145
+ foreach(args.slice(1), src => {
72
146
  if ((0, _is.isObject)(src)) {
73
- for (let name in src) {
147
+ for (const name in src) {
74
148
  if (deep && (0, _is.isPlainObject)(src[name])) {
75
149
  dest[name] = extend(true, {}, dest[name], src[name]);
76
150
  } else {
@@ -81,21 +155,39 @@ const extend = function (...args) {
81
155
  });
82
156
  return dest;
83
157
  };
158
+
159
+ /**
160
+ * Creates a deep copy of an Object or Array
161
+ *
162
+ * @template T
163
+ * @param {T} o
164
+ * @returns {T} The copy of o
165
+ */
84
166
  exports.extend = extend;
85
167
  const clone = function (o) {
86
168
  if (!(0, _is.isObject)(o) && !(0, _is.isArray)(o) || (0, _dom.isWindow)(o)) {
87
169
  return o;
88
170
  }
89
171
  const c = (0, _is.isObject)(o) ? {} : [];
90
- each(o, (i, value) => {
172
+ each(o, (key, value) => {
91
173
  if ((0, _is.isObject)(value)) {
92
- c[i] = clone(value);
174
+ c[key] = clone(value);
93
175
  } else {
94
- c[i] = value;
176
+ c[key] = value;
95
177
  }
96
178
  });
97
179
  return c;
98
180
  };
181
+
182
+ /**
183
+ * Merge multiple collections into a single array
184
+ *
185
+ * @template T
186
+ * @param {Collection<T>} first
187
+ * @param {Collection<T>} [second]
188
+ * @param {...Collection<T>} args Remaining collections to merge
189
+ * @returns {Array<T>} the resulted merged array
190
+ */
99
191
  exports.clone = clone;
100
192
  const merge = function (first, second = [], ...args) {
101
193
  const result = map(first, (i, elem) => elem);