react-native-arkit
Advanced tools
Comparing version 0.1.3 to 0.2.0
58
ARKit.js
@@ -10,2 +10,3 @@ // | ||
import React, { Component } from 'react'; | ||
import { | ||
@@ -18,4 +19,5 @@ StyleSheet, | ||
} from 'react-native'; | ||
import { parseColorWrapper } from './parseColor'; | ||
import generateId from './components/lib/generateId'; | ||
const ARKitManager = NativeModules.ARKitManager; | ||
@@ -39,2 +41,10 @@ | ||
componentDidMount() { | ||
ARKitManager.resume(); | ||
} | ||
componentWillUnmount() { | ||
ARKitManager.pause(); | ||
} | ||
render(AR = RCTARKit) { | ||
@@ -67,2 +77,3 @@ let state = null; | ||
onTrackingState={this.callback('onTrackingState')} | ||
onEvent={this._onEvent} | ||
/> | ||
@@ -96,2 +107,14 @@ {state} | ||
_onEvent = event => { | ||
let eventName = event.nativeEvent.event; | ||
if (!eventName) { | ||
return; | ||
} | ||
eventName = eventName.charAt(0).toUpperCase() + eventName.slice(1); | ||
const eventListener = this.props[`on${eventName}`]; | ||
if (eventListener) { | ||
eventListener(event.nativeEvent); | ||
} | ||
}; | ||
callback(name) { | ||
@@ -135,23 +158,13 @@ return event => { | ||
ARKit.getCameraPosition = ARKitManager.getCameraPosition; | ||
ARKit.ARHitTestResultType = ARKitManager.ARHitTestResultType; | ||
ARKit.hitTestPlanes = ARKitManager.hitTestPlanes; | ||
ARKit.snapshot = ARKitManager.snapshot; | ||
ARKit.snapshotCamera = ARKitManager.snapshotCamera; | ||
ARKit.pause = ARKitManager.pause; | ||
ARKit.resume = ARKitManager.resume; | ||
ARKit.focusScene = ARKitManager.focusScene; | ||
ARKit.addBox = parseColorWrapper(ARKitManager.addBox); | ||
ARKit.addSphere = parseColorWrapper(ARKitManager.addSphere); | ||
ARKit.addCylinder = parseColorWrapper(ARKitManager.addCylinder); | ||
ARKit.addCone = parseColorWrapper(ARKitManager.addCone); | ||
ARKit.addPyramid = parseColorWrapper(ARKitManager.addPyramid); | ||
ARKit.addTube = parseColorWrapper(ARKitManager.addTube); | ||
ARKit.addTorus = parseColorWrapper(ARKitManager.addTorus); | ||
ARKit.addCapsule = parseColorWrapper(ARKitManager.addCapsule); | ||
ARKit.addPlane = parseColorWrapper(ARKitManager.addPlane); | ||
ARKit.addText = parseColorWrapper(ARKitManager.addText); | ||
ARKit.addModel = ARKitManager.addModel; | ||
ARKit.addImage = ARKitManager.addImage; | ||
// copy all ARKitManager properties to ARKit | ||
Object.keys(ARKitManager).forEach(key => { | ||
ARKit[key] = ARKitManager[key]; | ||
}); | ||
ARKit.exportModel = presetId => { | ||
const id = presetId || generateId(); | ||
const property = { id }; | ||
return ARKitManager.exportModel(property).then(result => ({ ...result, id })); | ||
}; | ||
ARKit.propTypes = { | ||
@@ -165,3 +178,4 @@ debug: PropTypes.bool, | ||
onTapOnPlaneUsingExtent: PropTypes.func, | ||
onTapOnPlaneNoExtent: PropTypes.func | ||
onTapOnPlaneNoExtent: PropTypes.func, | ||
onEvent: PropTypes.func, | ||
}; | ||
@@ -168,0 +182,0 @@ |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARBoxManager = NativeModules.ARBoxManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARBox extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARBoxManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARBoxManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARBox.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARBox = createArComponent(NativeModules.ARBoxManager, { | ||
shape: PropTypes.shape({ | ||
@@ -50,4 +22,4 @@ width: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARBox; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARCapsuleManager = NativeModules.ARCapsuleManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARCapsule extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARCapsuleManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARCapsuleManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARCapsule.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARCapsule = createArComponent(NativeModules.ARCapsuleManager, { | ||
shape: PropTypes.shape({ | ||
@@ -48,4 +20,4 @@ capR: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARCapsule; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARConeManager = NativeModules.ARConeManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARCone extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARConeManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARConeManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARCone.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARCone = createArComponent(NativeModules.ARConeManager, { | ||
shape: PropTypes.shape({ | ||
@@ -49,4 +21,4 @@ topR: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARCone; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARCylinderManager = NativeModules.ARCylinderManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARCylinder extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARCylinderManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARCylinderManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARCylinder.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARCylinder = createArComponent(NativeModules.ARCylinderManager, { | ||
shape: PropTypes.shape({ | ||
@@ -48,4 +20,4 @@ radius: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARCylinder; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARModelManager = NativeModules.ARModelManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARModel extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARModelManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.model, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARModelManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARModel.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARModel = createArComponent(NativeModules.ARModelManager, { | ||
model: PropTypes.shape({ | ||
@@ -48,5 +20,6 @@ file: PropTypes.string, | ||
scale: PropTypes.number, | ||
alpha: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARModel; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARPlaneManager = NativeModules.ARPlaneManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARPlane extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARPlaneManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARPlaneManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARPlane.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARPlane = createArComponent(NativeModules.ARPlaneManager, { | ||
shape: PropTypes.shape({ | ||
@@ -48,4 +20,4 @@ width: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARPlane; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARPyramidManager = NativeModules.ARPyramidManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARPyramid extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARPyramidManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARPyramidManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARPyramid.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARPyramid = createArComponent(NativeModules.ARPyramidManager, { | ||
shape: PropTypes.shape({ | ||
@@ -49,4 +21,4 @@ width: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARPyramid; |
@@ -9,41 +9,13 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARSphereManager = NativeModules.ARSphereManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARSphere extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARSphereManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARSphereManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARSphere.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARSphere = createArComponent(NativeModules.ARSphereManager, { | ||
shape: PropTypes.shape({ | ||
radius: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARSphere; |
@@ -9,48 +9,9 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
import { parseColorWrapper } from '../parseColor'; | ||
const ARTextManager = NativeModules.ARTextManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARText extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
parseColorWrapper(ARTextManager.mount)({ | ||
id: this.identifier, | ||
text: this.props.text, | ||
...this.props.pos, | ||
...this.props.font, | ||
}); | ||
} | ||
componentWillReceiveProps(newProps) { | ||
parseColorWrapper(ARTextManager.mount)({ | ||
id: this.identifier, | ||
text: newProps.text, | ||
...newProps.pos, | ||
...newProps.font, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARTextManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARText.propTypes = { | ||
const ARText = createArComponent(NativeModules.ARTextManager, { | ||
text: PropTypes.string, | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
font: PropTypes.shape({ | ||
@@ -62,6 +23,5 @@ name: PropTypes.string, | ||
chamfer: PropTypes.number, | ||
color: PropTypes.string, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARText; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARTorusManager = NativeModules.ARTorusManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARTorus extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARTorusManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARTorusManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARTorus.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARTorus = createArComponent(NativeModules.ARTorusManager, { | ||
shape: PropTypes.shape({ | ||
@@ -48,4 +20,4 @@ ringR: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARTorus; |
@@ -9,36 +9,8 @@ // | ||
import PropTypes from 'prop-types'; | ||
import React, { Component } from 'react'; | ||
import { NativeModules } from 'react-native'; | ||
import id from './lib/id'; | ||
const ARTubeManager = NativeModules.ARTubeManager; | ||
import createArComponent from './lib/createArComponent'; | ||
class ARTube extends Component { | ||
identifier = null; | ||
componentWillMount() { | ||
this.identifier = this.props.id || id(); | ||
ARTubeManager.mount({ | ||
id: this.identifier, | ||
...this.props.pos, | ||
...this.props.shape, | ||
}); | ||
} | ||
componentWillUnmount() { | ||
ARTubeManager.unmount(this.identifier); | ||
} | ||
render() { | ||
return null; | ||
} | ||
} | ||
ARTube.propTypes = { | ||
pos: PropTypes.shape({ | ||
x: PropTypes.number, | ||
y: PropTypes.number, | ||
z: PropTypes.number, | ||
frame: PropTypes.string, | ||
}), | ||
const ARTube = createArComponent(NativeModules.ARTubeManager, { | ||
shape: PropTypes.shape({ | ||
@@ -49,4 +21,4 @@ innerR: PropTypes.number, | ||
}), | ||
}; | ||
}); | ||
module.exports = ARTube; |
@@ -7,3 +7,3 @@ { | ||
}, | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"description": "React Native binding for iOS ARKit", | ||
@@ -13,9 +13,3 @@ "author": "Zehao Li <qft.gtr@gmail.com>", | ||
"homepage": "https://github.com/HippoAR/react-native-arkit", | ||
"keywords": [ | ||
"react-native", | ||
"react", | ||
"native", | ||
"ARKit", | ||
"AR" | ||
], | ||
"keywords": ["react-native", "react", "native", "ARKit", "AR"], | ||
"main": "index.js", | ||
@@ -26,2 +20,3 @@ "scripts": { | ||
"dependencies": { | ||
"color": "^2.0.0", | ||
"prop-types": "^15.5.7", | ||
@@ -28,0 +23,0 @@ "react": "16.0.0-alpha.12" |
@@ -135,9 +135,13 @@ # react-native-arkit | ||
| Method Name | Arguments | Notes | ||
| Method Name | Arguments | Notes | ||
|---|---|---| | ||
| `snapshot` | | Take a screenshot (will save to Photo Library) | ||
| `getCameraPosition` | | Get the current position of the `ARCamera` | ||
| `focusScene` | | Sets the scene's position/rotation to where it was when first rendered (but now relative to your device's current position/rotation) | ||
| `snapshot` | | | Take a screenshot (will save to Photo Library) | | ||
| `snapshotCamera` | | Take a screenshot without 3d models (will save to Photo Library) | | ||
| `getCameraPosition` | | Get the current position of the `ARCamera` | | ||
| `focusScene` | | Sets the scene's position/rotation to where it was when first rendered (but now relative to your device's current position/rotation) | | ||
| `hitTestPlanes` | point, type | check if a plane has ben hit by point (`{x,y}`) with detection type (any of `ARKit.ARHitTestResultType`). See https://developer.apple.com/documentation/arkit/arhittestresulttype?language=objc for further information | | ||
| `hitTestSceneObjects` | point | check if a scene object has ben hit by point (`{x,y}`) | | ||
#### [`<ARKit.Box />`](https://developer.apple.com/documentation/scenekit/scnbox) | ||
@@ -151,2 +155,3 @@ | ||
| `shape` | `{ width, height, length, chamfer }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -161,2 +166,3 @@ #### [`<ARKit.Sphere />`](https://developer.apple.com/documentation/scenekit/scnsphere) | ||
| `shape` | `{ radius }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -171,2 +177,3 @@ #### [`<ARKit.Cylinder />`](https://developer.apple.com/documentation/scenekit/scncylinder) | ||
| `shape` | `{ radius, height }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -181,2 +188,3 @@ #### [`<ARKit.Cone />`](https://developer.apple.com/documentation/scenekit/scncone) | ||
| `shape` | `{ topR, bottomR, height }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -191,2 +199,3 @@ #### [`<ARKit.Pyramid />`](https://developer.apple.com/documentation/scenekit/scnpyramid) | ||
| `shape` | `{ width, height, length }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -201,2 +210,3 @@ #### [`<ARKit.Tube />`](https://developer.apple.com/documentation/scenekit/scntube) | ||
| `shape` | `{ innerR, outerR, height }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -211,2 +221,3 @@ #### [`<ARKit.Torus />`](https://developer.apple.com/documentation/scenekit/scntorus) | ||
| `shape` | `{ ringR, pipeR }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -221,2 +232,3 @@ #### [`<ARKit.Capsule />`](https://developer.apple.com/documentation/scenekit/scncapsule) | ||
| `shape` | `{ capR, height }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -231,2 +243,3 @@ #### [`<ARKit.Plane />`](https://developer.apple.com/documentation/scenekit/scnplane) | ||
| `shape` | `{ width, length }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -240,4 +253,5 @@ #### [`<ARKit.Text />`](https://developer.apple.com/documentation/scenekit/scntext) | ||
| `text` | `String` | | ||
| `pos` | `{ x, y, z }` | | ||
| `font` | `{ name, size, depth }` | | ||
| `pos` | `{ x, y, z, angle }` | | ||
| `font` | `{ name, size, depth, chamfer }` | | ||
| `material` | `{ color, metalness, roughness }` | | ||
@@ -254,3 +268,3 @@ | ||
| `pos` | `{ x, y, z }` | | ||
| `model` | `{ file, scale }` | | ||
| `model` | `{ file, node, scale, alpha }` | | ||
@@ -257,0 +271,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
395616
67
263
0
3
541
+ Addedcolor@^2.0.0
+ Addedcolor@2.0.1(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedcolor-string@1.9.1(transitive)
+ Addedis-arrayish@0.3.2(transitive)
+ Addedsimple-swizzle@0.2.2(transitive)