π§ TypeAheadX
A powerful, dependency-free TypeAhead widget for Flutter β supporting async API search, pagination, keyboard navigation, and full custom styling.
β¨ Features
- π Async search & pagination
- β¨οΈ Keyboard navigation (β β Enter)
- β‘ Debounced queries (no spam calls)
- πΎ Local or remote data search
- π¨ Fully customizable UI (via
TypeAheadXStyle) - π§± No external dependencies β just Flutter
π Installation
Add this to your pubspec.yaml:
dependencies:
typeaheadx: ^0.0.1
Import it:
import 'package:typeaheadx/typeaheadx.dart';
π‘ Basic Example
TypeAheadX(
hintText: 'Search fruits...',
itemList: ['Apple', 'Banana', 'Orange', 'Mango'],
onValueChanged: (value) {
print('Selected: $value');
},
);
π Async Search Example
TypeAheadX(
hintText: 'Search products...',
fetchSuggestions: (query) async {
await Future.delayed(const Duration(milliseconds: 500));
final products = ['Book', 'Bottle', 'Brush', 'Basket'];
return products
.where((item) => item.toLowerCase().contains(query.toLowerCase()))
.toList();
},
onValueChanged: (value) {
print('Selected async item: $value');
},
);
π Paginated API Example
TypeAheadX(
hintText: 'Search paginated items...',
pagination: true,
pageSize: 10,
fetchPaginated: (query, page, pageSize) async {
await Future.delayed(const Duration(milliseconds: 400));
final allItems = List.generate(
100,
(index) => 'Item ${index + 1}',
).where((item) => item.toLowerCase().contains(query.toLowerCase())).toList();
final start = (page - 1) * pageSize;
final end = (start + pageSize).clamp(0, allItems.length);
return allItems.sublist(start, end);
},
onValueChanged: print,
);
π¨ Custom Styling Example
TypeAheadX(
hintText: 'Search in style...',
itemList: ['Apple', 'Banana', 'Orange'],
style: const TypeAheadXStyle(
backgroundColor: Color(0xFF121212),
borderColor: Colors.deepPurple,
highlightColor: Color(0xFF2C2C2C),
textColor: Colors.white,
hintStyle: TextStyle(color: Colors.grey, fontSize: 14),
textStyle: TextStyle(color: Colors.white, fontSize: 14),
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onValueChanged: (value) {
print('Styled search selected: $value');
},
);
βοΈ Constructor Parameters
| Parameter | Type | Description |
|---|---|---|
hintText |
String |
Placeholder text for the search bar |
itemList |
List<String> |
Local list for offline search |
fetchSuggestions |
Future<List<String>> Function(String) |
Async callback for remote data |
fetchPaginated |
Future<List<String>> Function(String, int, int) |
Async paginated callback |
onValueChanged |
Function(String) |
Called when an item is selected |
onChanged |
Function(String)? |
Called on each keystroke |
onSubmitted |
Function(String)? |
Called on enter/search |
enabled |
bool |
Enable or disable the field |
pagination |
bool |
Enable pagination |
pageSize |
int |
Number of items per page |
style |
TypeAheadXStyle |
Custom visual style configuration |
π§± Example App
You can find a full working demo under /example/lib/main.dart.
Run it directly with:
flutter run -t example/lib/main.dart
Demo features:
- Local search
- Async search
- Pagination
- Custom styling
- Keyboard navigation
πΈ Example Preview
Add your screenshot or demo GIF here:
screenshots/demo.gif
π§© Architecture Overview
| Concept | Implementation |
|---|---|
| State management | StreamControllers (no GetX, no setState) |
| Async calls | Debounced Futures |
| UI updates | StreamBuilder + ValueNotifier |
| Styling | TypeAheadXStyle |
| Default colors | AppColors (override-ready) |
π§ͺ Example Snippet (Full Page)
import 'package:flutter/material.dart';
import 'package:typeaheadx/typeaheadx.dart';
void main() => runApp(const ExampleApp());
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TypeAheadX Example',
home: Scaffold(
appBar: AppBar(title: const Text('TypeAheadX Demo')),
body: Padding(
padding: const EdgeInsets.all(16),
child: TypeAheadX(
hintText: 'Search fruits...',
itemList: ['Apple', 'Banana', 'Orange', 'Mango', 'Grapes'],
fetchSuggestions: (query) async {
await Future.delayed(const Duration(milliseconds: 400));
final all = ['Apple', 'Banana', 'Orange', 'Mango', 'Grapes'];
return all
.where((item) =>
item.toLowerCase().contains(query.toLowerCase()))
.toList();
},
onValueChanged: (value) {
debugPrint('Selected: $value');
},
),
),
),
);
}
}
π§ Design Philosophy
- Zero external dependencies
- Fully reactive (no
setState) - Clean, extensible architecture
- Simple API β plug & play
- Easy to customize & contribute
π€ Contributing
Contributions are welcome!
To contribute:
- Fork this repo
- Create a feature branch
- Make your changes
- Run
flutter analyzeanddart format . - Submit a pull request
Please keep your code clean, documented, and well-tested.
π§Ύ CHANGELOG
See CHANGELOG.md for version history.
π License
This project is licensed under the MIT License.
See LICENSE for details.
β€οΈ Maintainer
GitHub β https://github.com/Rahul7f
Twitter β @
βοΈ Support
If you find this package useful:
- β Star the repo
- π Report bugs
- π¬ Suggest features
- π’ Share it with the Flutter community
Together, letβs make TypeAheadX the best search widget for Flutter!