npm package: @pragadanaveen/react-native-location-autocomplete
Description: A comprehensive React Native component for location autocomplete with Google Places API, featuring animated placeholders, current location, recent searches, and extensive customization options
Author: pragadanaveen
Latest version: 2.2.0

# React Native Location Autocomplete

A comprehensive React Native component for location autocomplete with Google Places API integration. Features animated placeholder text, current location detection, recent searches, extensive customization options, and much more.

## 🚀 Features

- ✅ **Advanced API Optimization** - Intelligent caching, request coalescing, and reduced API calls
- ✅ **Animated Rotating Placeholder** - Unique animated placeholder that cycles through location suggestions
- ✅ **Advanced Loading States** - Custom loading components, skeleton loaders, and shimmer effects
- ✅ **Smooth Fade-in Animations** - Results appear with elegant fade-in transitions
- ✅ **Google Places API Integration** - Full autocomplete and place details support
- ✅ **Current Location Detection** - GPS-based location detection with permissions handling
- ✅ **Recent Searches** - Automatically saves and displays recent location searches
- ✅ **Predefined Places** - Support for custom predefined locations
- ✅ **Advanced Filtering** - City-only filtering, country restrictions, search types
- ✅ **Location Bias & Radius** - Bias results based on current location with radius control
- ✅ **Multiple Themes** - Built-in dark, light, and default themes
- ✅ **Custom Rendering** - Full control over row rendering and styling
- ✅ **Accessibility Support** - Complete accessibility and testing support
- ✅ **TypeScript Ready** - Full TypeScript support (coming soon)
- ✅ **Debounced Search** - Optimized performance with configurable debouncing
- ✅ **Error Handling** - Comprehensive error handling and callbacks
- ✅ **Timeout Management** - Request timeout handling

## 📦 Installation

```bash
npm install @pragadanaveen/react-native-location-autocomplete expo-location
```

### Optional Dependencies
```bash
# For recent searches persistence
npm install @react-native-async-storage/async-storage
```

## 🎯 Basic Usage

```jsx
import React from 'react';
import { LocationAutocomplete } from '@pragadanaveen/react-native-location-autocomplete';

const MyComponent = () => {
  const handleLocationSelected = (location) => {
    console.log('Selected location:', location);
    // location object contains: { address, latitude, longitude, placeId, details }
  };

  return (
    <LocationAutocomplete
      apiKey="YOUR_GOOGLE_PLACES_API_KEY"
      onLocationSelected={handleLocationSelected}
      enableCurrentLocation={true}
      enableRecentSearches={true}
      filterCitiesOnly={true}
      style={{ margin: 16 }}
    />
  );
};
```

## 💰 API Cost Optimization

Your package includes advanced optimizations that **significantly reduce Google Places API costs**:

### Smart Caching System
```jsx
<LocationAutocomplete
  enableCaching={true}        // Cache responses for 5 minutes
  cacheTimeout={300000}       // Customizable cache duration
  maxCacheSize={100}          // Limit memory usage
/>
```

### Request Coalescing
```jsx
<LocationAutocomplete
  enableRequestCoalescing={true}  // Prevent duplicate requests
  // If user types "Mumbai" quickly, only 1 API call is made
/>
```

### Skip Unnecessary Details Calls
```jsx
<LocationAutocomplete
  skipDetailsForPredefined={true}  // Don't call details API for predefined places
  predefinedPlaces={[
    { description: 'Home', latitude: 19.0760, longitude: 72.8777 },
    { description: 'Office', latitude: 19.0896, longitude: 72.8656 }
  ]}
/>
```

### Cost Comparison

**Typical Usage Scenario**: User types "Mumbai" (6 characters)

| Package | API Calls | Cost Impact |
|---------|-----------|-------------|
| **react-native-google-places-autocomplete** | 6 autocomplete + 1 details = **7 calls** | Higher cost |
| **Your Package (optimized)** | 1 autocomplete + 1 details = **2 calls** | **71% cost reduction** |

**With Caching**: Subsequent searches for "Mumbai" = **0 additional calls** for 5 minutes!

## 🎨 Advanced Loading States

### Skeleton Loader with Shimmer
```jsx
<LocationAutocomplete
  apiKey="YOUR_API_KEY"
  onLocationSelected={handleLocationSelected}
  loadingRows={4}
  useShimmer={true}
  enableFadeIn={true}
  fadeInDuration={500}
/>
```

### Custom Loading Component
```jsx
const CustomLoader = () => (
  <View style={{ padding: 20, alignItems: 'center' }}>
    <ActivityIndicator size="large" color="#007AFF" />
    <Text style={{ marginTop: 10, color: '#666' }}>
      Finding amazing places...
    </Text>
  </View>
);

<LocationAutocomplete
  apiKey="YOUR_API_KEY"
  onLocationSelected={handleLocationSelected}
  loadingComponent={<CustomLoader />}
/>
```

### Animated Skeleton Cards
```jsx
<LocationAutocomplete
  apiKey="YOUR_API_KEY"
  onLocationSelected={handleLocationSelected}
  loadingRows={5}
  useShimmer={true}
  enableFadeIn={true}
  fadeInDuration={300}
  theme="dark"
/>
```

## 🎨 Advanced Usage

```jsx
<LocationAutocomplete
  // Basic Configuration
  apiKey="YOUR_API_KEY"
  onLocationSelected={handleLocationSelected}
  initialAddress="Mumbai, India"
  
  // Animated Placeholder (Unique Feature!)
  enableAnimatedPlaceholder={true}
  placeholderOptions={['New York', 'London', 'Tokyo', 'Mumbai']}
  placeholderAnimationDuration={2500}
  
  // Current Location
  enableCurrentLocation={true}
  currentLocationLabel="📍 Use My Location"
  requestLocationPermission={true}
  
  // Recent Searches
  enableRecentSearches={true}
  maxRecentSearches={8}
  recentSearchesLabel="Recent Locations"
  
  // Search Configuration
  filterCitiesOnly={false}
  searchTypes={['establishment', 'geocode']}
  countryCode="IN"
  minLength={3}
  debounceMs={400}
  
  // Location Bias
  radius={50000} // 50km
  strictBounds={false}
  
  // Predefined Places
  predefinedPlaces={[
    { description: 'Home', latitude: 19.0760, longitude: 72.8777 },
    { description: 'Office', latitude: 19.0896, longitude: 72.8656 }
  ]}
  predefinedPlacesAlwaysVisible={true}
  
  // API Optimization (Reduces costs!)
  enableCaching={true}
  cacheTimeout={300000} // 5 minutes
  maxCacheSize={100}
  enableRequestCoalescing={true}
  skipDetailsForPredefined={true}
  
  // Advanced Loading & Animations
  loadingComponent={<CustomLoader />}
  loadingRows={4}
  useShimmer={true}
  enableFadeIn={true}
  fadeInDuration={400}
  
  // Styling & Theming
  theme="dark" // 'default', 'light', 'dark'
  containerStyle={{ backgroundColor: '#f5f5f5' }}
  inputStyle={{ borderRadius: 12, fontSize: 18 }}
  
  // Custom Rendering
  renderRow={(data, index) => (
    <CustomLocationRow data={data} index={index} />
  )}
  renderLeftButton={() => <SearchIcon />}
  renderRightButton={() => <FilterIcon />}
  
  // Callbacks
  onFail={(error) => console.error('Location error:', error)}
  onNotFound={() => console.log('No results found')}
  onTimeout={() => console.log('Request timed out')}
  onFocus={() => console.log('Input focused')}
  onBlur={() => console.log('Input blurred')}
  
  // Accessibility
  accessibilityLabel="Location search input"
  testID="location-autocomplete"
/>
```

## 📋 Complete Props Reference

### Basic Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `apiKey` | string | **required** | Your Google Places API key |
| `onLocationSelected` | function | **required** | Callback when location is selected |
| `initialAddress` | string | `""` | Initial address value |

### Search & Filtering
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `filterCitiesOnly` | boolean | `false` | Filter results to cities only |
| `searchTypes` | array | `[]` | Google Places search types |
| `countryCode` | string | `""` | Restrict to specific country (e.g., 'IN', 'US') |
| `minLength` | number | `2` | Minimum characters before search |
| `debounceMs` | number | `300` | Debounce delay in milliseconds |

### Animated Placeholder (Unique Feature!)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `enableAnimatedPlaceholder` | boolean | `true` | Enable rotating placeholder animation |
| `placeholderOptions` | array | Indian cities | Array of placeholder suggestions |
| `placeholderAnimationDuration` | number | `3000` | Animation cycle duration (ms) |

### Current Location
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `enableCurrentLocation` | boolean | `false` | Show current location option |
| `currentLocationLabel` | string | `"Use Current Location"` | Current location button text |
| `requestLocationPermission` | boolean | `true` | Auto-request location permissions |

### Recent Searches
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `enableRecentSearches` | boolean | `false` | Enable recent searches |
| `maxRecentSearches` | number | `5` | Maximum recent searches to store |
| `recentSearchesLabel` | string | `"Recent Searches"` | Recent searches header text |

### Location Bias & Radius
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `radius` | number | `0` | Search radius in meters |
| `strictBounds` | boolean | `false` | Strict boundary enforcement |

### Predefined Places
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `predefinedPlaces` | array | `[]` | Array of predefined locations |
| `predefinedPlacesAlwaysVisible` | boolean | `false` | Always show predefined places |

### API Optimization (Reduces Costs!)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `enableCaching` | boolean | `true` | Cache API responses to reduce duplicate calls |
| `cacheTimeout` | number | `300000` | Cache expiry time in milliseconds (5 min) |
| `maxCacheSize` | number | `100` | Maximum number of cached responses |
| `enableRequestCoalescing` | boolean | `true` | Prevent duplicate simultaneous requests |
| `skipDetailsForPredefined` | boolean | `true` | Skip details API for predefined places |

### Loading & Animation
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `loadingComponent` | component | `null` | Custom loading component |
| `loadingRows` | number | `3` | Number of skeleton rows to show |
| `useShimmer` | boolean | `false` | Enable shimmer effect on skeleton |
| `enableFadeIn` | boolean | `true` | Enable fade-in animation for results |
| `fadeInDuration` | number | `300` | Fade-in animation duration (ms) |

### Styling & Theming
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `theme` | string | `'default'` | Theme: 'default', 'light', 'dark' |
| `style` | object | `{}` | Input style |
| `containerStyle` | object | `{}` | Container style |
| `inputStyle` | object | `{}` | Input field style |
| `listStyle` | object | `{}` | Results list style |
| `suggestionStyle` | object | `{}` | Individual suggestion style |
| `suggestionTextStyle` | object | `{}` | Suggestion text style |
| `loadingStyle` | object | `{}` | Loading indicator style |
| `currentLocationStyle` | object | `{}` | Current location item style |
| `recentSearchStyle` | object | `{}` | Recent search item style |

### Behavior
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `autoFocus` | boolean | `false` | Auto-focus input on mount |
| `clearButtonMode` | string | `'while-editing'` | Clear button visibility |
| `returnKeyType` | string | `'search'` | Keyboard return key type |
| `timeout` | number | `20000` | Request timeout (ms) |

### Custom Rendering
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `renderRow` | function | `null` | Custom row renderer |
| `renderLeftButton` | function | `null` | Custom left button renderer |
| `renderRightButton` | function | `null` | Custom right button renderer |
| `renderDescription` | function | `null` | Custom description renderer |

### Callbacks
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `onFail` | function | `null` | Error callback |
| `onNotFound` | function | `null` | No results callback |
| `onTimeout` | function | `null` | Timeout callback |
| `onPress` | function | `null` | Item press callback |
| `onFocus` | function | `null` | Input focus callback |
| `onBlur` | function | `null` | Input blur callback |

### Accessibility
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `accessibilityLabel` | string | `null` | Accessibility label |
| `testID` | string | `null` | Test identifier |

## 🎨 Theming Examples

### Dark Theme
```jsx
<LocationAutocomplete
  theme="dark"
  apiKey="YOUR_API_KEY"
  onLocationSelected={handleLocationSelected}
/>
```

### Custom Styling
```jsx
<LocationAutocomplete
  containerStyle={{
    backgroundColor: '#f8f9fa',
    borderRadius: 12,
    padding: 16,
  }}
  inputStyle={{
    backgroundColor: 'white',
    borderColor: '#007AFF',
    borderWidth: 2,
    borderRadius: 8,
    fontSize: 16,
  }}
  suggestionStyle={{
    backgroundColor: 'white',
    paddingVertical: 16,
  }}
  suggestionTextStyle={{
    fontSize: 16,
    color: '#333',
  }}
/>
```

## 🔧 Custom Rendering

### Custom Row Renderer
```jsx
const renderCustomRow = (data, index) => (
  <TouchableOpacity style={customStyles.row}>
    <Icon name="location" size={20} />
    <Text style={customStyles.text}>{data.description}</Text>
    <Text style={customStyles.distance}>{data.distance}</Text>
  </TouchableOpacity>
);

<LocationAutocomplete
  renderRow={renderCustomRow}
  // ... other props
/>
```

### Custom Buttons
```jsx
<LocationAutocomplete
  renderLeftButton={() => (
    <TouchableOpacity style={styles.iconButton}>
      <Icon name="search" size={20} color="#666" />
    </TouchableOpacity>
  )}
  renderRightButton={() => (
    <TouchableOpacity style={styles.iconButton}>
      <Icon name="filter" size={20} color="#666" />
    </TouchableOpacity>
  )}
/>
```

## 🌍 Location Data Structure

The `onLocationSelected` callback receives a comprehensive location object:

```javascript
{
  address: "Mumbai, Maharashtra, India",
  latitude: 19.0760,
  longitude: 72.8777,
  placeId: "ChIJwe1EZjDG5zsRaYxkjY_tpF0",
  details: {
    // Full Google Places API response
    geometry: { location: { lat: 19.0760, lng: 72.8777 } },
    address_components: [...],
    formatted_address: "Mumbai, Maharashtra, India",
    // ... other place details
  }
}
```

## 🚀 Performance Tips

1. **Use debouncing**: Adjust `debounceMs` based on your needs (300-500ms recommended)
2. **Set minimum length**: Use `minLength` to avoid unnecessary API calls
3. **Implement caching**: Cache recent results to reduce API usage
4. **Use country restrictions**: Limit search scope with `countryCode`
5. **Optimize rendering**: Use `renderRow` for complex custom layouts

## 🔐 API Key Setup

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing
3. Enable these APIs:
   - Places API
   - Geocoding API (for reverse geocoding)
4. Create credentials (API Key)
5. Restrict the key to your app's bundle ID/package name

## 🆚 Comparison with react-native-google-places-autocomplete

| Feature | This Package | react-native-google-places-autocomplete |
|---------|-------------|----------------------------------------|
| **API Cost Optimization** | ✅ 70%+ cost reduction | ❌ No optimization |
| **Intelligent Caching** | ✅ 5-minute smart cache | ❌ No caching |
| **Request Coalescing** | ✅ Prevents duplicate calls | ❌ Multiple duplicate calls |
| **Animated Placeholder** | ✅ Unique rotating animation | ❌ Static placeholder |
| **Bundle Size** | 🟢 Lightweight | 🟡 Larger |
| **Current Location** | ✅ Built-in GPS support | ✅ Supported |
| **Recent Searches** | ✅ Built-in | ✅ Supported |
| **Theming** | ✅ 3 built-in themes | ✅ Extensive theming |
| **Custom Rendering** | ✅ Full control | ✅ Full control |
| **TypeScript** | 🟡 Coming soon | ✅ Full support |
| **Modern React** | ✅ Hooks-based | 🟡 Mixed patterns |
| **City Focus** | ✅ Built for location apps | 🟡 General purpose |

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## 📄 License

MIT © [pragadanaveen](https://github.com/pragadanaveen)

## 🙏 Acknowledgments

- Google Places API for location data
- React Native community for inspiration
- All contributors and users

---

**Made with ❤️ for the React Native community**