save_points_extensions_utils 1.1.0 copy "save_points_extensions_utils: ^1.1.0" to clipboard
save_points_extensions_utils: ^1.1.0 copied to clipboard

Extensions and reusable widgets. Provides 100+ widget extensions, 40+ pre-built UI components, data type extensions, form validators, spacing utilities, and more. Zero dependencies, fully documented, [...]

Save Points Extensions #

A comprehensive Flutter library of extensions and reusable widgets designed to enhance developer productivity and code quality. This library provides a collection of well-organized, type-safe extensions and widgets following Flutter best practices.

A powerful, modular, zero-dependency Extensions library for Flutter

Dart Flutter

Pure DartZero Dependencies100+ ExtensionsFully ModularProduction Ready

🚀 Live DemoFeaturesInstallationQuick StartDocumentationExamples

✨ Features #

  • 100+ Widget Extensions - Streamline widget composition with chainable methods (padding, margin, center, clip, transform, gestures, and more)
  • 40+ Pre-built UI Components - Production-ready reusable widgets (avatars, cards, dialogs, buttons, loaders, navigation, and more)
  • Comprehensive Data Type Extensions - Enhance String, Number, List, Map, DateTime, Color, Context, and Animation with 50+ utility methods
  • Professional Code Quality - Fully documented with examples, type-safe, null-safe, and following Flutter best practices
  • Form Validation - Comprehensive validators for common use cases (email, phone, URL, required, length, etc.)
  • Utility Helpers - Spacing constants, app constants, debounce/throttle helpers, and reusable utilities
  • Zero Dependencies - Pure Flutter/Dart, no external dependencies
  • Well Documented - Every extension includes comprehensive documentation with usage examples

📦 Installation #

Add this to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  save_points_extensions_utils: ^1.1.0

Then import the extensions:

// Option 1: Import everything from main library
import 'package:save_points_extensions_utils/save_points_extensions_utils.dart';

// Option 2: Import specific parts
import 'package:save_points_extensions_utils/extensions/logics/extensions.dart';
import 'package:save_points_extensions_utils/utils/utils.dart';

⚠️ Avoiding Conflicts with Other Packages #

If you're using multiple packages that might have naming conflicts (e.g., save_points_extensions_utils and save_points_chart), here are strategies to avoid conflicts:

import 'package:save_points_extensions_utils/save_points_extensions_utils.dart' as utils;
import 'package:save_points_chart/save_points_chart.dart' as chart;

// Use with prefix
utils.Spacing.md;
utils.Validators.email('test@example.com');
chart.ChartConfig();

Strategy 2: Use Explicit Imports with show #

// Import only what you need
import 'package:save_points_extensions_utils/utils/utils.dart' 
  show Spacing, Validators, AppConstants;
import 'package:save_points_chart/chart_utils.dart' 
  show ChartConfig, ChartType;

Strategy 3: Use hide to Exclude Conflicting Names #

import 'package:save_points_extensions_utils/utils/utils.dart' 
  hide SpacingConfig; // Hide if it conflicts
import 'package:save_points_chart/chart_utils.dart';

Strategy 4: Import Extensions Separately #

Extensions on built-in types (String, List, Widget, etc.) won't conflict if they have different method names. If they do conflict, use prefixes:

import 'package:save_points_extensions_utils/save_points_extensions_utils.dart' as utils;
import 'package:save_points_chart/save_points_chart.dart' as chart;

// Extensions work normally
'hello'.capitalize(); // Uses utils extension

// If methods conflict, use explicit extension
utils.StringExtensions('hello').capitalize();

Common Conflict Scenarios #

  1. Utility Classes: Spacing, Validators, AppConstants - Use prefixes
  2. Config Classes: SpacingConfig, ValidatorConfig - Use prefixes or show/hide
  3. Extension Methods: Usually fine unless same method name - Use prefixes if needed
  4. Static Methods: Use prefixes or explicit class names

Best Practice #

For projects using multiple save_points_* packages, always use library prefixes:

import 'package:save_points_extensions_utils/save_points_extensions_utils.dart' as utils;
import 'package:save_points_chart/save_points_chart.dart' as chart;
import 'package:save_points_other/save_points_other.dart' as other;

// Clear and conflict-free
utils.Spacing.md;
chart.ChartConfig();
other.OtherUtility();

📖 For more details, see:

  • Conflict Prevention Guide - Detailed guide on avoiding conflicts
  • Best Practices - Comprehensive best practices guide

🚀 Quick Start #

Using Widget Extensions #

Chain multiple extensions together for clean, readable code:

import 'package:save_points_extensions_utils/extensions/extensions.dart';

// Chain widget modifications
const Text('Chained Extensions')
  .padding(all: 20)
  .center()
  .clipRRect(borderRadius: 16)
  .decoratedBox(
    color: context.colorScheme.primaryContainer,
    borderRadius: BorderRadius.circular(16),
    boxShadow: [
      BoxShadow(
        color: context.colorScheme.primary.withOpacity(0.3),
        blurRadius: 8,
        offset: Offset(0, 4),
      ),
    ],
  )
  .onTap(() => print('Tapped!'))
  .tooltip('Tap me!');

// Transform widgets
const Icon(Icons.star, size: 48)
  .rotate(0.2)
  .scale(1.5)
  .translate(x: 10, y: 5);

// Clip widgets
Container(
  width: 100,
  height: 100,
  color: Colors.blue,
)
  .clipRRect(borderRadius: 16)
  .clipOval()
  .onTap(() => print('Tapped'));

Using Context Extensions #

Easy access to theme, media query, and navigation:

import 'package:save_points_extensions_utils/extensions/extensions.dart';

// Theme access
context.colorScheme.primary
context.textTheme.headlineLarge
context.isDarkMode
context.isLightMode

// Screen dimensions
context.screenWidth
context.screenHeight
context.screenSize
context.isMobile
context.isTablet
context.isDesktop

// Navigation helpers
context.push(MyPage());
context.pop();
context.showSnackBar('Hello!');
context.hideKeyboard();

Using Data Extensions #

String Extensions

// Text manipulation
'hello world'.capitalize()           // "Hello world"
'hello world'.capitalizeWords()       // "Hello World"
'very long text'.truncate(10)        // "very long..."
'hello world'.removeWhitespace()     // "helloworld"
'hello world'.reverse()               // "dlrow olleh"
'hello world'.toSlug()                // "hello-world"

// Validation
'email@test.com'.isValidEmail        // true
'https://example.com'.isValidUrl      // true
'+1234567890'.isValidPhone           // true
'12345'.isNumeric                     // true
'Hello'.isAlpha                       // true
'Hello123'.isAlphanumeric             // true

// Utilities
'hello world'.startsWithAny(['he', 'hi'])  // true
'hello world'.endsWithAny(['ld', 'la'])    // true
'hello world'.findAll(RegExp(r'\w+'))      // ['hello', 'world']

Number Extensions

// Formatting
42.format(prefix: 'Count: ')              // "Count: 42"
1234567.formatWithSeparator()             // "1,234,567"
1234.formatCurrency()                     // "$1,234.00"
1500000.toHumanReadable()                 // "1.5M"

// Validation
42.isEven                                 // true
42.isOdd                                  // false
5.isPositive                              // true
(-5).isNegative                           // true
5.isBetween(1, 10)                        // true

// Duration helpers
60.seconds                                // Duration(seconds: 60)
5.minutes                                 // Duration(minutes: 5)
2.hours                                   // Duration(hours: 2)
7.days                                    // Duration(days: 7)

// Ranges
1.rangeTo(5)                              // [1, 2, 3, 4]
1.rangeToInclusive(5)                     // [1, 2, 3, 4, 5]

DateTime Extensions

// Date checks
DateTime.now().isToday                   // true
DateTime.now().isYesterday               // false
DateTime.now().isTomorrow                // false
DateTime(2020, 1, 1).isPast              // true
DateTime(2030, 1, 1).isFuture            // true

// Formatting
date.format('yyyy-MM-dd')                // "2024-01-15"
date.format('HH:mm:ss')                  // "14:30:45"
date.toFormattedString()                  // "January 15, 2024"
date.toShortFormattedString()            // "Jan 15, 2024"

// Relative time
date.timeAgo                              // "2 hours ago"
date.age                                  // 24

// Date manipulation
date.addDays(5)                          // Add 5 days
date.subtractDays(5)                      // Subtract 5 days
date.addMonths(2)                        // Add 2 months
date.addYears(1)                         // Add 1 year

// Date ranges
date.startOfDay                          // 00:00:00.000
date.endOfDay                            // 23:59:59.999
date.startOfWeek                         // Monday 00:00:00
date.endOfWeek                           // Sunday 23:59:59
date.startOfMonth                        // First day of month
date.endOfMonth                          // Last day of month

// Comparisons
date.isSameDay(otherDate)                // true/false
date.isSameWeek(otherDate)               // true/false
date.isBetween(startDate, endDate)       // true/false
date.daysUntil(otherDate)                // 5

List Extensions

// Safe access
list.firstOrNull                          // First element or null
list.lastOrNull                           // Last element or null
list.elementAtOrNull(5)                   // Element at index or null
list.elementAtOrDefault(5, defaultValue)  // Element or default

// Manipulation
[1, 2, 2, 3].distinct                     // [1, 2, 3]
list.distinctBy((item) => item.id)        // Remove duplicates by key
list.chunk(3)                             // Split into chunks of 3
list.shuffled                             // New shuffled list

// Querying
list.firstWhereOrNull((x) => x > 3)       // First matching or null
list.lastWhereOrNull((x) => x > 3)        // Last matching or null
list.any((x) => x > 5)                    // true if any matches
list.all((x) => x > 0)                    // true if all match

// Aggregation
list.sum((x) => x.value)                  // Sum of values
list.average((x) => x.value)              // Average of values
list.maxBy((x) => x.value)                 // Max element
list.minBy((x) => x.value)                 // Min element

// Grouping
list.groupBy((item) => item.category)      // Map<K, List<T>>

// Slicing
list.drop(2)                              // Remove first 2
list.dropLast(2)                          // Remove last 2
list.take(3)                              // Take first 3
list.takeLast(3)                          // Take last 3

Map Extensions

// Safe access
map.getOrNull('key')                      // Value or null
map.getOrDefault('key', defaultValue)     // Value or default
map.getOrPut('key', () => defaultValue)   // Value or compute and store

// Transformation
map.mapKeys((k) => k.toUpperCase())       // Transform keys
map.mapValues((v) => v * 2)               // Transform values
map.filter((k, v) => v > 10)              // Filter entries

// Utilities
map.firstEntry                            // First entry or null
map.lastEntry                             // Last entry or null
map.merge(otherMap)                      // Merge maps
map.mergeWith(otherMap, (a, b) => a + b)  // Merge with function
map.invert()                              // Swap keys and values
map.sortedByKey()                         // Sort by keys
map.sortedByValue()                       // Sort by values

Color Extensions

// Manipulation
color.darken(0.2)                         // Darker color
color.lighten(0.2)                        // Lighter color
color.saturate(0.3)                       // More saturated
color.desaturate(0.3)                     // Less saturated
color.blend(otherColor, 0.5)              // Blend colors
color.adjustBrightness(0.2)               // Adjust brightness
color.adjustHue(120)                      // Shift hue
color.complementary                       // Complementary color

// Conversion
color.hexString                           // "#FF2196F3"
color.hexStringNoAlpha                    // "#2196F3"
color.toRgb()                             // {'r': 255, 'g': 0, 'b': 0}
color.toHsl()                             // {'h': 0.0, 's': 1.0, 'l': 0.5}

// Utilities
color.isDark                              // true if dark
color.isLight                             // true if light
color.contrastingColor                    // Black or white for contrast

// Static factories
ColorExtensions.fromHex('#FF0000')        // From hex string
ColorExtensions.fromRgb(255, 0, 0)        // From RGB
ColorExtensions.fromHsl(0, 1.0, 0.5)      // From HSL

Animation Extensions

// Animation status
animation.isCompleted                     // true if completed
animation.isDismissed                     // true if dismissed
animation.isForward                       // true if forward
animation.isReverse                       // true if reverse
animation.isAnimating                     // true if animating
animation.clampedValue                    // Value clamped 0.0-1.0
animation.reversedValue                   // 1.0 - value

// Controller utilities
controller.toggle()                       // Toggle animation
controller.resetAndForward()              // Reset and forward
controller.resetAndReverse()              // Reset and reverse
controller.isNotAnimating                 // true if not animating

// Tween utilities
tween.reverse                             // Reverse tween
tween.evaluate(0.5)                       // Value at 0.5
tween.lerp(0.5)                           // Value at 0.5

Using Utilities #

Validators

import 'package:save_points_extensions_utils/utils/utils.dart';

// In form validation
TextFormField(
  validator: (value) => Validators.required(value),
)

TextFormField(
  validator: (value) => Validators.email(value),
)

// Available validators
Validators.required(value)
Validators.email(value)
Validators.phone(value)
Validators.url(value)
Validators.numeric(value)
Validators.minLength(value, 8)
Validators.maxLength(value, 100)
Validators.match(value, otherValue)

Spacing

import 'package:save_points_extensions_utils/utils/utils.dart';

// Constants
Spacing.xs  // 4.0
Spacing.sm  // 8.0
Spacing.md  // 16.0
Spacing.lg  // 24.0
Spacing.xl  // 32.0

// Helpers
Spacing.vertical(16)
Spacing.horizontal(8)
Spacing.all(16)
Spacing.symmetric(horizontal: 8, vertical: 16)
Spacing.only(top: 8, bottom: 16)

Constants

import 'package:save_points_extensions_utils/utils/utils.dart';

AppConstants.defaultPadding
AppConstants.defaultBorderRadius
AppConstants.shortAnimation

Debounce & Throttle

import 'package:save_points_extensions_utils/utils/utils.dart';

final debounce = Debounce(const Duration(milliseconds: 300));
final throttle = Throttle(const Duration(milliseconds: 500));

// Runs once after rapid triggers settle
debounce(() {
  // Your code here
});

// Runs at most once in the given interval
throttle(() {
  // Your code here
});

📚 Available Extensions #

Widget Extensions #

Located in lib/extensions/widgets/:

  • Core Extensions (widget_core_extensions.dart) - padding, margin, center, expanded, flexible, sizedBox, container, opacity, visible, safeArea, decoratedBox
  • Gesture Extensions (widget_gesture_extensions.dart) - onTap, onLongPress, onDoubleTap, inkWell
  • Clip Extensions (widget_clip_extensions.dart) - clipRRect, clipOval, clipRect
  • Transform Extensions (widget_transform_extensions.dart) - rotate, scale, translate, transform
  • Layout Extensions (widget_layout_extensions.dart) - align, positioned, aspectRatio, constrained, fittedBox, fractionallySizedBox
  • Material Extensions (widget_material_extensions.dart) - material, card
  • Animation Extensions (widget_animation_extensions.dart) - hero, animatedSwitcher
  • Scroll Extensions (widget_scroll_extensions.dart) - scrollable
  • Sizing Extensions (widget_sizing_extensions.dart) - intrinsicHeight, intrinsicWidth, unconstrained, limitedBox, overflowBox
  • Semantics Extensions (widget_semantics_extensions.dart) - semantics, tooltip
  • Text Extensions (widget_text_extensions.dart) - TextExtensions.bold, TextExtensions.italic
  • Icon Extensions (widget_icon_extensions.dart) - IconExtensions.themed
  • Image Extensions (widget_image_extensions.dart) - ImageExtensions.networkWithFallback
  • List Extensions (widget_list_extensions.dart) - ListViewExtensions.withPadding, GridViewExtensions.withDefaults
  • Stack Extensions (widget_stack_extensions.dart) - StackExtensions.centered
  • Column/Row Extensions (widget_column_row_extensions.dart) - ColumnExtensions.centered, RowExtensions.centered
  • Wrap Extensions (widget_column_row_extensions.dart) - WrapExtensions.withSpacing

Data Type Extensions #

  • String Extensions (string_extensions.dart) - 30+ methods for text manipulation, validation, and formatting
  • Number Extensions (number_extensions.dart) - Formatting, validation, duration helpers, ranges, and more
  • DateTime Extensions (datetime_extensions.dart) - Date manipulation, formatting, relative time, age calculation, date ranges
  • Duration Extensions (datetime_extensions.dart) - Human-readable strings, formatted output
  • List Extensions (list_extensions.dart) - 40+ methods for safe access, manipulation, querying, aggregation, grouping
  • Map Extensions (map_extensions.dart) - Safe access, transformation, filtering, merging, sorting
  • Color Extensions (color_extensions.dart) - Color manipulation, conversion, blending, HSL/RGB conversion
  • Context Extensions (context_extensions.dart) - Theme access, media query, navigation, snackbar, keyboard, screen size detection
  • Animation Extensions (animation_extensions.dart) - Animation status checks, controller utilities, tween helpers

🛠️ Utilities #

Validators #

Comprehensive form validation utilities:

import 'package:save_points_extensions_utils/utils/utils.dart';

Validators.required(value)
Validators.email(value)
Validators.phone(value)
Validators.url(value)
Validators.numeric(value)
Validators.minLength(value, 8)
Validators.maxLength(value, 100)
Validators.match(value, otherValue)

Spacing #

Consistent spacing constants and helpers:

import 'package:save_points_extensions_utils/utils/utils.dart';

// Constants
Spacing.xs  // 4.0
Spacing.sm  // 8.0
Spacing.md  // 16.0
Spacing.lg  // 24.0
Spacing.xl  // 32.0

// Helpers
Spacing.vertical(16)
Spacing.horizontal(8)
Spacing.all(16)
Spacing.symmetric(horizontal: 8, vertical: 16)
Spacing.only(top: 8, bottom: 16)

Constants #

Application-wide constants:

import 'package:save_points_extensions_utils/utils/utils.dart';

AppConstants.defaultPadding
AppConstants.defaultBorderRadius
AppConstants.shortAnimation

Debounce & Throttle #

Control how frequently callbacks execute to prevent spamming expensive work:

import 'package:save_points_extensions_utils/utils/utils.dart';

final debounce = Debounce(const Duration(milliseconds: 300));
final throttle = Throttle(const Duration(milliseconds: 500));

// Runs once after rapid triggers settle
debounce(() {
  // Your code here
});

// Runs at most once in the given interval
throttle(() {
  // Your code here
});

🎨 Pre-built UI Components #

The library includes 40+ production-ready, customizable UI components:

Core Components #

import 'package:save_points_extensions_utils/widgets/components/components.dart';

// Avatar with fallback
AvatarWidget(
  imageUrl: 'https://example.com/avatar.jpg',
  fallbackText: 'JD',
  size: 50,
  showStatusIndicator: true,
)

// Custom button with loading state
CustomButton(
  text: 'Submit',
  onPressed: () => submitForm(),
  isLoading: false,
  icon: Icons.send,
)

// Custom text field with validation
CustomTextField(
  label: 'Email',
  hint: 'Enter your email',
  validator: Validators.email,
  prefixIcon: Icons.email,
)

// Custom card with elevation
CustomCard(
  title: 'Card Title',
  subtitle: 'Card description',
  child: Text('Content here'),
  onTap: () => print('Tapped'),
)

// Loading states
LoadingIndicator(size: 40, color: Colors.blue)
ShimmerLoading(width: 200, height: 100)
SkeletonLoader(width: double.infinity, height: 60)

// Empty states
EmptyStateWidget(
  icon: Icons.inbox,
  title: 'No items',
  message: 'Add your first item',
  actionLabel: 'Add Item',
  onAction: () => addItem(),
)

// Expandable card
ExpansionCard(
  title: 'Details',
  children: [Text('Hidden content')],
)

// Rating widget
RatingWidget(
  rating: 4.5,
  maxRating: 5,
  onRatingChanged: (rating) => updateRating(rating),
)

// Progress indicators
ProgressBar(value: 0.7, showPercentage: true)

// Stepper
StepperWidget(
  currentStep: 1,
  steps: ['Step 1', 'Step 2', 'Step 3'],
  onStepTapped: (index) => goToStep(index),
)

// Timeline
TimelineWidget(
  events: [
    TimelineEvent(title: 'Event 1', time: '10:00 AM'),
    TimelineEvent(title: 'Event 2', time: '2:00 PM'),
  ],
)

// Search bar
SearchBarWidget(
  onSearch: (query) => searchItems(query),
  hintText: 'Search...',
)

// Navigation components
NavigationBarWidget(
  currentIndex: 0,
  items: [
    BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
    BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
  ],
  onTap: (index) => changePage(index),
)

// Carousel
CarouselWidget(
  items: [Image.network('url1'), Image.network('url2')],
  autoPlay: true,
  height: 200,
)

// Breadcrumb navigation
BreadcrumbWidget(
  items: ['Home', 'Products', 'Details'],
  onTap: (index) => navigateToLevel(index),
)

// Menu
MenuWidget(
  items: [
    MenuItem(label: 'Edit', icon: Icons.edit),
    MenuItem(label: 'Delete', icon: Icons.delete),
  ],
  onItemSelected: (item) => handleAction(item),
)

// Segmented control
SegmentedControl(
  segments: ['Option 1', 'Option 2', 'Option 3'],
  selectedIndex: 0,
  onSegmentChanged: (index) => handleChange(index),
)

// Custom chip
CustomChip(
  label: 'Tag',
  onDeleted: () => removeTag(),
  avatar: Icon(Icons.star),
)

// Badge
BadgeWidget(
  child: Icon(Icons.notifications),
  value: '5',
  color: Colors.red,
)

// Notification card
NotificationCard(
  title: 'New Message',
  message: 'You have a new message',
  time: '5 min ago',
  onTap: () => openMessage(),
)

// Info banner
InfoBanner(
  message: 'This is an important message',
  type: BannerType.warning,
  onDismiss: () => dismissBanner(),
)

// Custom dialog
CustomDialog(
  title: 'Confirm',
  content: 'Are you sure?',
  actions: [
    TextButton(child: Text('Cancel'), onPressed: () => close()),
    ElevatedButton(child: Text('Confirm'), onPressed: () => confirm()),
  ],
)

// Custom bottom sheet
CustomBottomSheet(
  title: 'Options',
  child: ListView(...),
  onClose: () => Navigator.pop(context),
)

// Divider with text
DividerWidget(text: 'OR', thickness: 1)

// Tooltip
TooltipWidget(
  message: 'This is a tooltip',
  child: Icon(Icons.info),
)

// Tag widget
TagWidget(
  label: 'Featured',
  color: Colors.orange,
  icon: Icons.star,
)

Available Components #

Component Description
AvatarWidget Customizable avatar with fallback and status indicator
BadgeWidget Notification and status badges
BreadcrumbWidget Navigation breadcrumbs
CarouselWidget Image/content carousel with auto-play
CopyButton Copy-to-clipboard button widget
CustomBottomSheet Styled bottom sheet component
CustomButton Button with loading states and icons
CustomCard Enhanced card with various styles
CustomChip Chip/tag component with delete action
CustomDialog Customizable dialog with actions
CustomListTile Enhanced list tile with more options
CustomTextField Styled text field with validation
DividerWidget Divider with optional text
DrawerWidget Navigation drawer component
DropdownWidget Custom dropdown selector
EmptyStateWidget Empty state with icon and CTA
ExpansionCard Expandable card with content
FloatingActionButtonWidget Custom FAB with extended options
IconButtonWidget Custom icon button
InfoBanner Information/warning banner
LoadingIndicator Custom loading spinner
MenuWidget Menu/popup menu component
NavigationBarWidget Bottom navigation bar
NotificationCard Notification display card
ProgressBar Linear and circular progress
RatingWidget Star rating component
SearchBarWidget Search input with filtering
SectionWrapper Section wrapper for layouts
SegmentedControl iOS-style segmented control
ShimmerLoading Shimmer loading effect
SkeletonLoader Skeleton screen loader
SnackbarWidget Custom snackbar component
StepperWidget Step-by-step progress indicator
TabsWidget Custom tabs component
TagWidget Tag/label component
TimelineWidget Timeline for events
TooltipWidget Custom tooltip component

📁 Project Structure #

lib/
├── app/
├── extensions/
│   ├── widgets/
│   │   ├── widget_core_extensions.dart
│   │   ├── widget_gesture_extensions.dart
│   │   ├── widget_clip_extensions.dart
│   │   ├── widget_transform_extensions.dart
│   │   ├── widget_layout_extensions.dart
│   │   ├── widget_material_extensions.dart
│   │   ├── widget_animation_extensions.dart
│   │   ├── widget_scroll_extensions.dart
│   │   ├── widget_sizing_extensions.dart
│   │   ├── widget_semantics_extensions.dart
│   │   ├── widget_text_extensions.dart
│   │   ├── widget_icon_extensions.dart
│   │   ├── widget_image_extensions.dart
│   │   ├── widget_list_extensions.dart
│   │   ├── widget_stack_extensions.dart
│   │   ├── widget_column_row_extensions.dart
│   │   └── widgets.dart
│   ├── animation_extensions.dart
│   ├── color_extensions.dart
│   ├── context_extensions.dart
│   ├── datetime_extensions.dart
│   ├── list_extensions.dart
│   ├── map_extensions.dart
│   ├── number_extensions.dart
│   ├── string_extensions.dart
│   ├── widget_extensions.dart
│   └── extensions.dart
├── pages/
├── utils/
│   ├── constants.dart
│   ├── spacing.dart
│   ├── validators.dart
│   ├── debounce.dart
│   ├── date_formatters.dart
│   ├── helpers.dart
│   ├── url_utils.dart
│   ├── string_formatters.dart
│   └── utils.dart
├── widgets/
│   ├── components/
│   │   ├── avatar_widget.dart
│   │   ├── badge_widget.dart
│   │   ├── breadcrumb_widget.dart
│   │   ├── carousel_widget.dart
│   │   ├── copy_button.dart
│   │   ├── custom_bottom_sheet.dart
│   │   ├── custom_button.dart
│   │   ├── custom_card.dart
│   │   ├── custom_chip.dart
│   │   ├── custom_dialog.dart
│   │   ├── custom_list_tile.dart
│   │   ├── custom_text_field.dart
│   │   ├── divider_widget.dart
│   │   ├── drawer_widget.dart
│   │   ├── dropdown_widget.dart
│   │   ├── empty_state_widget.dart
│   │   ├── expansion_card.dart
│   │   ├── floating_action_button_widget.dart
│   │   ├── icon_button_widget.dart
│   │   ├── info_banner.dart
│   │   ├── loading_indicator.dart
│   │   ├── menu_widget.dart
│   │   ├── navigation_bar_widget.dart
│   │   ├── notification_card.dart
│   │   ├── progress_bar.dart
│   │   ├── rating_widget.dart
│   │   ├── search_bar_widget.dart
│   │   ├── section_wrapper.dart
│   │   ├── segmented_control.dart
│   │   ├── shimmer_loading.dart
│   │   ├── skeleton_loader.dart
│   │   ├── snackbar_widget.dart
│   │   ├── stepper_widget.dart
│   │   ├── tabs_widget.dart
│   │   ├── tag_widget.dart
│   │   ├── timeline_widget.dart
│   │   ├── tooltip_widget.dart
│   │   └── components.dart
│   └── sections/
│       ├── animation_extensions_examples_section.dart
│       ├── debounce_throttle_section.dart
│       └── widget_extensions_section.dart
└── main.dart

💡 Best Practices #

Chaining Extensions #

Extensions can be chained for cleaner, more readable code:

const Text('Hello World')
  .padding(all: 16)
  .margin(all: 12)
  .center()
  .clipRRect(borderRadius: 8)
  .decoratedBox(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(8),
  )
  .onTap(() => print('Tapped!'))
  .tooltip('Click me');

Safe State Updates #

Always check if the widget is mounted before updating state:

void _incrementCounter() {
  if (mounted) {
    setState(() {
      _counter++;
    });
  }
}

Using Context Extensions #

Leverage context extensions for cleaner code:

// Instead of
Theme.of(context).colorScheme.primary
MediaQuery.of(context).size.width

// Use
context.colorScheme.primary
context.screenWidth

Const Constructors #

Use const constructors where possible for better performance:

const Text('Hello')
  .padding(all: 16)
  .center();

🎯 Examples #

🚀 Try the Live Demo to see all features in action!

See lib/main.dart for a comprehensive demo showcasing:

  • Widget Extensions Chaining - Multiple extensions chained together
  • Transform Extensions - Rotate, scale, and translate widgets
  • Clip Extensions - ClipRRect, ClipOval, ClipRect
  • Data Extensions - String, Number, DateTime, and List operations
  • Color Extensions - Color manipulation (darken, lighten)
  • Gesture Extensions - onTap, onLongPress, inkWell
  • Animation Extensions - Hero animations plus clamped/reversed values, curves, mirror, and controller helpers
  • Form Validation - Using validators utility
  • Context Extensions - Theme access, navigation, snackbar
  • Debounce & Throttle - Limit rapid calls with debounce/throttle helpers
  • Copyable Snippets - CopyButton widget to quickly copy example code

📝 License #

This project is open source and available for use in your Flutter projects.

🤝 Contributing #

Contributions are welcome! Feel free to:

  • Add new extensions
  • Improve existing ones
  • Fix bugs
  • Enhance documentation
  • Add more examples

📧 Support #

For issues, questions, or suggestions, please open an issue in the repository.


Built with ❤️ for the Flutter community

2
likes
150
points
121
downloads

Publisher

unverified uploader

Weekly Downloads

Extensions and reusable widgets. Provides 100+ widget extensions, 40+ pre-built UI components, data type extensions, form validators, spacing utilities, and more. Zero dependencies, fully documented, production-ready.

Homepage

Topics

#extensions #widget #utils #validators #spacing

Documentation

API reference

License

MIT (license)

Dependencies

cupertino_icons, flutter

More

Packages that depend on save_points_extensions_utils