Extensions Pro eliminates boilerplate by adding expressive, chainable helpers directly onto Flutter's built-in types — String, int, DateTime, List, Widget, and BuildContext. Write less, ship faster.
- Zero setup — pure Dart/Flutter extension methods, no code generation, no context providers.
- Chainable API — widget extensions compose naturally (
.withPadding().withBorder().withShadow()). - Null-safe — built for modern Dart with sound null safety throughout.
- Lightweight — only two runtime dependencies (
intl,cached_network_image).
Table of Contents
- Requirements
- Installation
- Extensions Overview
- Screen & Theme Extensions
- Dialog Extensions
- Color Extensions
- Duration Extensions
- Map Extensions
- Toast Extensions
- Clipboard Extensions
- Highlight Extensions
- Nullable Safety Extensions
- Date Extensions
- Time Extensions
- Clock Extensions
- Image Network Extensions
- Local Image Extensions
- Validation Extensions
- Navigation Extensions
- Widget Extensions
- String Extensions
- Int Extensions
- SnackBar Extensions
- List Extensions
- Distance Calculator
- Unit Conversion Extensions
- Status Bar Extensions
- Contributing
- Author
- License
- Support
Requirements
| Minimum version | |
|---|---|
| Dart SDK | ^3.5.3 |
| Flutter | >=1.17.0 |
Installation
Add to your pubspec.yaml:
dependencies:
extensions_pro: ^1.0.32
Then import in your Dart file:
import 'package:extensions_pro/extensions_pro.dart';
Extensions Overview
| Category | Extension Type | Highlights |
|---|---|---|
| Date | DateTime |
format, age, pickers, date math |
| Time | DateTime |
formatted strings, morning/afternoon/evening |
| Clock | DateTime |
digital clock strings |
| Image (Network) | ImageNetworkExtensionsPro |
progress, rounded, cached, shadow |
| Image (Local) | ImageLocalExtensionsPro |
progress, rounded, shadow, fitted box |
| Validation | String |
email, phone, password, OTP, card, hex, username, PIN code, IP, name |
| Navigation | BuildContext |
push, pop, replace, clear stack, named routes |
| Widget | Widget |
padding, border, shadow, rounded, tap, aspect ratio, safe area, hero |
| String | String |
capitalize, reverse, palindrome, camelCase, base64, slug, initials |
| Int | int |
roman, ordinal, words, file size, short, prime, currency, percentage |
| SnackBar | BuildContext |
success, error, gradient, icon, persistent |
| List | List<T> |
sort, find, chunk, dedup, toMap, groupBy, rotate, flatten |
| Distance | num |
Haversine geo distance (km) |
| Unit Conversion | num |
15 categories, 60+ conversions |
| Status Bar | BuildContext |
color, brightness, show/hide |
| Screen & Theme | BuildContext |
width, height, theme, dark mode, tablet check, keyboard, unfocus |
| Dialog | BuildContext |
loading dialog, confirm dialog |
| Color | Color, String |
hex conversion, lighten, darken, light/dark, blend, material swatch |
| Duration | Duration |
mm:ss / HH:mm:ss formatting, human-readable, isZero |
| Map | Map<K, V> |
filter by key/value, query string, isNullOrEmpty |
| Toast | BuildContext |
lightweight overlay toast messages |
| Clipboard | String |
copy to system clipboard |
| Highlight | String |
highlight search matches as TextSpans |
| Nullable Safety | String?, List<T>?, Map<K,V>? |
isNullOrEmpty, isNullOrBlank, orDefault |
Date Extensions
// Date Picker
final date = await context.pickDate(
dateFormatChange: 'yyyy-MM-dd',
primaryColor: Colors.red,
surfaceColor: Colors.white,
headerTextColor: Colors.white,
);
// Output: "2024-11-06"
// Weekday from int (1 = Monday … 7 = Sunday)
3.toWeekDay(); // "Wednesday"
3.toWeekDay(isHalfName: true); // "Wed"
// Difference between two dates
final diff = DateTime(2024, 11, 19).differenceInDays(DateTime(2024, 11, 15));
diff.inDays; // 4
diff.inHours; // 96
// Format
DateTime.now().format('yyyy-MM-dd'); // "2024-11-25"
DateTime.now().format('dd MMM yyyy'); // "25 Nov 2024"
// Start / End of day
DateTime.now().startOfDay; // 2024-11-25 00:00:00
DateTime.now().endOfDay; // 2024-11-25 23:59:59
// Age
DateTime(1990, 11, 25).age; // 34
// Relative checks
DateTime.now().isToday; // true
DateTime.now().isYesterday; // false
DateTime.now().isTomorrow; // false
// Date arithmetic
DateTime.now().addDays(5); // 5 days later
DateTime.now().subtractDays(10); // 10 days earlier
DateTime.now().addMonths(3); // 3 months later
DateTime.now().subtractYears(1); // 1 year earlier
// Day name
DateTime.now().weekdayName; // "Monday"
// Weekend / weekday checks
DateTime(2024, 11, 30).isWeekend; // true (Saturday)
DateTime(2024, 11, 25).isWeekday; // true (Monday)
// Leap year and days-in-month
DateTime(2024, 1, 1).isLeapYear; // true
DateTime(2024, 2, 10).daysInMonth; // 29
// Compare calendar day, ignoring time-of-day
DateTime(2024, 11, 25, 8, 0).isSameDay(DateTime(2024, 11, 25, 23, 30)); // true
// Relative time string
DateTime.now().subtract(const Duration(minutes: 5)).timeAgo; // "5m ago"
DateTime.now().subtract(const Duration(days: 3)).timeAgo; // "3d ago"
// Copy with modified fields
DateTime(2024, 11, 25, 10, 30).copyWith(year: 2025, hour: 8);
// 2025-11-25 08:30:00
// Past / future checks
DateTime.now().subtract(const Duration(days: 1)).isInPast; // true
DateTime.now().add(const Duration(days: 1)).isInFuture; // true
// Week boundaries (Monday start)
DateTime(2024, 11, 27).startOfWeek; // 2024-11-25 (Monday)
DateTime(2024, 11, 27).endOfWeek; // 2024-12-01 23:59:59 (Sunday)
// Month / year boundaries
DateTime(2024, 2, 15).startOfMonth; // 2024-02-01
DateTime(2024, 2, 15).endOfMonth; // 2024-02-29 23:59:59
DateTime(2024, 6, 15).startOfYear; // 2024-01-01
DateTime(2024, 6, 15).endOfYear; // 2024-12-31 23:59:59
// Add / subtract weeks
DateTime(2024, 11, 25).addWeeks(2); // 2024-12-09
DateTime(2024, 11, 25).subtractWeeks(1); // 2024-11-18
// Same month / year checks
DateTime(2024, 11, 5).isSameMonth(DateTime(2024, 11, 25)); // true
DateTime(2024, 3, 1).isSameYear(DateTime(2024, 11, 1)); // true
// ISO-8601 week number
DateTime(2024, 1, 1).weekOfYear; // 1
// "Today" / "Yesterday" / "Tomorrow" or a formatted date
DateTime.now().toRelativeDateLabel(); // "Today"
Time Extensions
// Formatted strings
DateTime.now().currentDateFormatted; // "2024-11-25"
DateTime.now().currentTimeFormatted; // "14:30"
// Time-of-day checks
DateTime.now().isMorning; // true (before 12 PM)
DateTime.now().isAfternoon; // false (12 PM – 6 PM)
DateTime.now().isEvening; // false (after 6 PM)
// Time Picker
final picked = await context.pickTime();
picked?.format(context); // "11:08 PM"
Clock Extensions
// Live digital clock — call inside a Timer.periodic(Duration(seconds: 1), ...)
DateTime.now().toDigitalTimeWithSeconds(); // "11:42:32"
DateTime.now().toDigitalTime(); // "11:42"
Image Network Extensions
// With progress indicator
ImageNetworkExtensionsPro.networkImageWithProgress(
url: 'https://picsum.photos/200',
width: 100,
height: 100,
fit: BoxFit.cover,
);
// With rounded corners
ImageNetworkExtensionsPro.networkImageWithRoundedCorners(
url: 'https://picsum.photos/200',
width: 100,
height: 100,
borderRadius: 16.0,
);
// With placeholder widget
ImageNetworkExtensionsPro.networkImageWithPlaceholder(
url: 'https://picsum.photos/200',
width: 100,
height: 100,
placeholder: const Center(child: Text('Loading...')),
);
// Cached (uses cached_network_image)
ImageNetworkExtensionsPro.cachedNetworkImage(
url: 'https://picsum.photos/200',
width: 100,
height: 100,
);
// With drop shadow
ImageNetworkExtensionsPro.networkImageWithShadow(
url: 'https://picsum.photos/200',
width: 100,
height: 100,
elevation: 10.0,
shadowColor: Colors.black45,
);
Local Image Extensions
// With progress indicator and error handling
ImageLocalExtensionsPro.assetImageWithProgress(
'assets/logo.png',
context: context,
width: 150,
height: 150,
);
// With rounded corners
ImageLocalExtensionsPro.assetImageWithRoundedCorners(
'assets/logo.png',
context: context,
width: 150,
height: 150,
borderRadius: 16.0,
);
// With shadow
ImageLocalExtensionsPro.assetImageWithShadow(
'assets/logo.png',
context: context,
width: 150,
height: 150,
elevation: 8.0,
shadowColor: Colors.blueAccent,
);
// Scaled with FittedBox
ImageLocalExtensionsPro.assetImageWithFittedBox(
'assets/logo.png',
width: 150,
height: 150,
);
Validation Extensions
// Email
'user@example.com'.isValidEmail(); // true
'invalid-email'.isValidEmail(); // false
// Phone (E.164 format)
'+1234567890'.isValidPhoneNumber(); // true
// Password (min 8 chars, upper + lower + digit)
'Flutter@123'.isStrongPassword(); // true
'weak'.isStrongPassword(); // false
// Password match
'Pass123'.isPasswordMatch('Pass123'); // true
'Pass123'.isPasswordMatch('pass123'); // false
// OTP (exactly 6 digits)
'123456'.isValidOTP(); // true
'12345a'.isValidOTP(); // false
// Credit card (Luhn algorithm — handles spaces/dashes)
'4532015112830366'.isValidCreditCardNumber(); // true
'4532 0151 1283 0366'.isValidCreditCardNumber(); // true
// Hex color
'#FF5733'.isValidHexColor(); // true
'ZZZ'.isValidHexColor(); // false
// Digits only (no decimals or signs)
'123456'.isDigitsOnly(); // true
'12.34'.isDigitsOnly(); // false
// Alphanumeric
'Abc123'.isAlphaNumeric(); // true
'Abc@123'.isAlphaNumeric(); // false
// Geo coordinates
'37.7749'.isValidLatitude(); // true
'100.0'.isValidLatitude(); // false (out of range)
'-122.4194'.isValidLongitude(); // true
'200.0'.isValidLongitude(); // false
// URL
'https://flutter.dev'.isValidUrl(); // true
'not a url'.isValidUrl(); // false
// Username (3-20 chars: letters, digits, underscore)
'flutter_dev1'.isValidUsername(); // true
'ab'.isValidUsername(); // false
// Indian PIN code (6 digits, first non-zero)
'411001'.isValidPinCode(); // true
'011001'.isValidPinCode(); // false
// IPv4 address
'192.168.1.1'.isValidIPAddress(); // true
'256.1.1.1'.isValidIPAddress(); // false
// Person's name (letters, spaces, apostrophes, hyphens)
"Mary-Jane O'Brien".isValidName(); // true
'John123'.isValidName(); // false
Navigation Extensions
// Push a new screen
context.push(const DetailScreen());
// Replace the current screen
context.pushReplacement(const HomeScreen());
// Pop back
context.pop();
// Pop with a result
context.pop('result');
// Clear the entire stack and push a new screen
context.pushAndRemoveUntil(const LoginScreen());
// Named routes
context.pushNamed('/details', arguments: {'id': 42});
context.popUntil('/home');
context.canPop; // true if there's a route to pop
Widget Extensions
All extensions are chainable:
// Individual usage
Text('Hello').withPadding(const EdgeInsets.all(16));
Text('Hello').withMargin(const EdgeInsets.all(8));
Text('Hello').centered();
Text('Hello').withBorder(color: Colors.blue, width: 2.0);
Text('Hello').withShadow(blurRadius: 8.0, color: Colors.black26);
Text('Hello').withRoundedCorners(radius: 12.0);
Text('Hello').withVisibility(isLoggedIn);
Text('Hello').onTap(() => print('tapped'));
Text('Hello').onLongPress(() => print('long pressed'));
Text('Hello').withOpacity(0.5);
Text('Hello').withAspectRatio(16 / 9);
Text('Hello').withSafeArea();
Text('Hello').withBackgroundColor(Colors.amber);
Text('Hello').withHero('hello-tag');
// Chained
Text('Hello World')
.withPadding(const EdgeInsets.all(16))
.withBorder(color: Colors.blue, width: 2.0)
.withShadow(blurRadius: 8.0)
.withRoundedCorners(radius: 12.0);
String Extensions
'flutter'.capitalize(); // "Flutter"
'flutter'.reverse(); // "rettulf"
'snake_case_string'.toCamelCase(); // "SnakeCaseString"
'Flutter is awesome'.removeWhitespace(); // "Flutterisawesome"
'Flutter is amazing'.truncate(10); // "Flutter is..."
'Order1234'.extractNumbers(); // "1234"
'madam'.isPalindrome(); // true
'flutter'.isPalindrome(); // false
'flutter is fun'.countOccurrences('u'); // 2
'123'.isNumeric(); // true (parses as double)
'abc'.isNumeric(); // false
// Title case
'flutter is awesome'.toTitleCase(); // "Flutter Is Awesome"
// Mask sensitive data (keeps first/last N characters visible)
'1234567890123456'.mask(); // "************3456"
'user@example.com'.mask(visibleStart: 2, visibleEnd: 0); // "us**************"
// Initials (great for avatar placeholders)
'John Doe'.toInitials(); // "JD"
// URL-friendly slug
'Hello, Flutter World!'.toSlug(); // "hello-flutter-world"
// Case-insensitive comparison
'Flutter'.equalsIgnoreCase('flutter'); // true
// Base64 encode / decode
'Flutter'.toBase64(); // "Rmx1dHRlcg=="
'Rmx1dHRlcg=='.fromBase64(); // "Flutter"
// Word count
'Flutter is awesome'.wordCount(); // 3
// Strip everything except letters, digits, and spaces
'Hello, World! #2024'.removeSpecialCharacters(); // "Hello World 2024"
// Pluralize based on count
'item'.pluralize(1); // "item"
'item'.pluralize(5); // "items"
'box'.pluralize(2, plural: 'boxes'); // "boxes"
Int Extensions
// Duration string
125.toDurationString; // "2m 5s"
// Roman numerals (1–3999)
1990.toRoman; // "MCMXC"
4.toRoman; // "IV"
// Ordinal
1.toOrdinal(); // "1st"
22.toOrdinal(); // "22nd"
103.toOrdinal(); // "103rd"
11.toOrdinal(); // "11th"
// File size
1024.toFileSize(); // "1.00 KB"
1048576.toFileSize(); // "1.00 MB"
512.toFileSize(); // "512 B"
// Short format
12340.toShortString(); // "12.3K"
1200000.toShortString(); // "1.2M"
// Number to words (Indian system)
1234.toWords(); // "one thousand two hundred thirty four"
100000.toWords(); // "one lakh"
10000000.toWords(); // "one crore"
// Weekday name (1 = Monday, 7 = Sunday)
3.toWeekDay(); // "Wednesday"
3.toWeekDay(isHalfName: true); // "Wed"
// Prime check
17.isPrime; // true
4.isPrime; // false
// Currency formatting (powered by intl)
1234567.toCurrencyString(); // "₹1,234,567"
1000.toCurrencyString(symbol: '\$'); // "$1,000"
// Percentage
45.toPercentageString(); // "45%"
// Treat as seconds and format as a clock string
125.secondsToTimeString(); // "02:05"
SnackBar Extensions
// Success (green)
context.showSuccessSnackBar('Saved successfully!');
// Error (red)
context.showErrorSnackBar('Something went wrong!');
// Custom color and duration
context.showCustomSnackBar(
message: 'Custom message',
backgroundColor: Colors.indigo,
duration: const Duration(seconds: 4),
action: SnackBarAction(label: 'UNDO', onPressed: () {}),
);
// With icon
context.showIconSnackBar(
message: 'Data saved!',
icon: Icons.check_circle,
backgroundColor: Colors.green,
);
// Gradient (purple → blue)
context.showGradientSnackBar('Beautiful gradient!');
// Persistent (stays until dismissed)
context.showPersistentSnackBar(
message: 'Tap DISMISS to close.',
dismissColor: Colors.white,
);
List Extensions
final numbers = [1, 2, 3, 4, 5, 6, 6, 7, 8, 9];
numbers.firstOrDefault(); // 1
numbers.lastOrDefault(); // 9
numbers.addIfNotExists(10); // adds 10 only if not present
numbers.removeDuplicates(); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.safeSublist(2, 5); // [3, 4, 5] — no RangeError
numbers.find((x) => x > 5); // 6
// Sort by property
final names = ['Zara', 'Anna', 'Mike'];
names.sortBy((n) => n); // ['Anna', 'Mike', 'Zara']
names.sortBy((n) => n, descending: true); // ['Zara', 'Mike', 'Anna']
// Convert to map
numbers.toMap((x) => x.toString());
// {'1': 1, '2': 2, '3': 3, ...}
// Indexed iteration
numbers.forEachIndexed((index, item) {
print('[$index] $item');
});
// Split into chunks
numbers.chunked(3);
// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
// Deduplicate by a derived key, keeping the first match
['apple', 'apricot', 'banana', 'blueberry'].distinctBy((s) => s[0]);
// ['apple', 'banana']
// Numeric aggregates
final scores = [1, 2, 3, 4, 5];
scores.sumPro; // 15
scores.averagePro; // 3.0
scores.maxPro; // 5
scores.minPro; // 1
// Random element
numbers.randomElement(); // a random item, or null if the list is empty
// Swap two elements in place
final letters = ['a', 'b', 'c'];
letters.swap(0, 2); // ['c', 'b', 'a']
// Group elements by a derived key
['apple', 'apricot', 'banana'].groupBy((w) => w[0]);
// {'a': ['apple', 'apricot'], 'b': ['banana']}
// Rotate the list
[1, 2, 3, 4, 5].rotate(2); // [4, 5, 1, 2, 3]
[1, 2, 3, 4, 5].rotate(-1); // [2, 3, 4, 5, 1]
// Flatten a list of lists
[[1, 2], [3], [4, 5]].flatten(); // [1, 2, 3, 4, 5]
// Remove null elements
<int?>[1, null, 2, null, 3].whereNotNull(); // [1, 2, 3]
Distance Calculator
Uses the Haversine formula for accurate great-circle distance.
final distance = 0.calculateDistance(
startLatitude: 28.7041, // Delhi
startLongitude: 77.1025,
endLatitude: 19.0760, // Mumbai
endLongitude: 72.8777,
);
print('${distance.toStringAsFixed(2)} km'); // 1158.91 km
Unit Conversion Extensions
All conversions are extension getters/methods on num (works with int and double).
// ── Length ────────────────────────────────────
5000.toKilometersPro; // m → km
5000.toMilesPro; // m → mi
5000.toMetersFromFeetPro; // ft → m
5000.toCentimetersFromInchesPro; // in → cm
5000.toInchesFromCentimetersPro; // cm → in
// ── Temperature ───────────────────────────────
25.toFahrenheitPro; // °C → °F → 77.0
77.toCelsiusPro; // °F → °C → 25.0
// ── Area ──────────────────────────────────────
10000.toAcresPro; // m² → acres
10000.toSquareMetersPro; // ft² → m²
// ── Weight ────────────────────────────────────
70.toPoundsPro; // kg → lb
154.toKilogramsPro; // lb → kg
28.toGramsPro; // oz → g
100.toOuncesPro; // g → oz
// ── Speed ─────────────────────────────────────
100.toMilesPerHourPro; // km/h → mph
62.toKilometersPerHourPro; // mph → km/h
// ── Time ──────────────────────────────────────
3600.toMinutesPro; // s → min → 60.0
3600.toHoursPro; // s → hr → 1.0
24.toDaysPro; // hr → days → 1.0
// ── Volume ────────────────────────────────────
100.toGallonsPro; // L → gal
10.toLitersPro; // gal → L
1.toCubicFeetPro; // m³ → ft³
35.toCubicMetersFromCubicFeetPro; // ft³ → m³
// ── Digital Storage ───────────────────────────
2048.toGBPro; // MB → GB
2.toMBPro; // GB → MB
500.toKilobytesPro; // MB → KB
512.toMegabytesPro; // KB → MB
// ── Energy ────────────────────────────────────
1000.toCaloriesPro; // J → cal
239.toJoulesPro; // cal → J
// ── Pressure ──────────────────────────────────
101325.toBarPro; // Pa → bar
1.toPascalPro; // atm → Pa
// ── Angle ─────────────────────────────────────
90.toRadiansPro; // deg → rad → 1.5708
1.5708.toDegreesPro; // rad → deg → 90.0
// ── Currency (indicative rates) ───────────────
100.toEURPro; // USD → EUR
92.toUSDPro; // EUR → USD
// ── Electricity ───────────────────────────────
1.5.toMillivoltsPro; // V → mV
1500.toVoltsFromMillivoltsPro; // mV → V
// ── Fuel Efficiency ───────────────────────────
25.toLPer100kmPro; // MPG → L/100km
9.41.toMPGPro; // L/100km → MPG
// ── Power ─────────────────────────────────────
500.toKilowattsPro; // W → kW
0.5.toWattsPro; // kW → W
// ── Data Rate ─────────────────────────────────
10.toKbpsPro; // Mbps → Kbps
10000.toMbpsPro; // Kbps → Mbps
// ── Power Consumption ─────────────────────────
1000.toKilowattHoursPro; // Wh → kWh
1.toWattHoursPro; // kWh → Wh
Status Bar Extensions
// Set color and icon brightness
context.setStatusBarColor(Colors.blue, darkIcons: false);
// Hide the status bar completely
context.hideStatusBar();
// Restore the status bar
context.showStatusBar();
// Set brightness
context.setStatusBarBrightness(Brightness.dark);
// Set icon color only
context.setStatusBarTextColor(true); // dark icons
context.setStatusBarTextColor(false); // light icons
Screen & Theme Extensions
// Screen dimensions
context.screenSize; // Size(360.0, 800.0)
context.screenWidth; // 360.0
context.screenHeight; // 800.0
// Theme shortcuts
context.theme; // Theme.of(context)
context.textTheme; // Theme.of(context).textTheme
context.isDarkMode; // true if the current theme brightness is dark
// Dismiss the keyboard from anywhere
context.unfocus();
// Orientation and device class
context.orientation; // Orientation.portrait
context.isTablet; // true if the shortest side is >= 600dp
// Safe area (notches, status/navigation bars)
context.safeAreaPadding; // EdgeInsets(...)
// Keyboard visibility
context.keyboardHeight; // height in logical pixels, 0 when hidden
context.isKeyboardVisible; // true when the keyboard is open
Dialog Extensions
// Show a non-dismissible loading spinner, then close it later
context.showLoadingDialog();
await doSomeWork();
context.hideLoadingDialog();
// Yes/No confirmation dialog
final confirmed = await context.showConfirmDialog(
title: 'Delete item?',
message: 'This action cannot be undone.',
confirmText: 'Delete',
cancelText: 'Cancel',
);
if (confirmed) {
// proceed with deletion
}
Color Extensions
// Color to hex string
const Color(0xFF336699).toHex(); // "#336699"
const Color(0xFF336699).toHex(includeAlpha: true); // "#ff336699"
const Color(0xFF336699).toHex(leadingHash: false); // "336699"
// Hex string to Color
'#336699'.toColor(); // Color(0xff336699)
'369'.toColor(); // Color(0xff336699) — shorthand hex
// Lighten / darken
const Color(0xFF336699).lighten(0.2);
const Color(0xFF336699).darken(0.2);
// Perceived brightness
Colors.white.isLight; // true
Colors.black.isDark; // true
// Blend two colors
Colors.black.blend(Colors.white, 0.5); // a 50/50 mix
// Build a MaterialColor swatch (50–900) from any Color
const Color(0xFF336699).toMaterialColor();
Duration Extensions
// Formats as mm:ss, or HH:mm:ss once it reaches an hour
const Duration(seconds: 125).toFormattedString(); // "02:05"
const Duration(hours: 1, minutes: 2, seconds: 3).toFormattedString(); // "01:02:03"
// Human-readable duration
const Duration(days: 1, hours: 2, minutes: 3).toHumanReadable(); // "1d 2h 3m"
Duration.zero.toHumanReadable(); // "0s"
// Zero check
Duration.zero.isZero; // true
Map Extensions
final map = {'a': 1, 'b': 2, 'c': 3};
// Filter by key or value
map.filterKeys((k) => k != 'b'); // {'a': 1, 'c': 3}
map.filterValues((v) => v > 1); // {'b': 2, 'c': 3}
// Build a URL query string
{'q': 'flutter dev', 'page': 2}.toQueryString(); // "q=flutter+dev&page=2"
// Map<K, V>?
Map<String, int>? config;
config.isNullOrEmpty; // true
Toast Extensions
// Shows a lightweight overlay toast — no Scaffold required
context.showToast('Saved!');
context.showToast(
'Something went wrong',
duration: const Duration(seconds: 3),
backgroundColor: Colors.red,
);
Clipboard Extensions
// Copy any string to the system clipboard
await 'Referral code: FLUTTER25'.copyToClipboard();
Highlight Extensions
// Highlight every case-insensitive occurrence of a search term
RichText(
text: TextSpan(
children: 'Hello World Hello'.highlightOccurrences(
'hello',
baseStyle: const TextStyle(color: Colors.black),
highlightStyle: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
backgroundColor: Colors.yellow,
),
),
),
);
Nullable Safety Extensions
// String?
String? name;
name.isNullOrEmpty; // true
name.isNullOrBlank; // true
name.orDefault('Guest'); // "Guest"
// List<T>?
List<int>? items;
items.isNullOrEmpty; // true
// Map<K, V>?
Map<String, int>? settings;
settings.isNullOrEmpty; // true
Contributing
Contributions, issues, and feature requests are welcome!
- Fork the repository.
- Create a branch for your change (
git checkout -b feature/my-feature). - Make your changes and add/update tests where relevant.
- Run
flutter analyzeandflutter testto make sure everything passes. - Open a pull request describing what you changed and why.
Found a bug or have an idea? Open an issue.
Author
Sanjay Sharma — Full-Stack & Cross-Platform Mobile Developer
Android · iOS · Swift · Flutter · Dart · Node.js
License
Support
If Extensions Pro saved you time, consider buying me a coffee — it keeps the extensions coming! ☕
