Comparing version 1.0.0 to 1.0.1
@@ -74,3 +74,4 @@ 'use strict'; | ||
var statusClassNames = function statusClassNames(_ref3) { | ||
var As = _ref3.As, | ||
var updates = _ref3.updates, | ||
forceUpdate = _ref3.forceUpdate, | ||
leaving = _ref3.leaving, | ||
@@ -87,3 +88,3 @@ _ref3$entering = _ref3.entering, | ||
children = _ref3.children, | ||
props = _objectWithoutProperties(_ref3, ['As', 'leaving', 'entering', 'entering_reverse', 'exiting', 'exiting_reverse', 'reverse', 'children']); | ||
props = _objectWithoutProperties(_ref3, ['updates', 'forceUpdate', 'leaving', 'entering', 'entering_reverse', 'exiting', 'exiting_reverse', 'reverse', 'children']); | ||
@@ -97,2 +98,2 @@ return _extends({}, props, { | ||
exports.default = (0, _recompose.compose)(_shared.triggerForceUpdates, withTransitionStates, (0, _recompose.withPropsOnChange)(diffChildren, _shared.zipLeaving), (0, _recompose.mapProps)(statusClassNames)); | ||
exports.default = (0, _recompose.compose)(_shared.triggerForceUpdates, withTransitionStates, (0, _recompose.withPropsOnChange)(diffChildren, _shared.zipLeaving), (0, _recompose.mapProps)(statusClassNames), _shared.cleanProps); |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.Wrapper = exports.zipLeaving = exports.nextReducer = exports.triggerForceUpdates = undefined; | ||
exports.Wrapper = exports.cleanProps = exports.zipLeaving = exports.nextReducer = exports.triggerForceUpdates = undefined; | ||
@@ -19,3 +19,3 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } | ||
@@ -25,2 +25,3 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var values = Object.values; | ||
var max = Math.max; | ||
var triggerForceUpdates = exports.triggerForceUpdates = (0, _recompose.withStateHandlers)({ updates: 0 }, { | ||
@@ -39,2 +40,24 @@ forceUpdate: function forceUpdate(_ref) { | ||
var iter = function iter(limit, fn) { | ||
for (var i = 0; i <= limit; i++) { | ||
fn(i); | ||
} | ||
}; | ||
var zip = function zip(into, first, second) { | ||
return function (i) { | ||
first[i] && into.push(first[i]); | ||
second[i] && into.push(second[i]); | ||
}; | ||
}; | ||
var nextFreeIndex = function nextFreeIndex(map, index) { | ||
var nextSafeIndex = -1; | ||
var count = 1; | ||
while (nextSafeIndex < 0) { | ||
nextSafeIndex = !map[index] ? index : !map[index + count++] ? index + count : nextSafeIndex; | ||
} | ||
return nextSafeIndex; | ||
}; | ||
var zipLeaving = exports.zipLeaving = function zipLeaving(_ref2) { | ||
@@ -44,23 +67,55 @@ var leaving = _ref2.leaving, | ||
var leavingMap = values(leaving()).reduce(function (acc, _ref3) { | ||
var child = _ref3.child, | ||
index = _ref3.index; | ||
return _extends({}, acc, _defineProperty({}, index, child)); | ||
var currentChildren = _react.Children.toArray(children); | ||
var allChildren = []; | ||
var currentKeys = currentChildren.map(function (_ref3) { | ||
var key = _ref3.key; | ||
return key; | ||
}); | ||
var maxIndex = currentChildren.length; | ||
var offset = 0; | ||
var leavingMap = values(leaving()).reduce(function (acc, _ref4) { | ||
var child = _ref4.child, | ||
index = _ref4.index; | ||
if (currentKeys.includes(child.key)) return acc; | ||
var insertAt = nextFreeIndex(acc, index + offset); | ||
maxIndex = max(insertAt, maxIndex); | ||
offset = insertAt - index; | ||
return _extends({}, acc, _defineProperty({}, insertAt, child)); | ||
}, {}); | ||
iter(maxIndex, zip(allChildren, leavingMap, currentChildren)); | ||
return { | ||
children: _react.Children.toArray(children).reduce(function (acc, child, i) { | ||
return [].concat(_toConsumableArray(acc), [leavingMap[i], child]); | ||
}, []).filter(Boolean) | ||
children: allChildren | ||
}; | ||
}; | ||
var Wrapper = exports.Wrapper = function Wrapper(_ref4) { | ||
var _ref4$As = _ref4.As, | ||
As = _ref4$As === undefined ? _react2.default.Fragment || 'div' : _ref4$As, | ||
children = _ref4.children; | ||
var cleanProps = (0, _recompose.mapProps)(function (_ref5) { | ||
var updates = _ref5.updates, | ||
forceUpdate = _ref5.forceUpdate, | ||
setLeaving = _ref5.setLeaving, | ||
setLeft = _ref5.setLeft, | ||
setJustEntered = _ref5.setJustEntered, | ||
props = _objectWithoutProperties(_ref5, ['updates', 'forceUpdate', 'setLeaving', 'setLeft', 'setJustEntered']); | ||
return props; | ||
}); | ||
exports.cleanProps = cleanProps; | ||
var Wrapper = function Wrapper(_ref6) { | ||
var _ref6$As = _ref6.As, | ||
As = _ref6$As === undefined ? _react2.default.Fragment || 'div' : _ref6$As, | ||
children = _ref6.children, | ||
props = _objectWithoutProperties(_ref6, ['As', 'children']); | ||
return _react2.default.createElement( | ||
As, | ||
null, | ||
props, | ||
children | ||
); | ||
}; | ||
}; | ||
exports.Wrapper = Wrapper; |
@@ -101,3 +101,5 @@ 'use strict'; | ||
var statusClassNames = function statusClassNames(_ref4) { | ||
var leaving = _ref4.leaving, | ||
var updates = _ref4.updates, | ||
forceUpdate = _ref4.forceUpdate, | ||
leaving = _ref4.leaving, | ||
justEntered = _ref4.justEntered, | ||
@@ -112,3 +114,3 @@ _ref4$before_enter = _ref4.before_enter, | ||
children = _ref4.children, | ||
props = _objectWithoutProperties(_ref4, ['leaving', 'justEntered', 'before_enter', 'entered', 'after_exit', 'reverse', 'children']); | ||
props = _objectWithoutProperties(_ref4, ['updates', 'forceUpdate', 'leaving', 'justEntered', 'before_enter', 'entered', 'after_exit', 'reverse', 'children']); | ||
@@ -122,2 +124,2 @@ return _extends({}, props, { | ||
exports.default = (0, _recompose.compose)(_shared.triggerForceUpdates, withTransitionStates, (0, _recompose.withPropsOnChange)(diffChildren, _shared.zipLeaving), (0, _recompose.mapProps)(statusClassNames)); | ||
exports.default = (0, _recompose.compose)(_shared.triggerForceUpdates, withTransitionStates, (0, _recompose.withPropsOnChange)(diffChildren, _shared.zipLeaving), (0, _recompose.mapProps)(statusClassNames), _shared.cleanProps); |
{ | ||
"name": "niflheim", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Painlessly animate mounting/unmounting React components", | ||
@@ -38,2 +38,4 @@ "repository": "https://github.com/benoneal/niflheim", | ||
"classnames": "^2.2.5", | ||
"enzyme": "^3.3.0", | ||
"enzyme-adapter-react-16": "^1.1.1", | ||
"moize": "^4.0.4", | ||
@@ -40,0 +42,0 @@ "react": "^16.2.0", |
@@ -8,3 +8,4 @@ import {Children, cloneElement} from 'react' | ||
nextReducer, | ||
zipLeaving | ||
zipLeaving, | ||
cleanProps | ||
} from './shared' | ||
@@ -50,3 +51,5 @@ | ||
const statusClassNames = ({ | ||
As, | ||
updates, | ||
forceUpdate, | ||
leaving, | ||
@@ -75,3 +78,4 @@ | ||
withPropsOnChange(diffChildren, zipLeaving), | ||
mapProps(statusClassNames) | ||
mapProps(statusClassNames), | ||
cleanProps | ||
) |
import React, {Children} from 'react' | ||
import {withStateHandlers} from 'recompose' | ||
import {withStateHandlers, mapProps} from 'recompose' | ||
const {values} = Object | ||
const {max} = Math | ||
@@ -12,2 +13,26 @@ export const triggerForceUpdates = withStateHandlers({updates: 0}, { | ||
const iter = (limit, fn) => { | ||
for (let i = 0; i <= limit; i++) { | ||
fn(i) | ||
} | ||
} | ||
const zip = (into, first, second) => i => { | ||
first[i] && into.push(first[i]) | ||
second[i] && into.push(second[i]) | ||
} | ||
const nextFreeIndex = (map, index) => { | ||
let nextSafeIndex = -1 | ||
let count = 1 | ||
while (nextSafeIndex < 0) { | ||
nextSafeIndex = !map[index] | ||
? index | ||
: !map[index + count++] | ||
? index + count | ||
: nextSafeIndex | ||
} | ||
return nextSafeIndex | ||
} | ||
export const zipLeaving = ({ | ||
@@ -17,12 +42,35 @@ leaving, | ||
}) => { | ||
const leavingMap = values(leaving()).reduce((acc, {child, index}) => ({...acc, [index]: child}), {}) | ||
const currentChildren = Children.toArray(children) | ||
const allChildren = [] | ||
const currentKeys = currentChildren.map(({key}) => key) | ||
let maxIndex = currentChildren.length | ||
let offset = 0 | ||
const leavingMap = values(leaving()).reduce((acc, {child, index}) => { | ||
if (currentKeys.includes(child.key)) return acc | ||
const insertAt = nextFreeIndex(acc, index + offset) | ||
maxIndex = max(insertAt, maxIndex) | ||
offset = insertAt - index | ||
return ({...acc, [insertAt]: child}) | ||
}, {}) | ||
iter(maxIndex, zip(allChildren, leavingMap, currentChildren)) | ||
return { | ||
children: Children.toArray(children).reduce((acc, child, i) => [ | ||
...acc, | ||
leavingMap[i], | ||
child | ||
], []).filter(Boolean) | ||
children: allChildren | ||
} | ||
} | ||
export const Wrapper = ({As = React.Fragment || 'div', children}) => <As>{children}</As> | ||
export const cleanProps = mapProps(({ | ||
updates, | ||
forceUpdate, | ||
setLeaving, | ||
setLeft, | ||
setJustEntered, | ||
...props | ||
}) => props) | ||
export const Wrapper = ({As = React.Fragment || 'div', children, ...props}) => | ||
<As {...props}>{children}</As> |
@@ -8,3 +8,4 @@ import {Children, cloneElement} from 'react' | ||
nextReducer, | ||
zipLeaving | ||
zipLeaving, | ||
cleanProps | ||
} from './shared' | ||
@@ -67,2 +68,5 @@ | ||
const statusClassNames = ({ | ||
updates, | ||
forceUpdate, | ||
leaving, | ||
@@ -93,3 +97,4 @@ justEntered, | ||
withPropsOnChange(diffChildren, zipLeaving), | ||
mapProps(statusClassNames) | ||
mapProps(statusClassNames), | ||
cleanProps | ||
) |
import React from 'react' | ||
import {renderToString} from 'react-dom/server' | ||
import {describe, it} from 'mocha' | ||
import {mount} from 'enzyme' | ||
import assert from 'assert' | ||
import {Animated, Transitioned} from '../src' | ||
const subject = (Comp, items) => renderToString( | ||
const compString = (Comp, items) => renderToString( | ||
<Comp> | ||
@@ -13,11 +14,57 @@ {items.map(x => <div key={x} className={`test_${x}`}>{x}</div>)} | ||
// Enzyme does not support Fragments, so rendering wrapper as div to pass tests | ||
const createWrapper = (Comp, items) => class TestWrapper extends React.Component { | ||
state = {items} | ||
render = () => ( | ||
<Comp As={'span'}> | ||
{this.state.items.map(x => <div key={x} className={`test_${x}`}>{x}</div>)} | ||
</Comp> | ||
) | ||
} | ||
const compMounted = (Comp, items) => { | ||
const Wrapper = createWrapper(Comp, items) | ||
return mount(<Wrapper />) | ||
} | ||
describe('Niflheim', () => { | ||
it('Animated works', () => { | ||
const html = subject(Animated, ['a', 'b', 'c']) | ||
assert(html === '<div class="test_a entering">a</div><div class="test_b entering">b</div><div class="test_c entering">c</div>') | ||
describe('Animated', () => { | ||
it('works', () => { | ||
const html = compString(Animated, ['a', 'b', 'c']) | ||
assert(html === '<div class="test_a entering">a</div><div class="test_b entering">b</div><div class="test_c entering">c</div>') | ||
}) | ||
it('renders entering and exiting components', () => { | ||
const wrapper = compMounted(Animated, ['a', 'b', 'c']) | ||
assert(wrapper.html() === '<span><div class="test_a entering">a</div><div class="test_b entering">b</div><div class="test_c entering">c</div></span>') | ||
wrapper.setState({items: ['a', 'c']}) | ||
assert(wrapper.html() === '<span><div class="test_a entering">a</div><div class="test_b exiting">b</div><div class="test_c entering">c</div></span>') | ||
wrapper.setState({items: ['a', 'c', 'd']}) | ||
assert(wrapper.html() === '<span><div class="test_a entering">a</div><div class="test_b exiting">b</div><div class="test_c entering">c</div><div class="test_d entering">d</div></span>') | ||
wrapper.setState({items: []}) | ||
assert(wrapper.html() === '<span><div class="test_a exiting">a</div><div class="test_b exiting">b</div><div class="test_c exiting">c</div><div class="test_d exiting">d</div></span>') | ||
}) | ||
}) | ||
it('Transitioned works', () => { | ||
const html = subject(Transitioned, ['a', 'b', 'c']) | ||
assert(html === '<div class="test_a entered">a</div><div class="test_b entered">b</div><div class="test_c entered">c</div>') | ||
describe('Transitioned', () => { | ||
it('works', () => { | ||
const html = compString(Transitioned, ['a', 'b', 'c']) | ||
assert(html === '<div class="test_a entered">a</div><div class="test_b entered">b</div><div class="test_c entered">c</div>') | ||
}) | ||
it('renders entering and exiting components', () => { | ||
const wrapper = compMounted(Transitioned, ['a', 'b', 'c']) | ||
assert(wrapper.html() === '<span><div class="test_a entered">a</div><div class="test_b entered">b</div><div class="test_c entered">c</div></span>') | ||
wrapper.setState({items: ['a', 'c']}) | ||
assert(wrapper.html() === '<span><div class="test_a entered">a</div><div class="test_b after_exit">b</div><div class="test_c entered">c</div></span>') | ||
wrapper.setState({items: ['a', 'c', 'd']}) | ||
assert(wrapper.html() === '<span><div class="test_a entered">a</div><div class="test_b after_exit">b</div><div class="test_c entered">c</div><div class="test_d before_enter">d</div></span>') | ||
wrapper.setState({items: []}) | ||
assert(wrapper.html() === '<span><div class="test_a after_exit">a</div><div class="test_b after_exit">b</div><div class="test_c after_exit">c</div><div class="test_d after_exit">d</div></span>') | ||
}) | ||
}) | ||
}) |
process.env.NODE_ENV = 'test' | ||
require('babel-register')() | ||
var jsdom = require('jsdom').jsdom | ||
var enzyme = require('enzyme') | ||
var Adapter = require('enzyme-adapter-react-16') | ||
var exposedProperties = ['window', 'navigator', 'document'] | ||
global.document = jsdom('') | ||
global.navigator = { userAgent: 'node.js' } | ||
global.window = document.defaultView | ||
enzyme.configure({adapter: new Adapter()}) | ||
Object.keys(document.defaultView).forEach((property) => { | ||
@@ -9,0 +13,0 @@ if (typeof global[property] === 'undefined') { |
27640
575
6
+ Addedenzyme@^3.3.0
+ Addedairbnb-prop-types@2.16.0(transitive)
+ Addedarray-buffer-byte-length@1.0.2(transitive)
+ Addedarray.prototype.filter@1.0.4(transitive)
+ Addedarray.prototype.find@2.2.3(transitive)
+ Addedarray.prototype.flat@1.3.3(transitive)
+ Addedarraybuffer.prototype.slice@1.0.4(transitive)
+ Addedasync-function@1.0.0(transitive)
+ Addedavailable-typed-arrays@1.0.7(transitive)
+ Addedboolbase@1.0.0(transitive)
+ Addedcall-bind@1.0.8(transitive)
+ Addedcall-bind-apply-helpers@1.0.1(transitive)
+ Addedcall-bound@1.0.3(transitive)
+ Addedcheerio@1.0.0(transitive)
+ Addedcheerio-select@2.1.0(transitive)
+ Addedcommander@2.20.3(transitive)
+ Addedcss-select@5.1.0(transitive)
+ Addedcss-what@6.1.0(transitive)
+ Addeddata-view-buffer@1.0.2(transitive)
+ Addeddata-view-byte-length@1.0.2(transitive)
+ Addeddata-view-byte-offset@1.0.1(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddefine-properties@1.2.1(transitive)
+ Addeddiscontinuous-range@1.0.0(transitive)
+ Addeddom-serializer@2.0.0(transitive)
+ Addeddomelementtype@2.3.0(transitive)
+ Addeddomhandler@5.0.3(transitive)
+ Addeddomutils@3.2.2(transitive)
+ Addeddunder-proto@1.0.1(transitive)
+ Addedencoding-sniffer@0.2.0(transitive)
+ Addedentities@4.5.0(transitive)
+ Addedenzyme@3.11.0(transitive)
+ Addedenzyme-adapter-react-16@1.15.8(transitive)
+ Addedenzyme-adapter-utils@1.14.2(transitive)
+ Addedenzyme-shallow-equal@1.0.7(transitive)
+ Addedes-abstract@1.23.9(transitive)
+ Addedes-array-method-boxes-properly@1.0.0(transitive)
+ Addedes-define-property@1.0.1(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-object-atoms@1.1.1(transitive)
+ Addedes-set-tostringtag@2.1.0(transitive)
+ Addedes-shim-unscopables@1.0.2(transitive)
+ Addedes-to-primitive@1.3.0(transitive)
+ Addedfor-each@0.3.4(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedfunction.prototype.name@1.1.8(transitive)
+ Addedfunctions-have-names@1.2.3(transitive)
+ Addedget-intrinsic@1.2.7(transitive)
+ Addedget-proto@1.0.1(transitive)
+ Addedget-symbol-description@1.1.0(transitive)
+ Addedglobalthis@1.0.4(transitive)
+ Addedgopd@1.2.0(transitive)
+ Addedhas@1.0.4(transitive)
+ Addedhas-bigints@1.1.0(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.2.0(transitive)
+ Addedhas-symbols@1.1.0(transitive)
+ Addedhas-tostringtag@1.0.2(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedhtml-element-map@1.3.1(transitive)
+ Addedhtmlparser2@9.1.0(transitive)
+ Addedinternal-slot@1.1.0(transitive)
+ Addedis-array-buffer@3.0.5(transitive)
+ Addedis-async-function@2.1.1(transitive)
+ Addedis-bigint@1.1.0(transitive)
+ Addedis-boolean-object@1.2.1(transitive)
+ Addedis-callable@1.2.7(transitive)
+ Addedis-data-view@1.0.2(transitive)
+ Addedis-date-object@1.1.0(transitive)
+ Addedis-finalizationregistry@1.1.1(transitive)
+ Addedis-generator-function@1.1.0(transitive)
+ Addedis-map@2.0.3(transitive)
+ Addedis-number-object@1.1.1(transitive)
+ Addedis-regex@1.2.1(transitive)
+ Addedis-set@2.0.3(transitive)
+ Addedis-shared-array-buffer@1.0.4(transitive)
+ Addedis-string@1.1.1(transitive)
+ Addedis-subset@0.1.1(transitive)
+ Addedis-symbol@1.1.1(transitive)
+ Addedis-typed-array@1.1.15(transitive)
+ Addedis-weakmap@2.0.2(transitive)
+ Addedis-weakref@1.1.0(transitive)
+ Addedis-weakset@2.0.4(transitive)
+ Addedisarray@2.0.5(transitive)
+ Addedlodash.escape@4.0.1(transitive)
+ Addedlodash.flattendeep@4.4.0(transitive)
+ Addedlodash.isequal@4.5.0(transitive)
+ Addedmath-intrinsics@1.1.0(transitive)
+ Addedmoo@0.5.2(transitive)
+ Addednearley@2.20.1(transitive)
+ Addednth-check@2.1.1(transitive)
+ Addedobject-inspect@1.13.3(transitive)
+ Addedobject-is@1.1.6(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedobject.assign@4.1.7(transitive)
+ Addedobject.entries@1.1.8(transitive)
+ Addedobject.fromentries@2.0.8(transitive)
+ Addedobject.values@1.2.1(transitive)
+ Addedown-keys@1.0.1(transitive)
+ Addedparse5@7.2.1(transitive)
+ Addedparse5-htmlparser2-tree-adapter@7.1.0(transitive)
+ Addedparse5-parser-stream@7.1.2(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedpossible-typed-array-names@1.0.0(transitive)
+ Addedprop-types-exact@1.2.7(transitive)
+ Addedraf@3.4.1(transitive)
+ Addedrailroad-diagrams@1.0.0(transitive)
+ Addedrandexp@0.4.6(transitive)
+ Addedreact-dom@16.14.0(transitive)
+ Addedreact-test-renderer@16.14.0(transitive)
+ Addedreflect.getprototypeof@1.0.10(transitive)
+ Addedregexp.prototype.flags@1.5.4(transitive)
+ Addedret@0.1.15(transitive)
+ Addedrst-selector-parser@2.2.3(transitive)
+ Addedsafe-array-concat@1.1.3(transitive)
+ Addedsafe-push-apply@1.0.0(transitive)
+ Addedsafe-regex-test@1.1.0(transitive)
+ Addedscheduler@0.19.1(transitive)
+ Addedsemver@5.7.26.3.1(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedset-function-name@2.0.2(transitive)
+ Addedset-proto@1.0.0(transitive)
+ Addedside-channel@1.1.0(transitive)
+ Addedside-channel-list@1.0.0(transitive)
+ Addedside-channel-map@1.0.1(transitive)
+ Addedside-channel-weakmap@1.0.2(transitive)
+ Addedstring.prototype.trim@1.2.10(transitive)
+ Addedstring.prototype.trimend@1.0.9(transitive)
+ Addedstring.prototype.trimstart@1.0.8(transitive)
+ Addedtyped-array-buffer@1.0.3(transitive)
+ Addedtyped-array-byte-length@1.0.3(transitive)
+ Addedtyped-array-byte-offset@1.0.4(transitive)
+ Addedtyped-array-length@1.0.7(transitive)
+ Addedunbox-primitive@1.1.0(transitive)
+ Addedundici@6.21.1(transitive)
+ Addedwhatwg-encoding@3.1.1(transitive)
+ Addedwhatwg-mimetype@4.0.0(transitive)
+ Addedwhich-boxed-primitive@1.1.1(transitive)
+ Addedwhich-builtin-type@1.2.1(transitive)
+ Addedwhich-collection@1.0.2(transitive)
+ Addedwhich-typed-array@1.1.18(transitive)