mayr_extensions 1.0.1
mayr_extensions: ^1.0.1 copied to clipboard
A comprehensive set of handy Dart and Flutter extensions to make your code cleaner, shorter, and more expressive.
๐งฐ Flutter Extension Utils #
Extensions that just make sense.
A handy collection of Dart and Flutter extension methods to supercharge your development experience โ clean syntax, reusable logic, and expressive code, all in one lightweight package.
Designed to save you time, reduce boilerplate, and improve readability across widgets, strings, numbers, booleans, and BuildContext.
๐ Installation & Setup #
The package can be installed using the command
flutter pub add mayr_extensions
And can then be imported using
import 'package:mayr_extensions/mayr_extensions.dart';
๐ Features #
๐งฑ BuildContext Extensions #
-
formโ Easily access the nearestFormStateusingcontext.form. -
navigatorโ Shorthand forNavigator.of(context). -
overlayโ Access the currentOverlayStatefrom the context. -
scaffoldโ Retrieve the nearestScaffoldStatewithcontext.scaffold.
ScaffoldMessenger
-
scaffoldMessengerโ Quickly get theScaffoldMessengerStatefor showing snackbars and more. -
void showSnackBar(String content, {Duration? duration, SnackBarBehavior behavior = SnackBarBehavior.fixed})- Quickly show a SnackBar without manually accessing ScaffoldMessenger.
Media Query
-
mediaQueryโ AccessMediaQueryDatafrom context. -
platformBrightnessโ Get the system's brightness setting (Brightness.darkorBrightness.light). -
platformInDarkMode|platformInLightModeโ Returnstruebased on the app's current brightness mode. -
widgetSizeโ Get the rendered size of the widget associated with the context. -
widgetHeightโ Convenience getter for just the height of the widget. -
widgetWidthโ Convenience getter for just the width.
Media Query Orientation
-
orientationโ Access the current screen orientation (portraitorlandscape). -
isLandscape/isPortraitโ Easy checks for current orientation. -
widgetShortestSideโ Useful for responsive layouts based on the device's shortest screen edge. -
isPhoneโ Returnstrueif the device is considered a phone. -
isSmallTablet,isLargeTabletโ Classify tablets based on width. -
isTabletโ Shortcut combining both small and large tablets. -
isDesktopโ Detects larger screens, typically desktops.
โ Bool Extensions #
choose(trueValue, falseValue)โ ReturnstrueValueif the boolean is true, otherwise returnsfalseValue.toInt()โ Converts the boolean to an integer (1 for true, 0 for false).toYesNo({trueString, falseString})โ Converts to a string representation with customizable values.notโ Returns the negation of the boolean (equivalent to!this).
// Examples
true.choose('Active', 'Inactive'); // 'Active'
false.choose('Active', 'Inactive'); // 'Inactive'
true.toInt(); // 1
false.toInt(); // 0
true.toYesNo(); // 'Yes'
false.toYesNo(trueString: 'On', falseString: 'Off'); // 'Off'
true.not; // false
๐๏ธ DateTime Extensions #
โ Checkers
-
isAfternoonโ Checks if the time is between 12:00 PM and 5:59 PM. -
isMorningโ Checks if the time is before 12:00 PM. -
isEveningโ Checks if the time is between 6:00 PM and 11:59 PM. -
isNightโ Checks if the time is between midnight and 5:59 AM. -
isToday/isTomorrow/isYesterdayโ Quickly check the relation to the current day. -
isSameDay(DateTime other)โ Returnstrueif the date is the same calendar day asother. -
isInPast/isInFutureโ Check if the datetime is before or after now.
๐ง Utilities
startOfDay()โ Returns the start of the day (midnight) for the datetime.
๐ง Manipulators
-
addDays(int)/addMonths(int)/addYears(int)โ Add to the datetime. -
addHours(int)/addMinutes(int)/addSeconds(int)โ Add smaller units. -
subDays(int)/subMonths(int)/subYears(int)โ Subtract from the datetime. -
subHours(int)/subMinutes(int)/subSeconds(int)โ Subtract smaller units.
๐ข Age
-
toAge()โ Convert the date to an age in years. -
isAgeOlder(age)/isAgeYounger(age)/isAgeEqualTo(age)โ Check against an age. -
isAgeBetween(min, max)โ Check if the age is within a given range.
๐ง Time to String
-
format(String format)โ Fully custom format usingintl.Popular date and time formats included in the [MayrDateTimeFormats] class.
Currently includes:
MayrDateTimeFormats.ukDate- dd/MM/yyyyMayrDateTimeFormats.ukDateTime- dd/MM/yyyy HH:mm:ssMayrDateTimeFormats.usDate- yyyy-MM-ddMayrDateTimeFormats.usDateTime- yyyy-MM-dd HH:mm:ssMayrDateTimeFormats.time- HH:mm:ssMayrDateTimeFormats.timeNoSecs- HH:mm
-
toDayOrdinal()โ Get the day of the month with ordinal (e.g.1st,22nd,31st). -
toTimeAgoString()โ Human-readable "time ago" format (e.g. "2 days ago"). -
toTimeString()โ Convert to time only (e.g.14:35or14:35:59). -
toShortDate()โ Returns a short formatted date string (e.g.Wed 15th Jan).
โณ Duration Extensions #
delay([callback])โ Delays execution for the given duration. Optionally accepts a callback to run after the delay.toReadableString()โ Returns a human-readable string representation (e.g., '2h 30m', '1d 5h 30m').isLongerThan(other)โ Checks if this duration is longer than another duration.isShorterThan(other)โ Checks if this duration is shorter than another duration.
// Example
await 2.seconds.delay(() {
print('Delayed by 2 seconds');
});
final duration = Duration(hours: 2, minutes: 30);
print(duration.toReadableString()); // '2h 30m'
5.seconds.isLongerThan(3.seconds); // true
3.seconds.isShorterThan(5.seconds); // true
๐ท Object Extensions #
let(transform)โ Executes a function with this object as its argument and returns the result. Useful for chaining operations or transforming values inline.also(action)โ Executes a function with this object and returns this object. Useful for performing side effects while maintaining the original value for further chaining.
// Examples
final result = 'hello'.let((it) => it.toUpperCase()); // 'HELLO'
final length = 'test'.let((it) => it.length); // 4
final user = User('John')
.also((it) => print('Created user: ${it.name}'))
.also((it) => log.info('User created'));
๐ Dynamic Extensions #
-
nullOnDebug<T>()โ Returnsnullonly in debug mode; retains value in release/profile. Useful for testing nullable flows. -
onlyOnDebug<T>()โ Returns the value only in debug mode, otherwisenull. -
maybe<T>({double probability = 0.5})โ Randomly returnsnullbased on the given probability (between 0.0 and 1.0). Great for simulating unreliable data in tests or dev mode.final value = 'Simulate me'.maybe(probability: 0.3); // Has a 30% chance of being null -
orDefault(T fallback)- Returns the fallback value if the provided value is null
๐ผ๏ธ Image Extensions #
circleAvatar({ ... })โ Quickly convert anImageProviderto aCircleAvatarwidget with full customisation options.
// Example
NetworkImage('https://example.com/pic.jpg').circleAvatar(radius: 40);
Parameters:
- backgroundColor โ Background colour of the avatar (default is transparent).
- radius โ Sets the circular radius of the avatar.
- minRadius / maxRadius โ Optional constraints.
- foregroundColor โ Colour for the foreground image.
- onBackgroundImageError / onForegroundImageError โ Handle image load failures.
๐ข Number Extensions #
๐งฎ General Num Extensions
-
isEqual(otherNum)โ Checks if two numbers are exactly equal. -
isGreaterThan(otherNum)โ Returnstrueif the number is greater. -
isLessThan(otherNum)โ Returnstrueif the number is less. -
clampMin(min)โ Clamps the number to a minimum value. -
clampMax(max)โ Clamps the number to a maximum value. -
isBetween(min, max)โ Checks if the number is within a range (inclusive). -
isPositiveโ Returnstrueif the number is greater than zero. -
isNegativeNumberโ Returnstrueif the number is less than zero. -
isZeroโ Returnstrueif the number equals zero.
๐ข Integer Extensions
isEvenNumberโ Checks if the integer is even.isOddNumberโ Checks if the integer is odd.times(action)โ Repeats an action n times.timesIndexed(action)โ Repeats an action n times with the current index.
// Example
5.isBetween(1, 10); // true
3.times(() => print('Hello')); // Prints 'Hello' 3 times
3.timesIndexed((i) => print('Index: $i')); // Prints indices 0, 1, 2
๐ฒ Random Generators
-
randomLess({min = 1.0})โ Forintordouble, generates a random value less than the current one, starting from themin. -
randomMore(max)โ Generates a random value greater than the current one, up tomax.
10.randomLess(); // e.g. returns 3, 7, etc.
5.5.randomMore(10.0); // e.g. returns 6.23, etc.
๐ฏ Double Extensions
toDecimalPlaces(places)โ Rounds the double to a specified number of decimal places.
3.14159.toDecimalPlaces(2); // 3.14
3.14159.toDecimalPlaces(4); // 3.1416
๐ฐ Number Formatting
-
formatAsCurrency({locale, symbol, decimalDigits})โ Formats the number as currency. -
formatAsDecimal({locale, decimalDigits})โ Formats the number as a decimal with specified precision. -
formatAsNumber({locale})โ Formats as a regular number string.
1234.5.formatAsCurrency(locale: 'en_NG', symbol: 'โฆ'); // โฆ1,234.50
โฑ๏ธ Number to Duration
days,hours,minutes,seconds,milliseconds,microsecondsโ Shorthand for converting numbers to Duration.
// Example
await 2.seconds.delay(); // Waits for 2 seconds
๐ค String Extensions #
โ Utilities
-
copyToClipboard()- Copies the string to clipboard. -
matchesRegExp(regex)โ Checks if the string matches a given regular expression. -
toBoolโ Converts"true"or"false"to a boolean. -
toDateTime()โ Parses the string into aDateTimeobject. Returns null if parse fails -
toRegExp()โ Converts the string into aRegExp. -
toUri()- Attempts to parse the string to aUri -
limit(maxLength, [overflow = "โฆ"])โ Limits string length with optional overflow characters. -
mask({start = 2, end = 2, maskChar = '*', maskLength})โ Masks the middle of the string, leaving edges visible.'08012345678'.mask(); // 08*******78 '08012345678'.mask(maskLength: 2); // 08**78 -
reverse()โ Reverses the string. -
isBlank/isNotBlankโ Checks if the string is empty or contains only whitespace. -
removeWhitespace()โ Removes all whitespace from the string. -
countOccurrences(substring)โ Counts how many times a substring appears. -
truncate(maxLength, {ellipsis})โ Truncates the string with word boundary awareness. -
wrap(prefix, [suffix])โ Wraps the string with a prefix and optional suffix. -
removePrefix(prefix)โ Removes a prefix if it exists. -
removeSuffix(suffix)โ Removes a suffix if it exists.
// Examples
'hello'.reverse(); // 'olleh'
' '.isBlank; // true
'hello world'.removeWhitespace(); // 'helloworld'
'hello world'.countOccurrences('l'); // 3
'The quick brown fox'.truncate(10); // 'The quick...'
'text'.wrap('"'); // '"text"'
'Hello World'.removePrefix('Hello '); // 'World'
๐ Pretty Printing
-
prettyJson()โ Formats a raw JSON string. -
prettyXml()โ Formats raw XML into readable indents. -
prettyYaml()โ Formats YAML strings prettily.
๐ Casing
-
camelCaseโ Converts string to camelCase. -
capitalisedโ Capitalises the first letter of each word. -
kebabCaseโ Converts string to kebab-case. -
pascalCaseโ Converts string to PascalCase. -
snakeCaseโ Converts string to snake_case. -
titleCaseโ Converts string to Title Case.
'the big brown fox'.camelCase; // theBigBrownFox
'the big brown fox'.capitalised; // The big brown fox
'the big brown fox'.pascalCase; // TheBigBrownFox
'the big brown fox'.kebabCase; // the-big-brown-fox
'the big brown fox'.snakeCase; // the_-_big_-_brown_-_fox
'the big brown fox'.titleCase; // The Big Brown Fox
๐งช Case and Pattern Checkers
Case Checkers
-
isCamelCase -
isPascalCase -
isSnakeCase -
isKebabCase -
isTitleCase -
isCapitalised -
isUpperCase -
isLowerCase
Pattern Checkers
-
isEmail -
isURL -
isUlid -
isUuid -
isSlug -
isHexColor -
isIPAddress -
isNum โ Validates numeric string -
isAlphabetOnly -
isNumericOnly
๐งฉ Iterable / List Extensions #
Query & Search
firstOrNull()โ Returns first element ornullif emptylastOrNull()โ Returns last element ornullif emptysingleWhereOrNull(predicate)โ Returns match ornullcontainsWhere(predicate)โ Boolean checkindexWhereOrNull(predicate)โ Returns index ornull
// Examples
[1, 2, 3].firstOrNull(); // 1
[].firstOrNull(); // null
[1, 2, 3].singleWhereOrNull((e) => e == 2); // 2
[1, 2, 3].containsWhere((e) => e > 2); // true
Safe Access
getOrNull(index)โ Returns element at index ornullgetOrDefault(index, defaultValue)โ Returns element or default value
// Examples
[1, 2, 3].getOrNull(1); // 2
[1, 2, 3].getOrNull(5); // null
[1, 2, 3].getOrDefault(5, 0); // 0
Transformations
chunked(size)โ Splits into chunksmapIndexed((index, item) => ...)โ Maps with indexwhereNotNull()โ Filters out nullsdistinctBy(keySelector)โ Unique items by propertyflatten()โ Flattens nested listssortedBy(keySelector)/sortedByDesc(keySelector)โ Sort by propertyflip()โ Reverses the list
// Examples
[1, 2, 3, 4, 5].chunked(2); // [[1, 2], [3, 4], [5]]
['a', 'b', 'c'].mapIndexed((i, e) => '$i: $e'); // ['0: a', '1: b', '2: c']
[1, null, 2, null, 3].whereNotNull(); // [1, 2, 3]
[[1, 2], [3, 4]].flatten(); // [1, 2, 3, 4]
[1, 2, 3].flip(); // [3, 2, 1]
Aggregations (Only available on list of numbers)
sumBy(num Function(T))โ Sum elements by selectoraverageBy(num Function(T))โ Average by selectormin()โ Minimum valuemax()โ Maximum valuecountWhere(predicate)โ Count matching elements
// Examples
[1, 2, 3, 4, 5].sumBy((e) => e); // 15
[1, 2, 3, 4, 5].averageBy((e) => e); // 3.0
[3, 1, 4, 1, 5].min(); // 1
[3, 1, 4, 1, 5].max(); // 5
[1, 2, 3, 4, 5].countWhere((e) => e > 3); // 2
Mutation Helpers (returns new copy)
insertIf(condition, value)โ Insert conditionallyreplaceWhere(predicate, newValue)โ Replace matching elementsremoveWhereNot(predicate)โ Keep only matching elementsupdateWhere(predicate, updater)โ Update matching elementsaddIf(value)/addAllIf(values)โ Add conditionallyappend(value)/appendAll(values)โ Append elementsappendIf(value)/appendAllIf(values)โ Append conditionallypop()โ Remove and return last elementfliter(predicate)โ Filter elementsunique()โ Get unique elements
// Examples
[1, 2, 3].insertIf(true, 4); // [1, 2, 3, 4]
[1, 2, 3, 2].replaceWhere((e) => e == 2, 5); // [1, 5, 3, 5]
[1, 2, 3, 4, 5].removeWhereNot((e) => e > 2); // [3, 4, 5]
[1, 2, 2, 3, 3, 4].unique(); // [1, 2, 3, 4]
Utility
isNullOrEmpty()โ Check if emptyjoinToString(separator, transform)โ Join with custom formatforEachIndexed()โ Iterate with index
// Examples
[].isNullOrEmpty(); // true
[1, 2, 3].joinToString(separator: ', '); // '1, 2, 3'
['a', 'b'].forEachIndexed((i, e) => print('$i: $e'));
๐บ๏ธ Map Extensions #
Safe Access
getOrNull(key)โ Get value or nullgetOrDefault(key, defaultValue)โ Get value or default
// Examples
{'a': 1, 'b': 2}.getOrNull('a'); // 1
{'a': 1, 'b': 2}.getOrNull('c'); // null
{'a': 1, 'b': 2}.getOrDefault('c', 0); // 0
Transformations
mapKeys((k, v) => newKey)โ Transform keysmapValues((k, v) => newValue)โ Transform valuesfilterKeys(predicate)โ Filter by keysfilterValues(predicate)โ Filter by valuesinvert()โ Swap keys and values
// Examples
{'a': 1, 'b': 2}.mapKeys((k, v) => k.toUpperCase()); // {'A': 1, 'B': 2}
{'a': 1, 'b': 2}.mapValues((k, v) => v * 2); // {'a': 2, 'b': 4}
{'a': 1, 'b': 2}.invert(); // {1: 'a', 2: 'b'}
Merge & Combine
merge(otherMap)โ Merge with precedencemergeIfAbsent(otherMap)โ Merge without overridingcombine(other, (k, v1, v2) => mergedValue)โ Custom merge
// Examples
{'a': 1, 'b': 2}.merge({'b': 3, 'c': 4}); // {'a': 1, 'b': 3, 'c': 4}
{'a': 1, 'b': 2}.mergeIfAbsent({'b': 3, 'c': 4}); // {'a': 1, 'b': 2, 'c': 4}
Utility
keysWhere(predicate)โ Get keys matching predicatevaluesWhere(predicate)โ Get values matching predicatetoQueryString()โ Convert to URL query string
// Examples
{'a': 1, 'b': 2, 'c': 3}.keysWhere((v) => v > 1); // ['b', 'c']
{'name': 'John', 'age': '30'}.toQueryString(); // 'name=John&age=30'
๐ข Set Extensions #
toggle(element)โ Adds if missing, removes if presentintersects(otherSet)โ Check for intersectionisSubsetOf(otherSet)โ Check if subsetisSupersetOf(otherSet)โ Check if supersetunionAll(sets)โ Union of multiple setswithout(element)โ Remove element
// Examples
{1, 2, 3}.toggle(2); // {1, 3}
{1, 2, 3}.toggle(4); // {1, 2, 3, 4}
{1, 2, 3}.intersects({2, 3, 4}); // true
{1, 2}.isSubsetOf({1, 2, 3}); // true
{1, 2}.unionAll([{2, 3}, {3, 4}]); // {1, 2, 3, 4}
๐ฏ Humanize Extensions #
The goal of humanize is simple:
Convert technical or numeric values into readable, natural, human-friendly strings.
Where computers speak in seconds, bytes, and counts, humanize translates them into something that sounds like it came from a person.
Durations
.humanize(locale)โ "2 hours, 3 minutes"
// Examples
Duration(hours: 2, minutes: 3).humanize(); // '2 hours, 3 minutes'
Duration(days: 1).humanize(); // '1 day'
Duration(seconds: 45).humanize(); // '45 seconds'
Time (DateTime)
.humanize(locale)โ "just now", "3 hours ago", "yesterday", "last week", "3 days from now", "2 weeks ago"
// Examples
DateTime.now().humanize(); // 'just now'
DateTime.now().subtract(Duration(hours: 3)).humanize(); // '3 hours ago'
DateTime.now().subtract(Duration(days: 1)).humanize(); // 'yesterday'
DateTime.now().add(Duration(days: 2)).humanize(); // 'in 2 days'
Numbers
humanizeNumber()โ "15.3k", "1.5M"humanizeOrdinal()โ "1st", "2nd", "3rd"humanizeCount('item')โ "1 item" / "3 items"humanizePercentage(max, min)โ "74%"humanizeFileSize()โ "1.0 MB", "520.3 KB"
// Examples
1234.humanizeNumber(); // '1.2k'
1500000.humanizeNumber(); // '1.5M'
1.humanizeOrdinal(); // '1st'
21.humanizeOrdinal(); // '21st'
3.humanizeCount('item'); // '3 items'
0.75.humanizePercentage(); // '75%'
1024.humanizeFileSize(); // '1.0 KB'
520300.humanizeFileSize(); // '508.1 KB'
๐งฉ Widget Extensions #
๐ช Basic Transformations
-
center({heightFactor, widthFactor})โ Wraps widget in aCenter. -
expanded([flex = 1])โ Wraps widget in anExpanded. -
flexible({flex = 1, fit = FlexFit.loose})โ Wraps widget in aFlexible. -
opacity(opacity)โ Wraps widget with anOpacitywidget. -
sizedBox({width, height})โ Wraps widget with aSizedBox. -
constrained({maxHeight, maxWidth, minHeight, minWidth})โ Wraps widget with aConstrainedBox.
โ๏ธ Clipping
-
clipRect()โ Clips widget to a rectangle. -
clipRRect(borderRadius)โ Clips widget with rounded corners. -
clipRounded([radius = 12])โ Quickly clip widget with a uniform rounded border.
๐งน Padding
-
paddingAll(padding)โ Adds equal padding on all sides. -
paddingSymmetric({horizontal, vertical})โ Adds symmetric horizontal and vertical padding. -
paddingOnly({left, top, right, bottom})โ Custom padding for specific sides. -
paddingZero()โ Adds zero padding.
๐งญ Positioning
-
positionAlign(alignment)โ Aligns widget usingAlign. -
positionedFill()โ Fills parent constraints usingPositioned.fill.
๐ป Visibility Helpers
-
hideIf(condition)โ Hides widget (returnsSizedBox.shrink()) ifconditionis true. -
hideUnless(condition)โ Hides widget unlessconditionis true. -
showIf(condition)โ Shows widget ifconditionis true, otherwise hides. -
showUnless(condition)โ Shows widget unlessconditionis true.
๐ inkwellManager on Widget
A helper class for managing taps on a widget in a cleaner way.
-
inkWellManager(callback, {color = Colors.transparent})โ Wraps widget with anInkWellfor tap detection. -
onTap()โ Wraps child withInkWellfor tap gesture. -
onDoubleTap()โ Wraps child withInkWellfor double-tap gesture. -
onLongPress()โ Wraps child withInkWellfor long-press gesture.
Tip: Used alongside the
inkWellManagerextension to easily attach tap interactions without boilerplate.
Text('Click Me')
.inkWellManager(() => print('Tapped'), color: Colors.black)
.onTap();
๐ก Why InkWellManager?
Normally, to make a widget respond to taps, you must manually wrap it inside an InkWell every time, setting colours and callbacks.
InkWellManager simplifies this by providing quick .onTap(), .onDoubleTap(), and .onLongPress() methods โ making your code shorter, cleaner, and more maintainable.
It also auto-applies the same splash, hover, and focus colours without extra setup.
๐ DateTimeFormat #
This package also include some common date time formats. These inlude:
MayrDateTimeFormats.ukDateMayrDateTimeFormats.usDateMayrDateTimeFormats.timeMayrDateTimeFormats.timeNoSecsMayrDateTimeFormats.ukDateTimeMayrDateTimeFormats.usDateTime
Usage #
To use, simply import the package into your project and you can then all of the extensions it provdes ๐ซถ๐พ
import 'package:mayr_extensions/mayr_extensions.dart';
๐ข Additional Information #
๐ค Contributing #
Contributions are highly welcome! If you have ideas for new extensions, improvements, or fixes, feel free to fork the repository and submit a pull request.
Please make sure to:
- Follow the existing coding style.
- Write tests for new features.
- Update documentation if necessary.
Let's build something amazing together!
๐ Reporting Issues #
If you encounter a bug, unexpected behaviour, or have feature requests:
- Open an issue on the repository.
- Provide a clear description and steps to reproduce (if it's a bug).
- Suggest improvements if you have any ideas.
Your feedback helps make the package better for everyone!
๐ Licence #
This package is licensed under the MIT License โ which means you are free to use it for commercial and non-commercial projects, with proper attribution.
See the LICENSE file for more details.
๐ Support #
If you find this package helpful, please consider giving it a โญ๏ธ on GitHub โ it motivates and helps the project grow!
You can also support by:
- Sharing the package with your friends, colleagues, and tech communities.
- Using it in your projects and giving feedback.
- Contributing new ideas, features, or improvements.
Every little bit of support counts! ๐๐