Perfect Text Field
An all-in-one Flutter text input toolkit — editable, decorated, reactive, and smart.
Build rich input fields with token highlighting, auto-complete, number formatting, and custom behaviors, all fully editable.
✨ Features
📌 PerfectTextField
- A drop-in replacement for
TextField
/TextFormField
. - Works with
PerfectTextController
for advanced decorations and focus control. - Supports token highlights, autocomplete, number input formatting, and more.
📋 PerfectTextController
- Detects and highlights:
- Hashtags (#example)
- Mentions (@username)
- Emails (user@example.com)
- Phone Numbers (+1 234 567 8900 via dlibphonenumber)
DecorationStyle
per token: background color, text style, tap-to-delete option.- Reactive: Get real-time updates via
rxText
notifier. - Full focus control:
requestFocus()
,selectAll()
, etc. - Smart delimiter matching for accurate highlighting.
🔍 PerfectAutocomplete
- Material Design styled autocomplete widget.
- Async or sync options building.
- Keyboard navigation (up/down arrows).
- Fully customizable field and options list.
- Built on top of
PerfectRawAutocomplete
.
🛠 PerfectRawAutocomplete
- Raw, flexible, low-level autocomplete engine.
- Overlay-based options with highlighted selection.
- Provides building blocks for custom autocomplete UIs.
🔢 DecimalNumberFormatter
- Text input formatter to restrict number fields:
- Minimum and maximum values.
- Decimal precision (e.g., only 2 digits after
.
). - Smart correction: replaces last character if overflow.
🗑 DeletePreviousCharIntent
- Custom intent to delete the previous character inside a
PerfectTextController
. - Useful for keyboard shortcut integrations.
🚀 Getting Started
Add to your pubspec.yaml
:
dependencies:
perfect_text_field: latest
🧩 Quick Example
import 'package:flutter/material.dart';
import 'package:perfect_text_field/perfect_text_field.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final controller = PerfectTextController(
text: 'Welcome to #Flutter! Contact @support or email hello@flutter.dev.',
decorations: [
DecorationStyle(
type: DecorationType.hashtag,
backgroundColor: Colors.blue.withOpacity(0.2),
textStyle: const TextStyle(color: Colors.blue),
),
DecorationStyle(
type: DecorationType.mention,
backgroundColor: Colors.green.withOpacity(0.2),
textStyle: const TextStyle(color: Colors.green),
),
DecorationStyle(
type: DecorationType.email,
backgroundColor: Colors.orange.withOpacity(0.2),
textStyle: const TextStyle(color: Colors.orange),
),
],
phoneRegion: 'US',
);
return MaterialApp(
title: 'Perfect Text Field Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: const Text('Perfect TextField Example')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: PerfectTextField(
controller: controller,
maxLines: null,
decoration: const InputDecoration(
hintText: 'Type #tags, @mentions, emails, phones...',
),
),
),
),
);
}
}
🎨 Autocomplete Example
PerfectAutocomplete<String>(
optionsBuilder: (textEditingValue) async {
if (textEditingValue.text.isEmpty) return const Iterable<String>.empty();
return ['Apple', 'Banana', 'Cherry'].where(
(option) => option.toLowerCase().contains(textEditingValue.text.toLowerCase()),
);
},
onSelected: (option) => print('Selected: $option'),
);
📜 License
MIT License.
See the LICENSE file for full details.