# Tour

Smart, decomposed onboarding Tour component with spotlight highlighting, animations, and i18n support.

## Installation

```bash
pnpm add @djangocfg/ui-tools
```

## Basic Usage

```tsx
import { Tour, useTour } from '@djangocfg/ui-tools/tour';

const tours = [
  {
    id: 'onboarding',
    steps: [
      {
        id: 'welcome',
        target: '[data-tour-step-id="header"]',
        title: 'Welcome',
        content: 'Let us show you around!',
        position: 'bottom',
      },
      {
        id: 'sidebar',
        target: '#sidebar',
        title: 'Navigation',
        content: 'Use the sidebar to navigate.',
        position: 'right',
      },
    ],
  },
];

function App() {
  return (
    <Tour
      tours={tours}
      onComplete={(tourId) => console.log('Tour completed:', tourId)}
    >
      <Layout />
    </Tour>
  );
}

function StartButton() {
  const { start } = useTour();
  return <button onClick={() => start('onboarding')}>Start Tour</button>;
}
```

## Components

### Tour

All-in-one wrapper combining TourProvider with overlay rendering.

```tsx
<Tour
  tours={tours}                    // Array of tour configs
  spotlight={true}                 // Enable spotlight (default: true)
  spotlightOpacity={0.5}          // Overlay opacity (default: 0.5)
  spotlightBlur={0}               // Backdrop blur in px (default: 0)
  animated={true}                 // Enable animations (default: true)
  pulseRing={false}               // Pulsing ring around target (default: false)
  showArrow={false}               // Show arrow to target (default: false)
  keyboardNavigation={true}       // Arrow keys navigation (default: true)
  closeOnEscape={true}            // Close on Escape (default: true)
  closeOnOverlayClick={false}     // Close on overlay click (default: false)
  scrollToTarget={true}           // Scroll target into view (default: true)
  progressVariant="dots"          // 'dots' | 'bar' | 'fraction' | 'none'
  showSkipButton={true}           // Show skip button (default: true)
  onStart={(tourId) => {}}
  onComplete={(tourId) => {}}
  onSkip={(tourId, stepIndex) => {}}
  onStepChange={(index, step, direction) => {}}
>
  {children}
</Tour>
```

### Custom Composition

```tsx
import {
  TourProvider,
  TourSpotlight,
  TourContent,
  TourProgress,
  TourNavigation,
  useTour,
} from '@djangocfg/ui-tools/tour';

function CustomTourOverlay() {
  const { currentStep, currentStepIndex, totalSteps, next, previous, close } = useTour();
  // ... render custom UI
}

<TourProvider tours={tours}>
  <App />
  <CustomTourOverlay />
</TourProvider>
```

## Step Configuration

```tsx
interface TourStep {
  id: string;                    // Unique identifier
  target?: string;               // CSS selector or data-tour-step-id
  title: ReactNode;              // Step title
  content: ReactNode;            // Step content
  position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
  offset?: number;               // Popover offset (default: 12)
  align?: 'start' | 'center' | 'end';

  // Multi-page tours
  nextRoute?: string;            // Navigate on Next
  previousRoute?: string;        // Navigate on Previous

  // Labels (overrides i18n)
  nextLabel?: ReactNode;
  previousLabel?: ReactNode;

  // Spotlight
  disableSpotlight?: boolean;
  spotlightPadding?: number;     // Padding around target (default: 8)
  spotlightRadius?: number;      // Border radius (default: 4)
  allowTargetInteraction?: boolean;

  // Auto-advance
  autoAdvance?: number;          // Auto-advance after ms

  // Custom actions
  actions?: TourAction[];

  // Callbacks
  onBeforeShow?: () => boolean | Promise<boolean>;
  onShow?: () => void;
  onHide?: () => void;
}
```

## Targeting Elements

### Option 1: CSS Selector

```tsx
{
  id: 'step-1',
  target: '#my-button',  // or '.my-class', '[data-id="123"]'
  title: 'Click here',
  content: '...',
}
```

### Option 2: data-tour-step-id Attribute

```tsx
// In your component
<header data-tour-step-id="header">...</header>

// In tour config
{
  id: 'header',  // matches data-tour-step-id
  title: 'Welcome',
  content: '...',
}
```

## Hooks

### useTour

```tsx
const {
  start,           // (tourId, startIndex?) => void
  next,            // () => void
  previous,        // () => void
  goTo,            // (index) => void
  close,           // () => void
  isActive,        // boolean
  activeTourId,    // string | null
  currentStep,     // TourStep | null
  currentStepIndex,// number
  totalSteps,      // number
  isFirstStep,     // boolean
  isLastStep,      // boolean
  progress,        // number (0-1)
} = useTour();
```

## Keyboard Navigation

When enabled (default):
- `ArrowRight` / `ArrowDown`: Next step
- `ArrowLeft` / `ArrowUp`: Previous step
- `Escape`: Close tour

## Multi-page Tours

```tsx
const tours = [{
  id: 'walkthrough',
  steps: [
    {
      id: 'home',
      target: '#hero',
      title: 'Welcome',
      content: 'Start here.',
      nextRoute: '/dashboard',  // Navigate on Next
    },
    {
      id: 'dashboard',
      target: '#stats',
      title: 'Dashboard',
      content: 'View your metrics.',
      previousRoute: '/',       // Navigate on Previous
    },
  ],
}];
```

## Callbacks

```tsx
<Tour
  tours={tours}
  onStart={(tourId) => {
    analytics.track('tour_started', { tourId });
  }}
  onComplete={(tourId) => {
    localStorage.setItem(`tour_${tourId}_completed`, 'true');
  }}
  onSkip={(tourId, stepIndex) => {
    analytics.track('tour_skipped', { tourId, stepIndex });
  }}
  onStepChange={(index, step, direction) => {
    analytics.track('tour_step', { stepId: step.id, direction });
  }}
  onBeforeStepChange={async (currentIndex, nextIndex) => {
    // Return false to prevent navigation
    return true;
  }}
>
```

## Progress Variants

- `dots` - Clickable dots (default)
- `bar` - Progress bar
- `fraction` - "1 / 5" text
- `none` - No progress indicator

## Visual Options

### Arrow

Shows an arrow pointing from the popover to the target element:

```tsx
<Tour tours={tours} showArrow>
  {children}
</Tour>
```

### Backdrop Blur

Blurs the background outside the spotlight for enhanced focus:

```tsx
<Tour tours={tours} spotlightBlur={4} spotlightOpacity={0.3}>
  {children}
</Tour>
```

### Pulse Ring

Animated pulsing ring around the target to draw attention:

```tsx
<Tour tours={tours} pulseRing>
  {children}
</Tour>
```

### Disable Animations

Turn off all spotlight transition animations:

```tsx
<Tour tours={tours} animated={false}>
  {children}
</Tour>
```

### Full Featured

Combine all visual enhancements:

```tsx
<Tour
  tours={tours}
  showArrow
  spotlightBlur={2}
  spotlightOpacity={0.4}
  pulseRing
>
  {children}
</Tour>
```

## Internationalization (i18n)

Tour uses `@djangocfg/i18n` for translations. Default labels come from `tools.tour.*` keys:

- `tools.tour.next` - "Next"
- `tools.tour.previous` - "Back"
- `tools.tour.skip` - "Skip"
- `tools.tour.finish` - "Finish"
- `tools.tour.close` - "Close"
- `tools.tour.stepOf` - "Step {current} of {total}"

To customize, either:

1. **Override via props** (per-step or global):
```tsx
<Tour
  tours={tours}
  skipLabel="Exit tour"
  finishLabel="Done!"
>
```

2. **Provide custom translations** via I18nProvider:
```tsx
import { I18nProvider, mergeTranslations, en } from '@djangocfg/i18n';

const customEn = mergeTranslations(en, {
  tools: {
    tour: {
      next: 'Continue',
      skip: 'Exit',
    }
  }
});

<I18nProvider locale="en" translations={customEn}>
  <Tour tours={tours}>
    <App />
  </Tour>
</I18nProvider>
```

## Features

- Spotlight highlighting with SVG mask
- Optional backdrop blur for enhanced focus
- Arrow pointing from popover to target
- Smooth animations between steps
- Pulse ring effect for attention
- Keyboard navigation
- Multi-step and multi-page tours
- Progress indicators (dots, bar, fraction)
- Auto-scroll to target
- Lifecycle callbacks
- Custom positioning
- Skip/close functionality
- ARIA accessibility
- Full i18n support
