handy_extensions 0.2.26 copy "handy_extensions: ^0.2.26" to clipboard
handy_extensions: ^0.2.26 copied to clipboard

Handy Extension is just a simple library with extensions to the core libraries to make them more handy and quicker to use.

HandyExtensions #

Developed with πŸ’™ by Ngonidzashe Mangudya

style: very good analysis License: MIT codecov


Handy Extension is a comprehensive library with extensions to Dart's core types and Flutter's BuildContext to make development more efficient and code more readable.

I don't know how "deadly" this is but I just use it anyway.

Extensions On: #

Getting started #

Add as a dependency #

dependencies:
  handy_extensions: <version>

Usage #

BuildContext #

Get Screen Dimensions

// Get screen height
double screenHeight = context.height;

// Get screen width
double screenWidth = context.width;

String #

Country Code to Emoji

String country = 'ZW';
String emoji = country.countryEmoji; // => πŸ‡ΏπŸ‡Ό

Text Case Transformations

String title = 'hello world';
String titleCase = title.titleCase; // => Hello world
String headingCase = title.headingCase; // => Hello World

String Parsing

String number = '42.5';

// Check if string is numeric
bool isNum = number.isNumeric; // => true

// Parse to double or int safely
double? doubleValue = number.toDoubleOrNull; // => 42.5
int? intValue = '42'.toIntOrNull; // => 42

String Comparisons

String text = 'Hello';

// Case-insensitive matching
bool matches = text.matches('hello'); // => true

// Check if all uppercase
bool isUpper = 'HELLO'.isAllCaps; // => true

// Check if strings have same characters (different order)
bool sameChars = 'hello'.hasSameCharacters('olleh'); // => true

List #

Partitioning

List<int> numbers = [1, 2, 3, 4, 5, 6];

// Split into chunks
List<List<int>> chunks = numbers.partition(chunkSize: 3); 
// => [[1, 2, 3], [4, 5, 6]]

// Partition based on condition
List<List<int>> evenOdd = numbers.partitionWhere((n) => n.isEven);
// => [[2, 4, 6], [1, 3, 5]]

// Split into equal-sized sublists
List<List<int>> split = numbers.splitInto(chunkSize: 2);
// => [[1, 2, 3], [4, 5, 6]]

Random Selection

List<String> words = ["Hello", "World", "Dart"];

// Get random item
String randomWord = words.randomItem();

// Get multiple random items (no duplicates)
List<String> randomWords = words.randomItems(count: 2);

Safe Operations

List<String> items = ['a', 'b', 'c'];

// Safe first where operation
String? found = items.firstWhereOrNull((item) => item == 'a'); // => 'a'

// Safe index access
String? item = items.getAt(1); // => 'b'
String? invalid = items.getAt(10); // => null

// Check if index is valid
bool valid = items.isValidIndex(1); // => true

Grouping and Organization

List<Map<String, dynamic>> movies = [
  {"title": "Avengers", "year": "2019"},
  {"title": "Creed", "year": "2019"},
  {"title": "Jumanji", "year": "2020"},
];

// Group by field
Map<String, List<Map<String, dynamic>>> grouped = 
    movies.groupBy((m) => m["year"]);

List Manipulation

List<int> numbers = [1, 2, 3, 4, 5];

// Swap elements
numbers.swap(0, 4); // [5, 2, 3, 4, 1]

// Swap ranges
numbers.swapRange(0, 2, 3); // [4, 5, 3, 1, 2]

// Check for duplicates
bool hasDups = [1, 2, 3, 2].hasDuplicates(); // => true

// Check if contains any of multiple items
bool containsAny = numbers.containsSome([6, 7, 8]); // => false

// Compare lists regardless of order
bool same = [1, 2, 3].same([3, 1, 2]); // => true

Update Operations

List<int> numbers = [1, 2, 3, 4, 5];

// Update elements matching condition
numbers.updateWhere(
  (n) => n.isEven,  // predicate
  (n) => n * 2,     // update function
);
// Result: [1, 4, 3, 8, 5]

// Update or create if no matches found
List<String> users = ['alice', 'bob'];
bool updated = users.updateWhereOrCreate(
  (user) => user.startsWith('c'),
  (user) => user.toUpperCase(),
  () => 'charlie', // created if no 'c' names found
);

Map #

Map Transformations

Map<String, int> original = {'a': 1, 'b': 2, 'c': 3};

// Swap keys and values
Map<int, String> swapped = original.swap; // {1: 'a', 2: 'b', 3: 'c'}

// Create a copy
Map<String, int> copied = original.copy;

// Remove null values
Map<String, int?> withNulls = {'a': 1, 'b': null, 'c': 3};
Map<String, int?> cleaned = withNulls.removeNulls; // {'a': 1, 'c': 3}

Map Operations

Map<String, int> map = {'a': 1, 'b': 2, 'c': 3, 'd': 4};

// Reorder entries
Map<String, int> reordered = map.adjustOrder(1, 3);

// Get value or default
int value = map.getOrDefault('e', 0); // => 0

DateTime #

Readable Formats

DateTime date = DateTime(2022, 3, 15, 14, 30, 45);

// Various readable formats
String readable = date.readableDate; // => Tuesday 15 March 2022
String readableDateTime = date.readableDateTime; // => March 15, 2022 14:30:45
String time = date.readableTime; // => 14:30:45
String timeFormat = date.timeFormat; // => 02:30pm
String combined = date.readableDateTimeFormat; // => Tuesday 15 March 2022, 02:30pm

Date Components

DateTime date = DateTime(2022, 3, 15);

// Get components
String day = date.getDay; // => Tuesday
String shortDay = date.getShortDay; // => Tue
int dayOfMonth = date.getDate; // => 15
String month = date.getMonth; // => March
String shortMonth = date.getShortMonth; // => Mar
String year = date.getYear; // => 2022

Time Intelligence

DateTime now = DateTime.now();
DateTime past = now.subtract(Duration(hours: 2));

// Time ago
String ago = past.timeAgo; // => 2h

// Time of day
String timeOfDay = DateTime(2022, 1, 1, 9, 0).timeOfDayStr; // => Morning
String emoji = DateTime(2022, 1, 1, 21, 0).timeOfDayEmoji; // => πŸŒ™

// Smart description
String desc = past.describe; // => 02:30pm (for today) or Yesterday, etc.

Date Comparisons

DateTime date1 = DateTime(2022, 3, 15, 9, 0);
DateTime date2 = DateTime(2022, 3, 15, 18, 0);
DateTime date3 = DateTime(2022, 3, 16);

// Check if same day (ignoring time)
bool sameDay = date1.isSameDayForYear(date2); // => true

// Check if same day/month (ignoring year)
bool sameDayMonth = date1.isSameDay(DateTime(2023, 3, 15)); // => true

// Check if between dates
bool between = date1.isBetween(
  DateTime(2022, 1, 1), 
  DateTime(2022, 12, 31)
); // => true

Num/Int #

Duration Creation

// Create durations easily
Duration micro = 500.microseconds;
Duration milli = 1500.milliseconds; // or 1500.ms
Duration sec = 30.seconds;
Duration min = 5.minutes;
Duration hr = 2.hours;
Duration day = 3.days;
Duration week = 2.weeks;
Duration month = 1.months; // ~30.44 days
Duration year = 1.years; // calculated based on current date

// Combine durations
Duration total = 1.weeks + 2.days + 3.hours + 4.minutes;

Number Operations

// Check if number is in range
bool inRange = 5.isBetween(1, 10); // => true

Iterable #

Interspersing Elements

List<String> words = ["Hello", "World", "Dart"];

// Insert separator between elements
Iterable<String> withCommas = words.intersperse(",");
// Result: [Hello, ,, World, ,, Dart]

// Insert separators conditionally
Iterable<int> numbers = [1, 2, 3, 4, 5];
Iterable<dynamic> conditional = numbers.intersperseWith(
  (n) => n.isEven ? ':' : null
);
// Result: [1, 2, :, 3, 4, :, 5]

// Insert at specific index
Iterable<String> atIndex = words.intersperseAt(1, '-');
// Result: [Hello, World, -, Dart]

// Insert at end
Iterable<String> atEnd = words.intersperseAtLast('!');
// Result: [Hello, World, Dart, !]

Nullable Extensions #

Nullable String

String? name = null;
String? greeting = 'Hello';

// Check if string (not null)
bool isString = name.isString; // => false
bool isGreeting = greeting.isString; // => true

// Get value or empty string
String safe = name.orEmpty; // => ''
String value = greeting.orEmpty; // => 'Hello'

// Check if not null and not empty/whitespace
bool hasContent = name.isNotReallyEmpty; // => false
bool greetingHasContent = greeting.isNotReallyEmpty; // => true

Nullable Int

int? number = null;
int? value = 42;

// Check if int (not null)
bool isInt = number.isInt; // => false
bool isValue = value.isInt; // => true

Nullable List

List<int?> numbers = [1, null, 3, 4];

// Find first element matching condition (handles nulls safely)
int? firstEven = numbers.firstOrNullWhere((n) => n != null && n.isEven); // => 4
int? firstNull = numbers.firstOrNullWhere((n) => n == null); // => null

Nullable Iterable

Iterable<String?> items = ['hello', null, 'world', null];

// Remove all null elements
Iterable<String> nonNull = items.withoutNullElements();
// Result: ['hello', 'world']

General Extensions #

Available on any type:

// Apply a function to any value
int result = 5.let((it) => it * 2); // => 10

String processed = "hello".let((s) => s.toUpperCase()); // => "HELLO"

// Check if any value is null
bool isNull = someValue.isNull;

Utility Types #

The library also includes utility enums:

enum HapticFeedbackType {
  light,
  medium,
  heavy,
  selection,
  vibrate,
}

Additional Information #

This library provides over 100 extension methods across Dart's core types and Flutter's BuildContext. All extensions are designed to be intuitive, well-documented, and thoroughly tested.

You can contribute additional extensions to help make Dart development even more efficient!


6
likes
150
points
683
downloads

Publisher

verified publisheriamngoni.co.zw

Weekly Downloads

Handy Extension is just a simple library with extensions to the core libraries to make them more handy and quicker to use.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on handy_extensions