# react-native-age-declaration

A React Native library to access platform age verification APIs:
- **iOS**: Apple's Declared Age Range API (iOS 16.0+)
- **Android**: Google Play's Age Signals API (Android 15+)

This library provides a unified interface for both platforms, making it easy to verify user age ranges in your React Native applications.

## 🚀 Features

- ✅ **Cross-platform**: Works on both iOS and Android
- ✅ **Type-safe**: Written in TypeScript with full type definitions
- ✅ **Expo compatible**: Works with both Expo and bare React Native projects
- ✅ **Simple API**: Easy-to-use interface with promises
- ✅ **Zero dependencies**: No additional npm packages required
- ✅ **Production ready**: Built with standard React Native modules (no experimental dependencies)

## 📱 Platform Requirements

### iOS
- iOS 26.0 or later
- Xcode 16.0 or later (with iOS 26 SDK)
- Uses Apple's DeclaredAgeRange framework and AgeRangeService API
- Requires the entitlement: `com.apple.developer.declared-age-range`

### Android
- Android 15+ (API level 35+)
- Google Play Services
- The API requires the device to have Google Play installed

## 📦 Installation

```bash
npm install react-native-age-declaration
# or
yarn add react-native-age-declaration
```

### iOS Setup

1. Install pods:
```bash
cd ios && pod install
```

2. Add the age range entitlement to your `app.config.js` or `app.json`:

```javascript
// app.config.js
export default {
  expo: {
    ios: {
      entitlements: {
        'com.apple.developer.declared-age-range': true
      }
    }
  }
}
```

Or for bare React Native, add to your `Info.plist`:
```xml
<key>com.apple.developer.declared-age-range</key>
<true/>
```

### Android Setup

#### For Expo projects
The package should work automatically after installation.

#### For bare React Native projects

1. Add the package to your `android/app/build.gradle`:
```gradle
dependencies {
    implementation project(':react-native-age-declaration')
}
```

2. Add the package to `MainApplication.java`:
```java
import com.agedeclaration.AgeDeclarationPackage;

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.asList(
      new MainReactPackage(),
      new AgeDeclarationPackage() // Add this line
  );
}
```

3. Add to `android/settings.gradle`:
```gradle
include ':react-native-age-declaration'
project(':react-native-age-declaration').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-age-declaration/android')
```

## 🔧 Usage

### Basic Example

```typescript
import AgeDeclaration from 'react-native-age-declaration';

async function checkUserAge() {
  try {
    // 1. Check if the API is supported on this device
    const supported = await AgeDeclaration.isSupported();

    if (!supported) {
      console.log('Age verification not supported on this device');
      return;
    }

    // 2. Set age thresholds (must be done before requesting)
    await AgeDeclaration.setAgeThresholds([13, 15, 18]);

    // 3. Request age range from the platform
    const result = await AgeDeclaration.requestAgeRange();

    // 4. Handle the result
    switch (result.status) {
      case 'verified':
        console.log('User meets age requirements ✅');
        break;
      case 'not_verified':
        console.log('User does not meet age requirements ❌');
        break;
      case 'unknown':
        console.log('Age verification status unknown');
        break;
      case 'not_available_yet':
        console.log('API not available on this device/OS version');
        break;
    }
  } catch (error) {
    console.error('Age verification error:', error);
  }
}
```

### React Hook Example

```typescript
import { useState, useEffect } from 'react';
import AgeDeclaration from 'react-native-age-declaration';

function useAgeVerification(thresholds: number[]) {
  const [isSupported, setIsSupported] = useState(false);
  const [isVerified, setIsVerified] = useState<boolean | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    async function verify() {
      try {
        // Check support
        const supported = await AgeDeclaration.isSupported();
        setIsSupported(supported);

        if (!supported) {
          setLoading(false);
          return;
        }

        // Set thresholds
        await AgeDeclaration.setAgeThresholds(thresholds);

        // Request age range
        const result = await AgeDeclaration.requestAgeRange();
        setIsVerified(result.status === 'verified');
      } catch (err) {
        setError(err as Error);
      } finally {
        setLoading(false);
      }
    }

    verify();
  }, [thresholds]);

  return { isSupported, isVerified, loading, error };
}

// Usage in component
function MyComponent() {
  const { isSupported, isVerified, loading } = useAgeVerification([13, 18]);

  if (loading) return <Text>Checking age...</Text>;
  if (!isSupported) return <Text>Age verification not available</Text>;
  if (isVerified) return <Text>Access granted</Text>;
  return <Text>Age verification required</Text>;
}
```

## 📚 API Reference

### `setAgeThresholds(thresholds: number[]): Promise<SetThresholdsResult>`

Sets the age range thresholds for the application.

**Parameters:**
- `thresholds`: Array of age thresholds (1-18, ascending order, 2-year separation)

**Returns:** Promise that resolves when thresholds are set

**Requirements:**
- First threshold is mandatory
- Values must be 1-18 (inclusive)
- Must be in ascending order
- Minimum 2-year separation between values

**Example:**
```typescript
await AgeDeclaration.setAgeThresholds([13, 15, 18]);
```

---

### `requestAgeRange(): Promise<AgeRangeResult>`

Requests age range information from the platform.

**Returns:** Promise that resolves with age verification result

**Important:**
- Must call `setAgeThresholds()` first
- iOS: Requires iOS 26.0+ with DeclaredAgeRange framework
- Android: Requires Android 15+ with Google Play Services

**Example:**
```typescript
const result = await AgeDeclaration.requestAgeRange();
console.log(result.status); // 'verified' | 'not_verified' | 'unknown' | 'not_available_yet'
```

---

### `isSupported(): Promise<boolean>`

Checks if age range API is supported on this device.

**Returns:** Promise that resolves to true if supported

**Example:**
```typescript
const supported = await AgeDeclaration.isSupported();
```

## 🎯 Types

### `AgeRangeResult`

```typescript
interface AgeRangeResult {
  status: 'verified' | 'not_verified' | 'unknown' | 'not_available_yet' | 'error';
  message?: string;
  thresholds?: number[];
  ageRange?: string;        // iOS only
  lowerBound?: number;      // iOS only
  upperBound?: number;      // iOS only
}
```

### `SetThresholdsResult`

```typescript
interface SetThresholdsResult {
  success: boolean;
}
```

## ⚠️ Important Notes

### iOS
- **Requires iOS 26.0 or later** with the DeclaredAgeRange framework
- On devices running iOS versions below 26.0, the library will return `status: 'not_available_yet'`
- You must add the `com.apple.developer.declared-age-range` entitlement
- Age thresholds can only be set once at startup; changing them will re-prompt the user
- The API presents a system dialog to the user to request age range information

### Android
- Requires Google Play Services to be installed and up-to-date
- Only works on Android 15+ (API level 35+)
- The device must have Google Play installed (won't work on devices without Play)

### Best Practices
1. **Set thresholds at app startup**: Call `setAgeThresholds()` early in your app lifecycle
2. **Check support first**: Always call `isSupported()` before attempting verification
3. **Handle all status cases**: The API can return different statuses, handle each appropriately
4. **Don't change thresholds**: Once set, keep thresholds consistent to avoid re-prompting users

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## 📄 License

MIT

## 🐛 Issues

If you encounter any issues, please report them at:
https://github.com/dandrykevych/react-native-age-declaration/issues

## 📝 Changelog

### 1.0.0 (2025-12-22)
- Initial release
- iOS support for Declared Age Range API
- Android support for Age Signals API
- TypeScript support
- Expo compatible

## 🙏 Acknowledgments

- Apple's Declared Age Range API documentation
- Google Play's Age Signals API documentation

---

Made with ❤️ for the React Native community
