Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-native-hotspot

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-hotspot - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

.eslintrc.js

119

example/example.js

@@ -1,71 +0,64 @@

import React, { Component } from "react";
import {
Alert,
Button,
ScrollView,
StyleSheet,
Text,
View
} from "react-native";
import { RNHotspot, RNHotspotHelper } from "react-native-hotspot";
import React, { Component } from 'react';
import { Alert, Button, ScrollView, StyleSheet, Text, View } from 'react-native';
import { RNHotspot, RNHotspotHelper } from 'react-native-hotspot';
export default class App extends Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
// in your screen's constructor, use the helper with an array of onPress actions you want your hotspots to trigger
this.componentRefs = RNHotspotHelper([
() => {
Alert.alert(null, "This button does this thing.");
},
() => {
Alert.alert(null, "This button does other thing.");
}
]);
}
// in your screen's constructor, use the helper with an array of onPress actions you want your hotspots to trigger
this.componentRefs = RNHotspotHelper([
() => {
Alert.alert(null, 'This button does this thing.');
},
() => {
Alert.alert(null, 'This button does other thing.');
},
]);
}
render() {
return (
<ScrollView style={{ flex: 1 }}>
// drop the component below the outer wrapping parent of your screen
<RNHotspot componentRefs={this.componentRefs} />
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<View style={{ marginVertical: 100 }}>
// expose the refs in the same order as the array definied above
<Button
title="Button #1"
onPress={() => {}}
ref={this.componentRefs[0].ref}
/>
</View>
<View style={{ marginVertical: 200 }}>
<Button
title="Button #2"
onPress={() => {}}
ref={this.componentRefs[1].ref}
/>
</View>
</View>
</ScrollView>
);
}
render() {
return (
<ScrollView style={{ flex: 1 }}>
{/* drop the component below the outer wrapping parent of your screen */}
<RNHotspot componentRefs={this.componentRefs} />
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<View style={{ marginVertical: 100 }}>
{/* expose the refs in the same order as the array definied above */}
<Button
title="Button #1"
onPress={() => {}}
ref={this.componentRefs[0].ref}
/>
</View>
<View style={{ marginVertical: 200 }}>
<Button
title="Button #2"
onPress={() => {}}
ref={this.componentRefs[1].ref}
/>
</View>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#F5FCFF"
},
welcome: {
marginTop: 50,
fontSize: 20,
textAlign: "center",
marginBottom: 100
},
instructions: {
textAlign: "center",
color: "#333333",
marginBottom: 5
}
container: {
backgroundColor: '#F5FCFF',
},
welcome: {
marginTop: 50,
fontSize: 20,
textAlign: 'center',
marginBottom: 100,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
{
"name": "react-native-hotspot",
"version": "0.0.2",
"description": "A React Native component that displays hotspots over desired components to help lead your users through an onboarding flow or direct them towards new UI elements",
"license": "MIT",
"author": "Michael Lefkowitz <lefkowitz.michael@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/lawnstarter/react-native-hotspot.git"
},
"main": "src/index.js",
"keywords": [
"hotspot",
"tutorial",
"onboarding",
"react",
"react-native",
"react native",
"expo"
],
"devDependencies": {
"react": "16.6.1",
"react-native": "0.57.5"
}
"name": "react-native-hotspot",
"version": "0.0.3",
"description": "A React Native component that displays hotspots over desired components to help lead your users through an onboarding flow or direct them towards new UI elements",
"license": "MIT",
"author": "Michael Lefkowitz <lefkowitz.michael@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/lawnstarter/react-native-hotspot.git"
},
"main": "src/index.js",
"keywords": [
"hotspot",
"tutorial",
"onboarding",
"react",
"react-native",
"react native",
"expo"
],
"devDependencies": {
"eslint-config-ls-react": "https://github.com/lawnstarter/eslint-config-ls-react#2.0.3",
"husky": "^0.14.3",
"prettier": "^1.15.2",
"pretty-quick": "^1.8.0",
"prop-types": "^15.6.2",
"react": "16.6.1",
"react-native": "0.57.5"
},
"scripts": {
"precommit": "pretty-quick --staged",
"prepush": "echo \"---Running ESLint---\" && eslint src/**",
"prettier:debug-check": "prettier --config ./.prettierrc.js --debug-check \"{src,test}/**/*.js\"",
"preprettier:all": "yarn run prettier:debug-check",
"prettier:all": "prettier --config ./.prettierrc.js --write \"{src,test}/**/*.js\""
}
}

@@ -11,3 +11,3 @@ # react-native-hotspot

<!-- [Run example](https://snack.expo.io/@lfkwtz/react-native-hotspot) -->
[Run example](https://snack.expo.io/@lfkwtz/react-native-hotspot)

@@ -14,0 +14,0 @@ ## Getting Started

@@ -1,10 +0,10 @@

import React from "react";
import React from 'react';
export function RNHotspotHelper(actions) {
return actions.map(action => {
return {
ref: React.createRef(),
onPress: action
};
});
return actions.map((action) => {
return {
ref: React.createRef(),
onPress: action,
};
});
}

@@ -1,77 +0,77 @@

import React, { PureComponent } from "react";
import { findNodeHandle } from "react-native";
import { Pulse } from "./";
import React, { PureComponent } from 'react';
import { findNodeHandle } from 'react-native';
import { Pulse } from './';
const RCTUIManager = require("NativeModules").UIManager;
const RCTUIManager = require('NativeModules').UIManager;
export class RNHotspot extends PureComponent {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.state = {
hotspots: null
};
this.state = {
hotspots: null,
};
this.onPress = this.onPress.bind(this);
}
this.onPress = this.onPress.bind(this);
}
componentDidMount() {
const { componentRefs } = this.props;
componentDidMount() {
const { componentRefs } = this.props;
const hotspots = [];
const hotspots = [];
setTimeout(() => {
componentRefs.map(({ ref, onPress }) => {
RCTUIManager.measure(
findNodeHandle(ref.current),
(x, y, width, height, pageX, pageY) => {
hotspots.push({
width,
height,
pageX,
pageY,
onPress
setTimeout(() => {
componentRefs.map(({ ref, onPress }) => {
RCTUIManager.measure(
findNodeHandle(ref.current),
(x, y, width, height, pageX, pageY) => {
hotspots.push({
width,
height,
pageX,
pageY,
onPress,
});
}
);
});
}
);
});
setTimeout(() => {
this.setState({
hotspots
setTimeout(() => {
this.setState({
hotspots,
});
}, 1);
});
}, 1);
});
}
}
onPress(idx) {
const { hotspots } = this.state;
onPress(idx) {
const { hotspots } = this.state;
hotspots[idx].onPress();
const newArr = hotspots.concat([]);
hotspots[idx].onPress();
const newArr = hotspots.concat([]);
newArr.splice(idx, 1);
newArr.splice(idx, 1);
this.setState({
hotspots: newArr
});
}
this.setState({
hotspots: newArr,
});
}
render() {
const { hotspots } = this.state;
render() {
const { hotspots } = this.state;
if (!hotspots) {
return null;
if (!hotspots) {
return null;
}
return hotspots.map(({ width, height, pageX, pageY }, idx) => {
return (
<Pulse
key={idx}
idx={idx}
dimensions={{ width, height, pageX, pageY }}
onPress={this.onPress}
/>
);
});
}
return hotspots.map(({ width, height, pageX, pageY }, idx) => {
return (
<Pulse
key={idx}
idx={idx}
dimensions={{ width, height, pageX, pageY }}
onPress={this.onPress}
/>
);
});
}
}

@@ -1,3 +0,3 @@

export * from "./helper";
export * from "./hotspot";
export * from "./pulse";
export * from './helper';
export * from './hotspot';
export * from './pulse';

@@ -1,10 +0,4 @@

import React, { PureComponent } from "react";
import {
Animated,
Easing,
StyleSheet,
TouchableWithoutFeedback,
View
} from "react-native";
import PropTypes from "prop-types";
import React, { PureComponent } from 'react';
import { Animated, Easing, StyleSheet, TouchableWithoutFeedback, View } from 'react-native';
import PropTypes from 'prop-types';

@@ -16,150 +10,146 @@ // https://github.com/facebook/react-native/issues/8968#issuecomment-314322836

export class Pulse extends PureComponent {
static propTypes = {
dimensions: PropTypes.shape({
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
pageX: PropTypes.number.isRequired,
pageY: PropTypes.number.isRequired
}).isRequired,
onPress: PropTypes.func,
offset: PropTypes.shape({
top: PropTypes.number,
left: PropTypes.number
}),
startSize: PropTypes.number,
endSize: PropTypes.number,
borderWidth: PropTypes.number,
borderColor: PropTypes.string,
backgroundColor: PropTypes.string,
duration: PropTypes.number,
stagger: PropTypes.number
};
static propTypes = {
dimensions: PropTypes.shape({
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
pageX: PropTypes.number.isRequired,
pageY: PropTypes.number.isRequired,
}).isRequired,
onPress: PropTypes.func,
offset: PropTypes.shape({
top: PropTypes.number,
left: PropTypes.number,
}),
startSize: PropTypes.number,
endSize: PropTypes.number,
borderWidth: PropTypes.number,
borderColor: PropTypes.string,
backgroundColor: PropTypes.string,
duration: PropTypes.number,
stagger: PropTypes.number,
};
static defaultProps = {
onPress: null,
offset: {
top: 0,
left: 0
},
startSize: 10,
endSize: 80,
borderWidth: 3,
borderColor: "rgba(249, 161, 27, 0.4)",
backgroundColor: "rgba(249, 161, 27, 0.6)",
duration: 2000,
stagger: 400
};
static defaultProps = {
onPress: null,
offset: {
top: 0,
left: 0,
},
startSize: 10,
endSize: 80,
borderWidth: 3,
borderColor: 'rgba(249, 161, 27, 0.4)',
backgroundColor: 'rgba(249, 161, 27, 0.6)',
duration: 2000,
stagger: 400,
};
constructor(props) {
super(props);
constructor(props) {
super(props);
this.animations = [
new Animated.Value(0),
new Animated.Value(0),
new Animated.Value(0)
];
}
this.animations = [new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)];
}
componentDidMount() {
this.animate();
}
componentDidMount() {
this.animate();
}
animate() {
const { duration, stagger } = this.props;
const animations = this.animations.map(item => {
return Animated.timing(item, {
toValue: 1,
duration,
easing: Easing.in
});
});
Animated.loop(Animated.stagger(stagger, animations)).start();
}
animate() {
const { duration, stagger } = this.props;
const animations = this.animations.map((item) => {
return Animated.timing(item, {
toValue: 1,
duration,
easing: Easing.in,
});
});
Animated.loop(Animated.stagger(stagger, animations)).start();
}
render() {
const {
dimensions,
onPress,
offset,
startSize,
endSize,
borderWidth,
borderColor,
backgroundColor
} = this.props;
render() {
const {
dimensions,
onPress,
offset,
startSize,
endSize,
borderWidth,
borderColor,
backgroundColor,
} = this.props;
const animations = this.animations.map((animation, idx) => {
return (
<TouchableWithoutFeedback key={idx} onPress={() => {}}>
<View
style={[
defaultStyles.overlay,
{
width: dimensions.width,
height: dimensions.height,
top: dimensions.pageY + offset.top,
left: dimensions.pageX + offset.left,
backgroundColor: "transparent",
zIndex: 100
}
]}
>
<TouchableWithoutFeedback
onPress={() => {
onPress(this.props.idx);
}}
testID="tappableArea"
>
<View
style={[
defaultStyles.overlay,
{
width: endSize,
height: endSize,
top: dimensions.height / 2 - endSize / 2 + offset.top,
left: dimensions.width / 2 - endSize / 2 + offset.left,
zIndex: 101
}
]}
testID="pulseOverlay"
>
<Animated.View
style={[
{
borderWidth: borderWidth * StyleSheet.hairlineWidth,
borderColor,
backgroundColor,
width: animation.interpolate({
inputRange: [0, 1],
outputRange: [startSize, endSize]
}),
height: animation.interpolate({
inputRange: [0, 1],
outputRange: [startSize, endSize]
}),
borderRadius: endSize / 2,
opacity: animation.interpolate({
inputRange: [0, 1],
outputRange: [1, 0]
})
}
]}
/>
</View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
);
});
const animations = this.animations.map((animation, idx) => {
return (
<TouchableWithoutFeedback key={idx} onPress={() => {}}>
<View
style={[
defaultStyles.overlay,
{
width: dimensions.width,
height: dimensions.height,
top: dimensions.pageY + offset.top,
left: dimensions.pageX + offset.left,
backgroundColor: 'transparent',
zIndex: 100,
},
]}
>
<TouchableWithoutFeedback
onPress={() => {
onPress(this.props.idx);
}}
testID="tappableArea"
>
<View
style={[
defaultStyles.overlay,
{
width: endSize,
height: endSize,
top: dimensions.height / 2 - endSize / 2 + offset.top,
left: dimensions.width / 2 - endSize / 2 + offset.left,
zIndex: 101,
},
]}
testID="pulseOverlay"
>
<Animated.View
style={[
{
borderWidth: borderWidth * StyleSheet.hairlineWidth,
borderColor,
backgroundColor,
width: animation.interpolate({
inputRange: [0, 1],
outputRange: [startSize, endSize],
}),
height: animation.interpolate({
inputRange: [0, 1],
outputRange: [startSize, endSize],
}),
borderRadius: endSize / 2,
opacity: animation.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
},
]}
/>
</View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
);
});
return animations;
}
return animations;
}
}
const defaultStyles = StyleSheet.create({
overlay: {
justifyContent: "center",
alignItems: "center",
position: "absolute"
}
overlay: {
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
},
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc