Skip to content
This repository was archived by the owner on Oct 17, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Improved
- Added comprehensive test coverage for DateTime extensions
- Tests for all manipulation methods (addDays, addMonths, addYears, subDays, etc.)
- Tests for check methods (isToday, isTomorrow, isYesterday, isInFuture, isInPast)
- Tests for formatting methods (format, toTimeString, toShortDate, toDayOrdinal)
- Tests for time of day checks (isMorning, isAfternoon, isEvening, isNight)
- Tests for age calculations (toAge, isAgeOlder, isAgeYounger, isAgeBetween)

## [0.4.0] - 6th October, 2025

### Added
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,15 @@ true.not; // false
- `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 8:59 PM.
- `isNight` – Checks if the time is after 9: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)` – Returns `true` if the date is the same calendar day as `other`.
- `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.

Expand All @@ -117,7 +120,7 @@ true.not; // false

#### 🧠 Time to String

- `toFormat(String format)` – Fully custom format using `intl`.
- `format(String format)` – Fully custom format using `intl`.
> Popular date and time formats included in the [MayrDateTimeFormats] class.
>
> Currently includes:
Expand All @@ -131,7 +134,7 @@ true.not; // false
- `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:35` or `14:35:59`).
- `toShortDate()` – Returns a short formatted date string (e.g. `Apr 25, 2025`).
- `toShortDate()` – Returns a short formatted date string (e.g. `Wed 15th Jan`).

-------------------------------------------------------------------------------

Expand Down
44 changes: 40 additions & 4 deletions lib/src/extensions/date_time.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,31 @@ extension MayrDateTimeManipulationExtensions on DateTime {
DateTime addMinutes(int minutes) => add(Duration(minutes: minutes));

/// Add months to a [DateTime]
DateTime addMonths(int months) => DateTime(year, month + months, day);
DateTime addMonths(int months) => DateTime(
year,
month + months,
day,
hour,
minute,
second,
millisecond,
microsecond,
);

/// Add seconds to a [DateTime]
DateTime addSeconds(int seconds) => add(Duration(seconds: seconds));

/// Add years to a [DateTime]
DateTime addYears(int years) => DateTime(year + years, month, day);
DateTime addYears(int years) => DateTime(
year + years,
month,
day,
hour,
minute,
second,
millisecond,
microsecond,
);

/// Subtract days from a [DateTime]
DateTime subDays(int days) => subtract(Duration(days: days));
Expand All @@ -93,13 +111,31 @@ extension MayrDateTimeManipulationExtensions on DateTime {
DateTime subMinutes(int minutes) => subtract(Duration(minutes: minutes));

/// Subtract months from a [DateTime]
DateTime subMonths(int months) => DateTime(year, month - months, day);
DateTime subMonths(int months) => DateTime(
year,
month - months,
day,
hour,
minute,
second,
millisecond,
microsecond,
);

/// Subtract seconds from a [DateTime]
DateTime subSeconds(int seconds) => subtract(Duration(seconds: seconds));

/// Subtract years from a [DateTime]
DateTime subYears(int years) => DateTime(year - years, month, day);
DateTime subYears(int years) => DateTime(
year - years,
month,
day,
hour,
minute,
second,
millisecond,
microsecond,
);
}

extension MayrDateTimeToStringExtensions on DateTime {
Expand Down
120 changes: 120 additions & 0 deletions lib/src/extensions/widget.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,66 @@
part of './../extensions.dart';

extension MayrWidgetExtensions on Widget {
/// Wraps this widget in a [Center] widget.
///
/// Example:
/// ```dart
/// Text('Hello').center();
/// ```
Center center({double? heightFactor, double? widthFactor}) =>
Center(heightFactor: heightFactor, widthFactor: widthFactor, child: this);

/// Wraps this widget in an [Expanded] widget.
///
/// Example:
/// ```dart
/// Text('Hello').expanded(2); // Takes 2x the space of other expanded widgets
/// ```
Expanded expanded([int flex = 1]) => Expanded(flex: flex, child: this);

/// Wraps this widget in a [Flexible] widget.
///
/// Example:
/// ```dart
/// Text('Hello').flexible(flex: 2, fit: FlexFit.tight);
/// ```
Flexible flexible({int flex = 1, FlexFit fit = FlexFit.loose}) =>
Flexible(flex: 1, fit: fit, child: this);

/// Wraps this widget with an [InkWellManager] for touch interactions.
///
/// Example:
/// ```dart
/// Text('Click me').inkWellManager(() => print('Tapped!'));
/// ```
InkWellManager inkWellManager(
void Function()? callback, {
Color color = Colors.transparent,
}) => InkWellManager(this, callback, color: color);

/// Wraps this widget in an [Opacity] widget.
///
/// Example:
/// ```dart
/// Text('Hello').opacity(0.5); // Makes text semi-transparent
/// ```
Opacity opacity(double opacity) => Opacity(opacity: opacity, child: this);

/// Wraps this widget in a [SizedBox] with optional width and height.
///
/// Example:
/// ```dart
/// Text('Hello').sizedBox(width: 100, height: 50);
/// ```
Widget sizedBox({double? width, double? height}) =>
SizedBox(height: height, width: width, child: this);

/// Wraps this widget in a [ConstrainedBox] with optional constraints.
///
/// Example:
/// ```dart
/// Text('Hello').constrained(maxWidth: 200, minHeight: 50);
/// ```
Widget constrained({
double? maxHeight,
double? maxWidth,
Expand All @@ -36,19 +78,49 @@ extension MayrWidgetExtensions on Widget {
}

extension MayrWidgetClipExtensions on Widget {
/// Wraps this widget in a [ClipRect] widget.
///
/// Example:
/// ```dart
/// Image.network('url').clipRect();
/// ```
ClipRect clipRect() => ClipRect(child: this);

/// Wraps this widget in a [ClipRRect] widget with custom border radius.
///
/// Example:
/// ```dart
/// Image.network('url').clipRRect(BorderRadius.circular(20));
/// ```
ClipRRect clipRRect(BorderRadiusGeometry borderRadius) =>
ClipRRect(borderRadius: borderRadius, child: this);

/// Wraps this widget in a [ClipRRect] widget with circular border radius.
///
/// Example:
/// ```dart
/// Image.network('url').clipRounded(15); // 15 pixel radius
/// ```
ClipRRect clipRounded([double radius = 12]) =>
clipRRect(BorderRadius.circular(radius));
}

extension MayrWidgetPaddingExtensions on Widget {
/// Wraps this widget in a [Padding] widget with equal padding on all sides.
///
/// Example:
/// ```dart
/// Text('Hello').paddingAll(16.0);
/// ```
Widget paddingAll(double padding) =>
Padding(padding: EdgeInsets.all(padding), child: this);

/// Wraps this widget in a [Padding] widget with symmetric padding.
///
/// Example:
/// ```dart
/// Text('Hello').paddingSymmetric(horizontal: 20, vertical: 10);
/// ```
Widget paddingSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
Padding(
padding: EdgeInsets.symmetric(
Expand All @@ -58,6 +130,12 @@ extension MayrWidgetPaddingExtensions on Widget {
child: this,
);

/// Wraps this widget in a [Padding] widget with specific padding on each side.
///
/// Example:
/// ```dart
/// Text('Hello').paddingOnly(left: 10, top: 5, right: 10, bottom: 5);
/// ```
Widget paddingOnly({
double left = 0.0,
double top = 0.0,
Expand All @@ -73,22 +151,64 @@ extension MayrWidgetPaddingExtensions on Widget {
child: this,
);

/// Wraps this widget in a [Padding] widget with zero padding.
///
/// Example:
/// ```dart
/// Text('Hello').paddingZero();
/// ```
Widget paddingZero() => Padding(padding: EdgeInsets.zero, child: this);
}

extension MayrWidgetPositionExtensions on Widget {
/// Wraps this widget in an [Align] widget with the specified alignment.
///
/// Example:
/// ```dart
/// Text('Hello').positionAlign(Alignment.topLeft);
/// ```
Align positionAlign(AlignmentGeometry alignment) =>
Align(alignment: alignment, child: this);

/// Wraps this widget in a [Positioned.fill] widget.
///
/// Example:
/// ```dart
/// Container().positionedFill();
/// ```
Positioned positionedFill() => Positioned.fill(child: this);
}

extension MayrWidgetVisibilityExtensions on Widget {
/// Hides this widget if the [condition] is true, otherwise shows it.
///
/// Example:
/// ```dart
/// Text('Hello').hideIf(isHidden);
/// ```
Widget hideIf(bool condition) => showIf(!condition);

/// Hides this widget unless the [condition] is true.
///
/// Example:
/// ```dart
/// Text('Hello').hideUnless(isVisible);
/// ```
Widget hideUnless(bool condition) => showIf(condition);

/// Shows this widget if the [condition] is true, otherwise hides it.
///
/// Example:
/// ```dart
/// Text('Hello').showIf(isVisible);
/// ```
Widget showIf(bool condition) => condition ? this : const SizedBox.shrink();

/// Shows this widget unless the [condition] is true.
///
/// Example:
/// ```dart
/// Text('Hello').showUnless(isHidden);
/// ```
Widget showUnless(bool condition) => showIf(!condition);
}
Loading