JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4
  • Score
    100M100P100Q53290F
  • License MIT

Make an interactive step by step tour guide for your react-native app (a rewrite of react-native-copilot)

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@attarchi/rn-tourguide) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    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

    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 <TourGuideProvider/> at the root of you app!
    function App() {
      return (
    // If you added a statusbar in Andoid set androidStatusBarVisible: true as well to avoid vertical position issues
        <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.
      tourKey?: string // A string indicating which tour the zone belongs to
      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
      keepTooltipPosition?: boolean
      tooltipBottomOffset?: number
      children: React.ReactNode
      withoutButtons?: boolean
      pressable?: boolean
      onNext?: (currentStep: IStep | undefined, nextStep: IStep | undefined) => void | 'stop' | 'doNothing'
      onPrevious?: (currentStep: IStep | undefined, nextStep: IStep | undefined) => void | 'stop' | 'doNothing'
    }
    
    type Shape = 'circle' | 'rectangle' | 'circle_and_keep' | 'rectangle_and_keep'
    
    export interface TourGuideProviderProps {
      tooltipComponent?: React.ComponentType<TooltipProps>
      tooltipStyle?: StyleProp<ViewStyle>
      labels?: Labels
      startAtMount?: boolean | string //  start at mount, boolean for single tours, string for multiple tours
      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.

    Using Multiple Tours

    If you'd like to have multiple tours (different pages, differnt user types, etc) you can pass in a tourKey to useTourGuideController to create a tour that is keyed to that tourKey. Important If you use a keyed tour, in order for the TourGuideZone components to register correctly you must do one of two things. Either (1) pass along the tourKey to the TourGuideZone components, or (2) extract the TourGuideZone components from the hook itself

    (1) If you want to pass along the tourKey

    import { TourGuideZone, useTourGuideController } from 'rn-tourguide'
    const {
      canStart, // <-- These are all keyed to the tourKey
      start, // <-- These are all keyed to the tourKey
      stop, // <-- These are all keyed to the tourKey
      eventEmitter, // <-- These are all keyed to the tourKey
      tourKey, // <-- Extract the tourKey
    } = useTourGuideController('results')
    
    return (
      <TourGuideZone
        tourKey={tourKey} // <-- Pass in the tourKey
        zone={2}
        text='Check on your results'
      >
        {/** Children */}
      </TourGuideZone>
    )

    Or (2) if you want to extract the components directly from the hook

    import { useTourGuideController } from 'rn-tourguide'
    const { canStart, start, stop, TourGuideZone } =
      useTourGuideController('results')
    
    return (
      <TourGuideZone // <-- No need to pass in the tourKey
        zone={2}
        text='Check on your results'
      >
        {/** Children */}
      </TourGuideZone>
    )

    If you use multiple tours and would like to use the startAtMount prop on the TourGuideProvider component, then pass in the string of the tour you'd like to start

    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