RN-TourGuide - A flexible tourguide for your react native app

Last update: May 9, 2022

RN-TourGuide

A flexible tourguide for your react native app!
🎉 Webable 🎉
(a rewriting of react-native-copilot)

RN Tourguide

🎉 DEMO WEB 🎉

Installation

yarn add rn-tourguide
yarn add react-native-svg
react-native link react-native-svg

If you are using Expo:

expo install react-native-svg

Usage

start()}> START THE TUTORIAL! start(4)}> Step 4 start(2)}> Step 2 Stop ) }">
import {
  TourGuideProvider, // Main provider
  TourGuideZone, // Main wrapper of highlight component
  TourGuideZoneByPosition, // Component to use mask on overlay (ie, position absolute)
  useTourGuideController, // hook to start, etc.
} from 'rn-tourguide'

// Add  at the root of you app!
function App() {
  return (
    <TourGuideProvider {...{ borderRadius: 16 }}>
      <AppContent />
    </TourGuideProvider>
  )
}

const AppContent = () => {
  const iconProps = { size: 40, color: '#888' }

  // Use Hooks to control!
  const {
    canStart, // a boolean indicate if you can start tour guide
    start, // a function to start the tourguide
    stop, // a function  to stopping it
    eventEmitter, // an object for listening some events
  } = useTourGuideController()

  // Can start at mount 🎉
  // you need to wait until everything is registered 😁
  React.useEffect(() => {
    if (canStart) {
      // 👈 test if you can start otherwise nothing will happen
      start()
    }
  }, [canStart]) // 👈 don't miss it!

  const handleOnStart = () => console.log('start')
  const handleOnStop = () => console.log('stop')
  const handleOnStepChange = () => console.log(`stepChange`)

  React.useEffect(() => {
    eventEmitter.on('start', handleOnStart)
    eventEmitter.on('stop', handleOnStop)
    eventEmitter.on('stepChange', handleOnStepChange)

    return () => {
      eventEmitter.off('start', handleOnStart)
      eventEmitter.off('stop', handleOnStop)
      eventEmitter.off('stepChange', handleOnStepChange)
    }
  }, [])

  return (
    <View style={styles.container}>
      {/*

          Use TourGuideZone only to wrap your component

      */}
      <TourGuideZone
        zone={2}
        text={'A react-native-copilot remastered! 🎉'}
        borderRadius={16}
      >
        <Text style={styles.title}>
          {'Welcome to the demo of\n"rn-tourguide"'}
        </Text>
      </TourGuideZone>
      <View style={styles.middleView}>
        <TouchableOpacity style={styles.button} onPress={() => start()}>
          <Text style={styles.buttonText}>START THE TUTORIAL!</Text>
        </TouchableOpacity>

        <TourGuideZone zone={3} shape={'rectangle_and_keep'}>
          <TouchableOpacity style={styles.button} onPress={() => start(4)}>
            <Text style={styles.buttonText}>Step 4</Text>
          </TouchableOpacity>
        </TourGuideZone>
        <TouchableOpacity style={styles.button} onPress={() => start(2)}>
          <Text style={styles.buttonText}>Step 2</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.button} onPress={stop}>
          <Text style={styles.buttonText}>Stop</Text>
        </TouchableOpacity>
        <TourGuideZone
          zone={1}
          shape='circle'
          text={'With animated SVG morphing with awesome flubber 🍮💯'}
        >
          <Image source={{ uri }} style={styles.profilePhoto} />
        </TourGuideZone>
      </View>
      <View style={styles.row}>
        <TourGuideZone zone={4} shape={'circle'}>
          <Ionicons name='ios-contact' {...iconProps} />
        </TourGuideZone>
        <Ionicons name='ios-chatbubbles' {...iconProps} />
        <Ionicons name='ios-globe' {...iconProps} />
        <TourGuideZone zone={5}>
          <Ionicons name='ios-navigate' {...iconProps} />
        </TourGuideZone>
        <TourGuideZone zone={6} shape={'circle'}>
          <Ionicons name='ios-rainy' {...iconProps} />
        </TourGuideZone>
        <TourGuideZoneByPosition
          zone={7}
          shape={'circle'}
          isTourGuide
          bottom={30}
          left={35}
          width={300}
          height={300}
        />
      </View>
    </View>
  )
}

TourGuide props:

interface TourGuideZoneProps {
  zone: number // A positive number indicating the order of the step in the entire walkthrough.
  isTourGuide?: boolean // return children without wrapping id false
  text?: string // text in tooltip
  shape?: Shape // which shape
  maskOffset?: number // offset around zone
  borderRadius?: number // round corner when rectangle
  startAtMount?: boolean //  start at mount
  keepTooltipPosition?: boolean
  tooltipBottomOffset?: number
  children: React.ReactNode
}

type Shape = 'circle' | 'rectangle' | 'circle_and_keep' | 'rectangle_and_keep'

export interface TourGuideProviderProps {
  tooltipComponent?: React.ComponentType<TooltipProps>
  tooltipStyle?: StyleProp<ViewStyle>
  labels?: Labels
  androidStatusBarVisible?: boolean
  backdropColor?: string
  verticalOffset?: number
  wrapperStyle?: StyleProp<ViewStyle>
  maskOffset?: number
  borderRadius?: number
  animationDuration?: number
  children: React.ReactNode
  dismissOnPress?: boolean
  preventOutsideInteraction?:boolean
}

interface TooltipProps {
  isFirstStep?: boolean
  isLastStep?: boolean
  currentStep: Step
  labels?: Labels
  handleNext?(): void
  handlePrev?(): void
  handleStop?(): void
}

interface Labels {
  skip?: string
  previous?: string
  next?: string
  finish?: string
}

In order to start the tutorial, you can call the start function from useTourGuideController hook:

function HomeScreen() {
  const { start } = useTourGuideController()

  React.useEffect(() => {
    start()
  }, [])


  render() {
    // ...
  }
}

export default HomeScreen

If you are looking for a working example, please check out this link.

Custom tooltip component

You can customize the tooltip by passing a component to the copilot HOC maker. If you are looking for an example tooltip component, take a look at the default tooltip implementation.

const TooltipComponent = ({
  isFirstStep,
  isLastStep,
  handleNext,
  handlePrev,
  handleStop,
  currentStep,
}) => (
  // ...
);

<TourGuideProvider {...{tooltipComponent: TooltipComponent}}>
// ...
</TourGuideProvider>

Custom tooltip styling

You can customize tooltips style:

const style = {
  backgroundColor: '#9FA8DA',
  borderRadius: 10,
  paddingTop: 5,
}

<TourGuideProvider {...{ tooltipStyle: style }}>
// ...
</TourGuideProvider>

Custom mask color

You can customize the mask color - default is rgba(0, 0, 0, 0.4), by passing a color string to the copilot HOC maker.

<TourGuideProvider {...{ backdropColor: 'rgba(50, 50, 100, 0.9)' }}>
  // ...
</TourGuideProvider>

Custom labels (for i18n)

You can localize labels:

<TourGuideProvider
  {...{
    labels: {
      previous: 'Vorheriger',
      next: 'Nächster',
      skip: 'Überspringen',
      finish: 'Beenden',
    },
  }}
>
  // ...
</TourGuideProvider>

Listening to the events

Along with start(), useTourGuideController passes copilotEvents function to the component to help you with tracking of tutorial progress. It utilizes mitt under the hood, you can see how full API there.

List of available events is:

  • start — Copilot tutorial has started.
  • stop — Copilot tutorial has ended or skipped.
  • stepChange — Next step is triggered. Passes Step instance as event handler argument.

Prevent Outside Interaction

Sometimes you need to prevent users to interact with app while tour is shown, in such case preventOutsideInteraction prop is up for you.

default: false

<TourGuideProvider preventOutsideInteraction>
  <AppContent />
</TourGuideProvider>

Contributing

Issues and Pull Requests are always welcome.

Hire an expert!

Looking for a ReactNative freelance expert with more than 14 years experience? Contact me from my website!

License

GitHub

https://github.com/xcarpentier/rn-tourguide
Comments
  • 1. Block interaction with outside area

    This PR extends the current API with new propertypreventOutsideInteraction it allows preventing users to interact with the app while the tour is shown.

    resolves #23 resolves #3

    Reviewed by arthur-nesterenko at 2021-10-25 20:25
  • 2. fix(svg-mask): consider devices with on-screen buttons

    Replaces the use of the window size with the screen size, to ensure that on Android devices (that the gesture option is enabled, that is, that it does not use buttons on the screen) the mask is correctly sized.

    As it is today, on Android devices that disable the on-screen buttons on: PHOTO-2020-09-30-17-23-55

    Reviewed by Gabrielfcs at 2020-09-30 20:29
  • 3. fix(tourGuideZoneByPosition): adding optional params text and its styling

    Changelog

    • adding optional params text for TourGuideZoneByPosition
    • add style {position: 'absolute') in TourGuideZoneByPosition's style to be able to place tooltip from position bottom.
    Reviewed by cindmichelle at 2020-11-11 16:01
  • 4. I have multiple view in a screen, which has scrolling.

    I have multiple views inside a screen, which has scrolling when I need to show guide to a bottom, the guide does not move the position which is in the scroll. Can someone help with this?

    Reviewed by vineelk8 at 2020-10-13 08:15
  • 5. Maximum call stack size exceeded

    Hey, Your library looks great, however I stumble on a problem. I want the tour to start when the app is mounted, so I tried your demo app, but I changed out

        React.useEffect(() => {
            eventEmitter.on('start', () => console.log('start'))
            eventEmitter.on('stop', () => console.log('stop'))
            eventEmitter.on('stepChange', () => console.log(`stepChange`))
    
            return () => eventEmitter.off('*', null)
        }, [])
    

    with

        React.useEffect(() => {
            start()
        }, [])
    

    Then start runs in an infinite loop. I printed out the values in

    const start = async (fromStep) => {
            const currentStep = fromStep
                ? steps[fromStep]
                : getFirstStep();
            if (startTries > MAX_START_TRIES) {
                setStartTries(0);
                return;
            }
            console.log({fromStep, currentStep, steps});
            if (!currentStep) {
                setStartTries(startTries + 1);
                start(fromStep);
            }
            else {
                eventEmitter.emit('start');
                await setCurrentStep(currentStep);
                setVisible(true);
                setStartTries(0);
            }
        };
    

    which is:

    currentStep: null
    fromStep: undefined
    steps: {}
    

    So, currentStep is always null, hence it goes in an infinite loop, it might seem like there is a bug when using it onMount? :)

    RN version: 0.62.2 Full code

    import * as React from 'react'
    import { Image, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
    import {
        TourGuideProvider,
        TourGuideZone,
        TourGuideZoneByPosition,
        useTourGuideController
    } from 'rn-tourguide'
    
    const uri = 'https://pbs.twimg.com/profile_images/1223192265969016833/U8AX9Lfn_400x400.jpg'
    
    // Add <TourGuideProvider/> at the root of you app!
    function App() {
        return (
            <TourGuideProvider {...{ borderRadius: 16 }}>
                <AppContent />
            </TourGuideProvider>
        )
    }
    
    const AppContent = () => {
        const iconProps = { size: 40, color: '#888' }
    
        // Use Hooks to control!
        const { start, stop, eventEmitter } = useTourGuideController()
    
        React.useEffect(() => {
            start()
        }, [])
    
        return (
            <View style={styles.container}>
                {/* Use TourGuideZone only to wrap */}
                <TourGuideZone
                    keepTooltipPosition
                    zone={2}
                    text={'A react-native-copilot remastered! 🎉'}
                    borderRadius={16}>
                    <Text style={styles.title}>{'Welcome to the demo of\n"rn-tourguide"'}</Text>
                </TourGuideZone>
                <View style={styles.middleView}>
                    <TouchableOpacity style={styles.button} onPress={() => start()}>
                        <Text style={styles.buttonText}>START THE TUTORIAL!</Text>
                    </TouchableOpacity>
    
                    <TourGuideZone zone={3} shape={'rectangle_and_keep'}>
                        <TouchableOpacity style={styles.button} onPress={() => start(4)}>
                            <Text style={styles.buttonText}>Step 4</Text>
                        </TouchableOpacity>
                    </TourGuideZone>
                    <TouchableOpacity style={styles.button} onPress={() => start(2)}>
                        <Text style={styles.buttonText}>Step 2</Text>
                    </TouchableOpacity>
                    <TouchableOpacity style={styles.button} onPress={stop}>
                        <Text style={styles.buttonText}>Stop</Text>
                    </TouchableOpacity>
                    <TourGuideZone
                        zone={1}
                        shape="circle"
                        text={'With animated SVG morphing with awesome flubber 🍮💯'}>
                        <Image source={{ uri }} style={styles.profilePhoto} />
                    </TourGuideZone>
                </View>
            </View>
        )
    }
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
            backgroundColor: '#fff',
            alignItems: 'center',
            paddingTop: 40
        },
        title: {
            fontSize: 24,
            textAlign: 'center'
        },
        profilePhoto: {
            width: 140,
            height: 140,
            borderRadius: 70,
            marginVertical: 20
        },
        middleView: {
            flex: 1,
            alignItems: 'center'
        },
        button: {
            backgroundColor: '#2980b9',
            paddingVertical: 10,
            paddingHorizontal: 15,
            margin: 2
        },
        buttonText: {
            color: 'white',
            fontSize: 16
        },
        row: {
            width: '100%',
            padding: 15,
            flexDirection: 'row',
            justifyContent: 'space-between'
        },
        activeSwitchContainer: {
            flexDirection: 'row',
            justifyContent: 'space-between',
            marginBottom: 20,
            alignItems: 'center',
            paddingHorizontal: 40
        }
    })
    
    export default App
    
    Reviewed by skeie at 2020-06-12 15:58
  • 6. custom toolTip connecting functions

    I'm sure there is a trivial solution to this but I can't seem to get it worked out.

    I want to customize the labels for my rn-tourguide tooltip so I have implemented a TooltipComponent as detailed in the README and I'm getting my custom labels but cannot make them do anything.

    Apologies, still learning react. Any help appreciated.

    Here is my code:

    import React, { useEffect, useState } from "react";
    import {
      View,
      Image,
      Button,
      Text,
      StyleSheet,
      TouchableOpacity,
      Animated,
      Dimensions,
    } from "react-native";
    
    import {
      TourGuideProvider,
      TourGuideZone,
      TourGuideZoneByPosition,
      useTourGuideController,
    } from "rn-tourguide";
    
    const { width, height } = Dimensions.get("window");
    
    const TooltipComponent = ({
      isFirstStep,
      isLastStep,
      handleNext,
      handlePrev,
      handleStop,
      currentStep,
      labels,
    }) => (
      <View
        style={{
          borderRadius: 16,
          paddingTop: 24,
          alignItems: "center",
          justifyContent: "center",
          paddingBottom: 16,
          width: "80%",
          backgroundColor: "#ffffffef",
        }}
      >
        <View style={styles.tooltipContainer}>
          <Text testID="stepDescription" style={styles.tooltipText}>
            {currentStep && currentStep.text}
          </Text>
        </View>
        <View style={[styles.bottomBar]}>
          {!isLastStep ? (
            <TouchableOpacity onPress={handleStop}>
              <Button title={labels?.skip || "Skip?"}> </Button>
            </TouchableOpacity>
          ) : null}
          {!isFirstStep ? (
            <TouchableOpacity onPress={handlePrev}>
              <Button title={labels?.previous || "Previous"}> </Button>
            </TouchableOpacity>
          ) : null}
          {!isLastStep ? (
            <TouchableOpacity onPress={handleNext}>
              <Button title={labels?.next || "Next"}></Button>
            </TouchableOpacity>
          ) : (
            <TouchableOpacity onPress={handleStop}>
              <Button title={labels?.finish || "Finish"}></Button>
            </TouchableOpacity>
          )}
        </View>
      </View>
    );
    
    function LocalSettingsScreen(props) {
      
      const { canStart, start, stop, eventEmitter } = useTourGuideController();
    
      useEffect(() => {
        if (canStart) {
          start();
        }
      }, [canStart]);
    
      const handleOnStart = () => console.log("start");
      const handleOnStop = () => {
        console.log("stop");
        moveView(0);
      };
      const handleOnStepChange = () => console.log(`stepChange`);
    
      useEffect(() => {
        eventEmitter.on("start", handleOnStart);
        eventEmitter.on("stop", handleOnStop);
        eventEmitter.on("stepChange", handleOnStepChange);
    
        return () => {
          eventEmitter.off("start", handleOnStart);
          eventEmitter.off("stop", handleOnStop);
          eventEmitter.off("stepChange", handleOnStepChange);
        };
      }, []);
    
      const yValue = useState(new Animated.Value(0))[0];
      let startingYValue = 0;
    
      function moveView(value) {
        console.log(`moving ${value}`);
        Animated.timing(yValue, {
          toValue: value,
          duration: 5,
          useNativeDriver: true,
        }).start();
      }
    
      return (
        <>
          <View
            style={styles.container}
          >
            <View>
              <TouchableOpacity
                onPress={() => {
                  startingYValue = startingYValue + 50;
                  console.log("startingYValue ", startingYValue);
                  moveView(startingYValue);
                }}
              >
                <Animated.View style={{ transform: [{ translateY: yValue }] }}>
                  <Image
                    source={require("../../../assets/settings_walkthrough_screen.png")}
                    style={styles.image}
                  />
                </Animated.View>
              </TouchableOpacity>
    
              <TourGuideZone
                zone={0}
                text={"This is Step 1"}
                borderRadius={8}
                tooltipBottomOffset={400}
              ></TourGuideZone>
              <TourGuideZoneByPosition
                text={"This is Step 2"}
                zone={1}
                shape={"circle"}
                isTourGuide
                top={83}
                left={"2.5%"}
                width={50}
                height={50}
              />
            </View>
          </View>
          <View style={{ height: 100, width: "100%", paddingTop:0 }}>
            <View style={{ marginLeft: 0 }}>
              <Image
                resizeMode={"contain"}
                style={{
                  width: "100%",
                  height: "100%",
                  alignSelf: "center",
                }}
                source={require("../../../assets/settings_walkthrough_screen_ft.png")}
              />
            </View>
          </View>
        </>
      );
    }
    
    export function SettingsScreen(props) {
    
      return (
        <View style={{ flex: 1, width: "100%" }}>
          <TourGuideProvider {...{ tooltipComponent: TooltipComponent }}>
            <LocalSettingsScreen props={props} />
          </TourGuideProvider>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
        width: "100%",
        height: "100%",
      },
     
      image: {
        height: "100%",
        zIndex: -1,
        width: width,
      },
      backgroundImage: {
        height: "100%",
        position: "absolute",
        top: 0,
        left: 0,
        alignItems: "center",
        bottom: 0,
        right: 0,
        width: width,
        flex: 1,
      },
    });
    
    
    Reviewed by lucidprojects at 2022-02-22 21:27
  • 7. chore(deps): bump url-parse from 1.5.3 to 1.5.7

    Bumps url-parse from 1.5.3 to 1.5.7.

    Commits
    • 8b3f5f2 1.5.7
    • ef45a13 [fix] Readd the empty userinfo to url.href (#226)
    • 88df234 [doc] Add soft deprecation notice
    • 78e9f2f [security] Fix nits
    • e6fa434 [security] Add credits for incorrect handling of userinfo vulnerability
    • 4c9fa23 1.5.6
    • 7b0b8a6 Merge pull request #223 from unshiftio/fix/at-sign-handling-in-userinfo
    • e4a5807 1.5.5
    • 193b44b [minor] Simplify whitespace regex
    • 319851b [fix] Remove CR, HT, and LF
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2022-02-19 02:47
  • 8. chore(deps): bump tar from 4.4.10 to 4.4.15

    Bumps tar from 4.4.10 to 4.4.15.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2021-08-04 23:30
  • 9. chore(deps): bump url-parse from 1.4.7 to 1.5.1

    Bumps url-parse from 1.4.7 to 1.5.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2021-05-09 20:24
  • 10. Export types alongside with components

    This change would allow to have code like

    import type { TourGuideZoneProps } from 'rn-tourguide'
    

    instead of

    import type { TourGuideZoneProps } from 'rn-tourguide/lib/components/TourGuideZone'
    
    Reviewed by MasterLambaster at 2021-03-03 13:42
  • 11. fix(TourGuideProvider): fix fractional pixels (only for Retina display)

    it seems the problem here is in float pixel values. In reality, there is no fractional pixel, and therefore when we try to select a fractional pixel, inaccuracies can occur. This causes image misalignment on the web. I suggest rounding the 'top' and 'left' values to fix plotting inaccuracies.

    This bug only appears on Retina displays

    Before:

    image image

    After:

    image image

    Reviewed by lupenq at 2020-11-17 11:28
  • 12. chore(deps): bump async from 2.6.0 to 2.6.4

    Bumps async from 2.6.0 to 2.6.4.

    Changelog

    Sourced from async's changelog.

    v2.6.4

    • Fix potential prototype pollution exploit (#1828)

    v2.6.3

    • Updated lodash to squelch a security warning (#1675)

    v2.6.2

    • Updated lodash to squelch a security warning (#1620)

    v2.6.1

    • Updated lodash to prevent npm audit warnings. (#1532, #1533)
    • Made async-es more optimized for webpack users (#1517)
    • Fixed a stack overflow with large collections and a synchronous iterator (#1514)
    • Various small fixes/chores (#1505, #1511, #1527, #1530)
    Commits
    Maintainer changes

    This version was pushed to npm by hargasinski, a new releaser for async since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2022-04-29 10:56
  • 13. chore(deps): bump cross-fetch from 3.1.4 to 3.1.5

    Bumps cross-fetch from 3.1.4 to 3.1.5.

    Release notes

    Sourced from cross-fetch's releases.

    v3.1.5

    What's Changed

    New Contributors

    Full Changelog: https://github.com/lquixada/cross-fetch/compare/v3.1.4...v3.1.5

    Commits
    • c6089df chore(release): 3.1.5
    • a3b3a94 chore: updated node-fetch version to 2.6.7 (#124)
    • efed703 chore: updated node-fetch version to 2.6.5
    • 694ff77 refactor: removed ora from dependencies
    • efc5956 refactor: added .vscode to .gitignore
    • da605d5 refactor: renamed test/fetch/ to test/fetch-api/ and test/module/ to test/mod...
    • 0f0d51d chore: updated minor and patch versions of dev dependencies
    • c6e34ea refactor: removed sinon.js
    • f524a52 fix: yargs was incompatible with node 10
    • 7906fcf chore: updated dev dependencies
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2022-04-28 23:28
  • 14. Fix for the broken svg-mask on screen's resize (web + mobile native)

    This PR adds recalculation of the svg-mask, if app's screen was resized (zoomed). Added babel deps to support export type syntax. Also added fix for the [object Object] opacity prop in the AnimatedSvgPath component.

    Reviewed by Konstantin-Sharohin at 2021-11-07 18:17
  • 15. Multiple tours

    I wanted to be able to support multiple tours within my app (on different pages, or just on the same page but on different use cases potentially) so I made this fork. I basically made keyed objects so you can (optionally) input a tourKey when using the useTourGuideController hook and receive functions (and components) that are keyed to that string.

    Updated the README file with an example

    Made a lot of revisions and changes (and one little bugfix in there too (1st commit)). Feel free to take what I started and make your own changes if you like the direction it's going but don't feel this is enough.

    I tested it a bit for backwards compatibility but not crazily extensively.

    Cheers

    Reviewed by b-steel at 2021-10-22 18:30
react-native-wheel-picker-android ★186 - Simple and flexible React native wheel picker for Android, including DatePicker and TimePicker.
react-native-wheel-picker-android ★186 - Simple and flexible React native wheel picker for Android, including DatePicker and TimePicker.

React native wheel picker V2 A simple Wheel Picker for Android (For IOs is using Picker from react-native) Example You can clone the repo and run exam

May 8, 2022
react-native-photo-grid ★31 - React Native component that handles the complexities of building a grid of photos with a flexible number of photos per row.

react-native-photo-grid React Native component that handles the complexities of building a grid of photos with a flexible number of photos per row Ins

May 2, 2022
A Cross Platform(Android & iOS) ActionSheet with a flexible api, native performance and zero dependency code for react native. Create anything you want inside ActionSheet.
A Cross Platform(Android & iOS) ActionSheet with a flexible api, native performance and zero dependency code for react native. Create anything you want inside ActionSheet.

react-native-actions-sheet A highly customizable cross platform ActionSheet for react native. Screenshots Features Cross Platform (iOS and Android) Na

May 17, 2022
Flexible React & React Native feature flagging/flipping/toggling for simple use cases

Flexible React & React Native feature flagging/flipping/toggling for simple use cases

May 17, 2022
Flexible and lightweight React Native component for UITableView made with pure CSS
Flexible and lightweight React Native component for UITableView made with pure CSS

react-native-tableview-simple ?? This component is used in my production app Game ideas. Make sure to check it out! ?? This cross-platform component i

Apr 27, 2022
A simple search box with animation, inspired from ios search bar. Lightweight, fast, flexible.

React Native Search Box A simple search box with animation, inspired from ios search bar. Lightweight, fast, flexible, customizable. Support both iOS/

Apr 24, 2022
🚀 Organize your games easily. Create groups to play your favorite games with your friends.
🚀  Organize your games easily. Create groups to play your favorite games with your friends.

?? Introduction ?? Technologies This project was developed using the following technologies: React Native Expo ??️ Features OAuth2 Social Authenticati

Sep 10, 2021
Easy, cross-platform credit-card input for your React Native Project! Start accepting payment 💰 in your app today!
Easy, cross-platform credit-card input for your React Native Project! Start accepting payment 💰 in your app today!

React Native Credit Card Input Easy (and good looking) credit-card input for your React Native Project ?? ?? Code: <CreditCardInput onChange={this._on

May 15, 2022
react-native-egg make your react native app infinitely more fun !!

react-native-egg react-native-egg make your react native app infinitely more fun !! Implementation simple gestures detection achieve trigger easter eg

Apr 27, 2022
🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense!
🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense!

toastify-react-native ?? toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense! De

May 7, 2022
react-native-app-intro is a react native component implementing a parallax effect welcome page using base on react-native-swiper , similar to the one found in Google's app like Sheet, Drive, Docs...
react-native-app-intro is a react native component implementing a parallax effect welcome page using base on react-native-swiper , similar to the one found in Google's app like Sheet, Drive, Docs...

react-native-app-intro react-native-app-intro is a react native component implementing a parallax effect welcome page using base on react-native-swipe

May 6, 2022
react-native-app-intro is a react native component implementing a parallax effect welcome page using base on react-native-swiper , similar to the one found in Google's app like Sheet, Drive, Docs...
react-native-app-intro is a react native component implementing a parallax effect welcome page using base on react-native-swiper , similar to the one found in Google's app like Sheet, Drive, Docs...

react-native-app-intro react-native-app-intro is a react native component implementing a parallax effect welcome page using base on react-native-swipe

Nov 13, 2021
[NOT MAINTAINED] :bar_chart: Add line, area, pie, and bar charts to your React Native app
[NOT MAINTAINED] :bar_chart: Add line, area, pie, and bar charts to your React Native app

react-native-chart NOTE: I have not been able to maintain this repo. Recommend switching to Victory Charts. Getting Started npm i react-native-chart -

May 2, 2022
Tinder-like swipe cards for your React Native app
Tinder-like swipe cards for your React Native app

Swipe Cards for React Native A package based on @brentvatne's awesome example. Quick Start npm install --save react-native-swipe-cards Create a module

Apr 24, 2022
Step-by-step walkthrough for your react native app

React Native Copilot Step-by-step walkthrough for your react native app! Demo Creation of this project was sponsored by OK GROW! Installation npm inst

May 13, 2022
A clean and lightweight progress HUD for your React Native app.

React Native Progress HUD React Native Progress HUD is a React Native port of the popular SVProgressHUD. It is a clean and easy-to-use HUD meant to di

Feb 3, 2022
Make your app reactive with MobX and react-native-router-flux
Make your app reactive with MobX and react-native-router-flux

Package is obsolete with latest react-native-router-flux v4 - RNRF allows now wrapping all scenes and navbar by passing wrapBy param (equal to MobX ob

Oct 8, 2021
tinder-like loader for your react native app
tinder-like loader for your react native app

Pulse Loader for React Native tinder-like loader for your react native app Installation npm i react-native-pulse-loader --save Example import React fr

Feb 18, 2022
A cross-platform bridge that allows you to enable and disable the screen idle timer in your React Native app

react-native-idle-timer A cross-platform bridge that allows you to enable and disable the screen idle timer in your React Native app Install npm insta

Mar 28, 2022