npm package: @kunlexze1/react-native-otp-timer
Description: OTP input component + countdown timer hook for React Native (using react-native-otp-entry)
Author: Your Name
Latest version: 1.0.0

# react-native-otp-timer

A comprehensive React Native OTP input component with built-in countdown timer functionality, built on top of `react-native-otp-entry`.

## Features

- 🔄 **Auto Restart**: Built-in restart button when timer expires
- 🎯 **Complete OTP Input**: All props from `react-native-otp-entry` exposed
- ⏰ **Built-in Timer**: Countdown timer with customizable duration
- 🎨 **Fully Customizable**: Timer styling, position, and formatting
- 📱 **Background Support**: Handles app state changes correctly
- 🔒 **TypeScript**: Full TypeScript support with proper types
- 🪝 **Flexible Hooks**: Use timer independently or with OTP component
- ♿ **Accessible**: Maintains accessibility features from base component

## Installation

```bash
npm install react-native-otp-timer react-native-otp-entry
# or
yarn add react-native-otp-timer react-native-otp-entry
```

## Quick Start

```tsx
import React from 'react';
import { OtpWithTimer } from 'react-native-otp-timer';

export default function App() {
  const handleOtpFilled = (otp: string) => {
    console.log('OTP entered:', otp);
  };

  const handleResendOtp = async () => {
    // Call your API to resend OTP
    console.log('Resending OTP...');
    // await api.resendOtp();
  };

  return (
    <OtpWithTimer
      numberOfDigits={6}
      timerDuration={120} // 2 minutes
      onFilled={handleOtpFilled}
      onTimerExpire={() => console.log('Timer expired!')}
      onRestartTimer={handleResendOtp}
      showRestartButton={true}
      restartButtonText="Resend OTP"
    />
  );
}
```

## API Reference

### OtpWithTimer Props

#### Timer Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `timerDuration` | `number` | `60` | Timer duration in seconds |
| `timerStyle` | `TextStyle` | - | Custom styling for timer text |
| `timerFormatter` | `(time: string) => string` | - | Custom timer display formatter |
| `showTimer` | `boolean` | `true` | Show/hide the timer |
| `timerPosition` | `'top' \| 'bottom'` | `'top'` | Timer position relative to OTP |
| `autoStartTimer` | `boolean` | `true` | Auto-start timer on mount |
| `onTimerExpire` | `() => void` | - | Called when timer expires |
| `onTimerStart` | `() => void` | - | Called when timer starts |
| `onTimerReset` | `() => void` | - | Called when timer resets |
| `onRestartTimer` | `() => void` | - | Called when timer restarts |
| `showRestartButton` | `boolean` | `true` | Show restart button when expired |
| `restartButtonText` | `string` | `'Resend OTP'` | Custom restart button text |
| `restartButtonStyle` | `TextStyle` | - | Custom restart button styling |

#### OTP Props (from react-native-otp-entry)
All props from `react-native-otp-entry` are supported:

| Prop | Type | Description |
|------|------|-------------|
| `numberOfDigits` | `number` | Number of OTP digits |
| `onFilled` | `(text: string) => void` | Called when OTP is complete |
| `focusColor` | `string` | Focus color for inputs |
| `theme` | `object` | Styling theme object |
| ... and many more | | See react-native-otp-entry docs |

## Hooks

### useTimer

Standalone timer hook for custom implementations:

```tsx
import { useTimer } from 'react-native-otp-timer';

function CustomTimer() {
  const { timeLeft, hasTimeout, startTimer, resetOtpTimer } = useTimer(60);
  
  return (
    <View>
      <Text>{timeLeft}</Text>
      <Button title="Reset" onPress={resetOtpTimer} />
    </View>
  );
}
```

### useOtpTimer

Enhanced timer hook with additional utilities:

```tsx
import { useOtpTimer } from 'react-native-otp-timer';

function EnhancedTimer() {
  const { timeLeft, hasTimeout, startTimer, resetTimer, restartTimer } = useOtpTimer(120);
  
  const handleResend = () => {
    restartTimer(); // Resets and starts the timer
    // Call your resend API here
  };

  return (
    <View>
      <Text>{timeLeft}</Text>
      {hasTimeout && (
        <Button title="Resend OTP" onPress={handleResend} />
      )}
    </View>
  );
}
```

## Advanced Usage

### Timer Restart Options

#### 1. Built-in Restart Button
```tsx
<OtpWithTimer
  numberOfDigits={6}
  timerDuration={60}
  showRestartButton={true}
  restartButtonText="Get New Code"
  restartButtonStyle={{ color: '#007AFF', fontWeight: 'bold' }}
  onRestartTimer={() => {
    console.log('Resending OTP...');
    // Call your resend OTP API
  }}
/>
```

#### 2. Programmatic Restart
```tsx
import { useOtpTimer } from 'react-native-otp-timer';

function CustomOtpScreen() {
  const { restartTimer, hasTimeout, timeLeft } = useOtpTimer(60);

  const handleManualResend = async () => {
    try {
      await resendOtpApi();
      restartTimer(); // Restart the timer after successful API call
    } catch (error) {
      console.error('Failed to resend OTP');
    }
  };

  return (
    <View>
      <OtpWithTimer 
        numberOfDigits={6} 
        showRestartButton={false} // Hide built-in button
      />
      <Text>Timer: {timeLeft}</Text>
      {hasTimeout && (
        <Button title="Resend Code" onPress={handleManualResend} />
      )}
    </View>
  );
}
```

### Custom Timer Formatting

```tsx
<OtpWithTimer
  numberOfDigits={4}
  timerDuration={300}
  timerFormatter={(time) => `Expires in: ${time}`}
  timerStyle={{ color: 'red', fontSize: 18 }}
/>
```

### Timer Position Control

```tsx
<OtpWithTimer
  numberOfDigits={6}
  timerPosition="bottom"
  showTimer={true}
/>
```

### Complete Example

```tsx
import React, { useState } from 'react';
import { View, StyleSheet, Alert } from 'react-native';
import { OtpWithTimer } from 'react-native-otp-timer';

export default function OtpVerificationScreen() {
  const [isLoading, setIsLoading] = useState(false);

  const handleOtpComplete = async (otp: string) => {
    setIsLoading(true);
    try {
      const response = await verifyOtp(otp);
      if (response.success) {
        // Navigate to next screen
        Alert.alert('Success', 'OTP verified successfully!');
      }
    } catch (error) {
      Alert.alert('Error', 'Invalid OTP. Please try again.');
    } finally {
      setIsLoading(false);
    }
  };

  const handleResendOtp = async () => {
    try {
      await resendOtpApi();
      Alert.alert('Success', 'New OTP sent to your phone!');
    } catch (error) {
      Alert.alert('Error', 'Failed to resend OTP. Please try again.');
    }
  };

  return (
    <View style={styles.container}>
      <OtpWithTimer
        numberOfDigits={6}
        timerDuration={300} // 5 minutes
        focusColor="#007AFF"
        type="numeric"
        secureTextEntry={false}
        disabled={isLoading}
        autoStartTimer={true}
        showRestartButton={true}
        restartButtonText="Didn't receive code? Resend"
        timerPosition="bottom"
        containerStyle={styles.otpContainer}
        timerStyle={styles.timerText}
        restartButtonStyle={styles.resendButton}
        theme={{
          pinCodeContainerStyle: styles.pinContainer,
          focusedPinCodeContainerStyle: styles.focusedPin,
          filledPinCodeContainerStyle: styles.filledPin,
          pinCodeTextStyle: styles.pinText,
        }}
        onFilled={handleOtpComplete}
        onTimerExpire={() => Alert.alert('Timeout', 'OTP has expired')}
        onRestartTimer={handleResendOtp}
        textInputProps={{
          accessibilityLabel: 'OTP digit input',
        }}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
  },
  otpContainer: {
    marginVertical: 20,
  },
  timerText: {
    fontSize: 16,
    color: '#666',
    fontWeight: '500',
  },
  resendButton: {
    fontSize: 14,
    color: '#007AFF',
    fontWeight: '600',
  },
  pinContainer: {
    borderWidth: 2,
    borderColor: '#E0E0E0',
    borderRadius: 12,
    width: 50,
    height: 60,
  },
  focusedPin: {
    borderColor: '#007AFF',
    backgroundColor: '#F0F8FF',
  },
  filledPin: {
    borderColor: '#4CAF50',
    backgroundColor: '#F0FFF0',
  },
  pinText: {
    fontSize: 20,
    fontWeight: '600',
  },
});
```

## Requirements

- React Native >= 0.71
- React >= 17
- react-native-otp-entry >= 1.8.0

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## Issues & Support

If you encounter any issues or have questions:

1. Check the [GitHub Issues](https://github.com/your-username/react-native-otp-timer/issues)
2. Create a new issue with detailed information
3. Provide React Native version, device information, and code examples

## Changelog

### v1.0.0
- Initial release
- Complete OTP input with timer functionality
- Built-in restart capabilities
- Full TypeScript support
- Background app state handling

## Support

If you find this package helpful, please consider:
- ⭐ Starring the repository
- 🐛 Reporting bugs
- 💡 Suggesting new features
- 📖 Improving documentation

---

**Made with ❤️ for the React Native community**