wonzy_core_utils
A comprehensive collection of Flutter/Dart extensions and reusable widgets that eliminate boilerplate and accelerate UI development. One import, dozens of superpowers.
import 'package:wonzy_core_utils/wonzy_core_utils.dart';
Table of Contents
- Installation
- Context Extensions
- Num Extensions (Spacing, Padding, Duration)
- String Extensions
- Text Builder (Chainable API)
- Widget Extensions
- Image Extensions
- String → Image Shortcuts
- Layout Extensions
- Navigation Extensions
- Route Transitions
- Log Extensions
- Wonzy Widget Namespace
- Full Export Tree
- Requirements
- Contributing
- License
Installation
Option A — pub.dev (recommended)
dependencies:
wonzy_core_utils: ^2.0.0
Option B — Git dependency
dependencies:
wonzy_core_utils:
git:
url: https://github.com/muhammedeminalan/core_utils.git
ref: v2.0.0
Then run:
flutter pub get
Then import:
import 'package:wonzy_core_utils/wonzy_core_utils.dart';
Context Extensions
Shortcuts on BuildContext for screen size, theme, colors, and text styles.
// ── Screen Size ──
context.screenSize // MediaQuery size
context.width // screen width
context.height // screen height
context.screenHeight(0.5) // 50% of screen height
context.screenWidth(0.3) // 30% of screen width
// ── Theme ──
context.theme // ThemeData
context.colorScheme // ColorScheme
// ── Color Shortcuts ──
context.primaryColor // colorScheme.primary
context.secondaryColor // colorScheme.secondary
context.errorColor // colorScheme.error
context.surfaceColor // colorScheme.surface
context.onPrimaryColor // colorScheme.onPrimary
context.onSecondaryColor // colorScheme.onSecondary
context.onSurfaceColor // colorScheme.onSurface
context.outlineColor // colorScheme.outline
// ── Text Style Shortcuts ──
context.displayLarge // textTheme.displayLarge!
context.displayMedium // textTheme.displayMedium!
context.headlineLarge // textTheme.headlineLarge!
context.headlineMedium // textTheme.headlineMedium!
context.titleLarge // textTheme.titleLarge!
context.titleMedium // textTheme.titleMedium!
context.bodyLarge // textTheme.bodyLarge!
context.bodyMedium // textTheme.bodyMedium!
context.labelLarge // textTheme.labelLarge!
context.labelSmall // textTheme.labelSmall!
// ── Widget Theme Shortcuts ──
context.appBarTheme // theme.appBarTheme
context.cardTheme // theme.cardTheme
context.inputTheme // theme.inputDecorationTheme
context.elevatedButtonTheme // theme.elevatedButtonTheme
context.bottomNavTheme // theme.bottomNavigationBarTheme
// ── Divider ──
context.divider(color: Colors.grey)
Num Extensions
Turn any num into spacing, padding, radius, or duration — zero boilerplate.
// ── SizedBox Spacing ──
16.h // SizedBox(height: 16)
24.w // SizedBox(width: 24)
16.height // SizedBox(height: 16) — alias
24.width // SizedBox(width: 24) — alias
// ── EdgeInsets ──
12.all // EdgeInsets.all(12)
16.horizontal // EdgeInsets.symmetric(horizontal: 16)
8.vertical // EdgeInsets.symmetric(vertical: 8)
// ── BorderRadius ──
8.radius // BorderRadius.circular(8)
// ── Duration ──
300.ms // Duration(milliseconds: 300)
2.seconds // Duration(seconds: 2)
Real-world usage:
Column(
children: [
Text('Title'),
16.h, // instead of SizedBox(height: 16)
Text('Subtitle'),
24.h,
ElevatedButton(...)
.paddingAll(12) // uses 12.all internally
],
)
String Extensions
Rich set of string manipulation, formatting, validation, and conversion utilities.
Case Conversion
'hello world'.capitalize() // "Hello world"
'hello world'.toTitleCase() // "Hello World"
'hello world'.toSnakeCase() // "hello_world"
'hello world'.toKebabCase() // "hello-world"
'hello world'.toCamelCase() // "helloWorld"
Validation
'42'.isNumeric // true
'hello'.isAlphabetic // true
'abc123'.isAlphanumeric // true
'abc123'.hasNumber // true
'abc123'.hasLetter // true
''.isNullOrEmpty // true
'hello'.isNotNullOrEmpty // true
Manipulation
'Hello World'.reversed // "dlroW olleH"
'Hello World'.ellipsis(5) // "Hello..."
'Hello World'.trimmed // "Hello World" (trim shortcut)
'Hello World'.containsIgnoreCase('hello') // true
'Hello World'.replaceAllIgnoreCase('hello', 'Hi') // "Hi World"
'<b>bold</b>'.stripHtml // "bold"
'true'.toBool // true
'Hello World'.splitToList // ["Hello", "World"]
'abc'.charAtOr(5, 'x') // "x" (safe index access)
'abc'.padLeftToLength(6, '0') // "000abc"
'abc'.padRightToLength(6, '0') // "abc000"
'abc'.lengthSafe // 3
Turkish Formatters
'5551234567'.toTurkishPhoneFormat() // "+90 0555 123 4567"
'john'.toUsername() // "@john"
'@john'.toUsername() // "@john" (no double @)
'john'.toGmail() // "john@gmail.com"
'JOHN@gmail.com'.toGmail() // "john@gmail.com"
Text Builder
A fully chainable API to build styled Text widgets from any String. No more nested Text() + TextStyle() boilerplate.
// Basic usage
'Hello World'.text // plain Text widget
// Font weight
'Bold'.text.bold // FontWeight.w700
'Light'.text.light // FontWeight.w300
'Medium'.text.medium // FontWeight.w500
'SemiBold'.text.semiBold // FontWeight.w600
'Black'.text.black // FontWeight.w900
// Font style
'Italic'.text.italic // FontStyle.italic
// Decoration
'Underline'.text.underline
'Strikethrough'.text.lineThrough
'Overline'.text.overline
// Alignment
'Centered'.text.alignCenter
'Right'.text.alignRight
'Justified'.text.alignJustify
// Overflow
'Long text...'.text.ellipsis.maxLine(2)
// Custom values
'Custom'.text
.color(Colors.red)
.backgroundColor(Colors.yellow)
.fontSize(20)
.letterSpacing(1.5)
.wordSpacing(2.0)
.height(1.4)
.fontFamily('Roboto')
// Theme-based typography (Material 3)
'Display'.text.displayLarge(context)
'Headline'.text.headlineMedium(context)
'Title'.text.titleLarge(context)
'Body'.text.bodyMedium(context)
'Label'.text.labelSmall(context)
// Legacy Material 2 names (still supported)
'Legacy'.text.headline4(context)
'Legacy'.text.subtitle1(context)
'Legacy'.text.body1(context)
'Legacy'.text.caption(context)
// Merge with existing style
'Merged'.text.style(myTextStyle)
// ── Full chain example ──
'Welcome Back!'.text
.bold
.italic
.titleLarge(context)
.color(Colors.indigo)
.letterSpacing(0.5)
.maxLine(1)
.ellipsis
Widget Extensions
Padding & Margin
// Padding
widget.paddingAll(16) // all sides
widget.paddingHorizontal(12) // left + right
widget.paddingVertical(8) // top + bottom
widget.paddingSymmetric(h: 16, v: 8) // symmetric
widget.paddingOnly(left: 8, top: 16) // specific sides
widget.padding(EdgeInsets.all(10)) // custom EdgeInsets
// Margin (uses Container internally)
widget.marginAll(16)
widget.marginHorizontal(12)
widget.marginVertical(8)
widget.marginOnly(left: 8, bottom: 16)
Alignment
widget.center // Center(child: widget)
widget.alignLeft // Alignment.centerLeft
widget.alignRight // Alignment.centerRight
widget.alignTop // Alignment.topCenter
widget.alignBottom // Alignment.bottomCenter
widget.align(Alignment.topRight) // custom
Container
Wrap any widget in a fully customizable Container — one method call:
Text('Hello').container(
color: Colors.blue,
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(8),
borderRadius: 12,
width: 200,
height: 50,
gradient: LinearGradient(...),
border: Border.all(color: Colors.white),
boxShadow: [BoxShadow(...)],
alignment: Alignment.center,
)
Expanded & Flexible
widget.expanded() // Expanded(child: widget)
widget.expanded(flex: 2) // Expanded(flex: 2, child: widget)
widget.flexible() // Flexible(child: widget)
widget.flexible(flex: 2, fit: FlexFit.tight)
Size Constraints
widget.sized(width: 100, height: 50) // SizedBox wrapper
widget.square(60) // square SizedBox(60×60)
widget.expandedWidth // width: double.infinity
widget.expandedHeight // height: double.infinity
widget.constrained(
minWidth: 100,
maxWidth: 300,
minHeight: 50,
maxHeight: 200,
)
Decoration & Interaction
// ── Rounded Box ──
Text('Chip').roundedBox(
radius: 20,
backgroundColor: Colors.blue,
gradient: LinearGradient(...),
border: Border.all(color: Colors.white),
shadow: [BoxShadow(...)],
innerPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
outerMargin: EdgeInsets.all(4),
width: 120,
height: 40,
)
// ── Background ──
Icon(Icons.star).withBackground(
Colors.amber,
radius: 8,
innerPadding: EdgeInsets.all(8),
)
// ── Shadow ──
widget.withShadow(
color: Colors.black26,
blurRadius: 8,
offset: Offset(0, 2),
spreadRadius: 0,
borderRadius: 12,
)
// ── Card ──
widget.asCard(elevation: 4, radius: 16, color: Colors.white)
// ── Tap ──
widget.onTap(() => doSomething())
widget.onTap(() => doSomething(), borderRadius: BorderRadius.circular(8))
// ── InkWell (Material ripple) ──
widget.onInkTap(
() => doSomething(),
borderRadius: BorderRadius.circular(8),
splashColor: Colors.blue.withOpacity(0.2),
)
// ── Long Press ──
widget.onLongPress(() => showMenu())
// ── Visibility ──
widget.withVisibility(false) // hidden
widget.withVisibility(false, maintainSize: true) // invisible but takes space
// ── Opacity ──
widget.withOpacity(0.5)
// ── Border ──
widget.withBorder(color: Colors.grey, width: 1, radius: 8)
Transform
widget.rotated(0.785) // rotate by radians (≈45°)
widget.scaled(1.2) // scale up 120%
widget.translated(Offset(10, -5)) // translate by offset
Clip & Border
widget.clipRect() // ClipRect
widget.clipOval() // ClipOval (circle/ellipse)
widget.clipRounded(12) // ClipRRect with radius
widget.asCircle(size: 80, backgroundColor: Colors.grey) // circle container
Helpers
widget.withTooltip('Helpful info') // Tooltip wrapper
widget.asHero('unique-tag') // Hero animation
widget.withAspectRatio(16 / 9) // AspectRatio
widget.safeArea() // SafeArea (all edges)
widget.safeArea(top: true, bottom: false) // selective SafeArea
widget.ignorePointer() // IgnorePointer
widget.absorbPointer() // AbsorbPointer
Image Extensions
Extensions on Image widgets for shape, filter, overlay, and animation.
Shape
Image.asset('photo.png').rounded(16) // rounded corners
Image.asset('photo.png').circular(size: 80) // circular crop
Image.asset('photo.png').bordered(
color: Colors.white,
width: 3,
radius: 12,
)
Image.network(url).circleAvatar(
size: 60,
borderColor: Colors.white,
borderWidth: 2,
shadow: [BoxShadow(blurRadius: 8)],
)
Shadow & Color
Image.asset('photo.png').shadow(
blurRadius: 12,
offset: Offset(0, 4),
color: Colors.black26,
)
Image.asset('photo.png').colorFiltered(
color: Colors.blue,
blendMode: BlendMode.colorBurn,
)
Image.asset('photo.png').grayscale() // black & white
Image.asset('photo.png').sepia() // antique effect
Image.asset('photo.png').opacity(0.7) // semi-transparent
Blur & Overlay
Image.asset('bg.png').blurred(sigmaX: 5, sigmaY: 5)
Image.asset('banner.png').gradientOverlay(
colors: [Colors.transparent, Colors.black87],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
borderRadius: 12,
)
Image.asset('banner.png').colorOverlay(Colors.black45)
Size & Animation
Image.asset('photo.png').sized(width: 200, height: 150)
Image.asset('photo.png').ratio(16 / 9)
Image.network(url).fadeIn(duration: Duration(milliseconds: 500))
String → Image Shortcuts
Create image widgets directly from strings:
// ── Asset ──
'assets/logo.png'.asAssetImage(width: 120, fit: BoxFit.contain)
// ── Network ──
'https://example.com/photo.jpg'.asNetworkImage(
width: 200,
height: 200,
fit: BoxFit.cover,
)
// ── Smart Network (with loading spinner + error fallback) ──
'https://example.com/photo.jpg'.asSmartNetworkImage(
width: 200,
height: 200,
fit: BoxFit.cover,
borderRadius: 12,
placeholder: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
)
// ── Image Providers ──
'assets/logo.png'.toAssetImageProvider()
'https://example.com/photo.jpg'.toNetworkImageProvider()
// ── Decoration Images (for Container backgrounds) ──
'assets/bg.png'.asDecorationImage(fit: BoxFit.cover)
'https://example.com/bg.jpg'.asNetworkDecorationImage(opacity: 0.8)
// ── ImageProvider Extensions ──
AssetImage('logo.png').toImage(width: 100)
NetworkImage(url).toCircleAvatar(radius: 30)
AssetImage('logo.png').toDecorationImage(fit: BoxFit.cover)
NetworkImage(url).toInk(width: 200, height: 150)
Layout Extensions
List → Column / Row
Build Column or Row from a list of widgets with optional spacing:
// Column with spacing
[
Text('First'),
Text('Second'),
Text('Third'),
].column(spacing: 8)
// Column with full customization
[widgets].column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
spacing: 12,
)
// Row with spacing
[Icon(Icons.star), Text('Favorite')].row(spacing: 4)
// Row with full customization
[widgets].row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 8,
)
Axis Alignment on Existing Widgets
Chain alignment properties directly on Column or Row:
// Column cross-axis
Column(children: [...]).crossStart
Column(children: [...]).crossCenter
Column(children: [...]).crossEnd
Column(children: [...]).crossStretch
// Column main-axis
Column(children: [...]).mainStart
Column(children: [...]).mainCenter
Column(children: [...]).mainEnd
Column(children: [...]).mainSpaceBetween
Column(children: [...]).mainSpaceAround
Column(children: [...]).mainSpaceEvenly
// Row cross-axis
Row(children: [...]).crossStart
Row(children: [...]).crossCenter
Row(children: [...]).crossEnd
Row(children: [...]).crossStretch
// Row main-axis
Row(children: [...]).mainStart
Row(children: [...]).mainEnd
Row(children: [...]).mainSpaceBetween
Row(children: [...]).mainSpaceEvenly
// ── Chain them together ──
Column(children: [...]).crossCenter.mainSpaceBetween
Row(children: [...]).mainEnd.crossStretch
Navigation Extensions
All navigation shortcuts are available directly on BuildContext:
// ── Basic Navigation ──
context.pushPage(DetailPage())
context.pop()
context.pop(result) // pop with result
// ── Replacement ──
context.pushReplacementPage(HomePage())
// ── Clear Stack ──
context.pushAndRemoveUntilPage(LoginPage()) // removes all routes
context.pushAndRemoveUntilPage(
HomePage(),
predicate: (route) => route.isFirst, // custom predicate
)
// ── Named Routes ──
context.pushNamed('/detail', arguments: {'id': 42})
context.pushReplacementNamed('/home')
// ── With Transitions ──
context.pushPage(
ProfilePage(),
transitionBuilder: RouteTransitions.fadeIn(),
transitionDuration: Duration(milliseconds: 400),
)
context.pushReplacementPage(
HomePage(),
transitionBuilder: RouteTransitions.slideFromBottom(),
)
// ── Fullscreen Dialog ──
context.pushPage(SettingsPage(), fullscreenDialog: true)
// ── Navigator accessor ──
context.navigator // Navigator.of(context)
Route Transitions
RouteTransitions provides 17+ ready-to-use transition builders:
// ── Basic ──
RouteTransitions.fadeIn() // fade in
RouteTransitions.slide() // slide from right (default)
RouteTransitions.scale() // zoom
RouteTransitions.rotation() // rotate
// ── Directional Slides ──
RouteTransitions.slideFromTop()
RouteTransitions.slideFromBottom()
RouteTransitions.slideFromLeft()
RouteTransitions.slideFromRight()
// ── Size ──
RouteTransitions.size() // expand vertically
RouteTransitions.size(axis: Axis.horizontal) // expand horizontally
// ── Combined ──
RouteTransitions.fadeScale() // fade + scale
RouteTransitions.fadeSlide() // fade + slide from bottom
RouteTransitions.fadeRotate() // fade + rotate
RouteTransitions.scaleRotate() // scale + rotate
RouteTransitions.slideScale() // slide + scale
// ── 3D Flip ──
RouteTransitions.flipX() // flip around X axis
RouteTransitions.flipY() // flip around Y axis
// ── Presets ──
RouteTransitions.zoomIn() // fast zoom in
RouteTransitions.zoomOut() // zoom out
RouteTransitions.bounceIn() // bounce effect
RouteTransitions.elasticIn() // elastic spring
// ── Custom curve ──
RouteTransitions.fadeIn(curve: Curves.easeInOutCubic)
RouteTransitions.slide(begin: Offset(0.5, 0.5), curve: Curves.bounceOut)
Usage with navigation:
context.pushPage(
DetailPage(),
transitionBuilder: RouteTransitions.fadeScale(),
transitionDuration: Duration(milliseconds: 500),
);
Log Extensions
Debug logging shortcuts on String:
'User logged in'.debugLog() // debugPrint
'Loading data'.infoLog() // log level 800 (INFO)
'Cache miss'.warningLog() // log level 900 (WARNING)
'Connection failed'.errorLog() // log level 1000 (ERROR)
// Custom log name
'Data fetched'.infoLog(name: 'API') // [API] Data fetched
'Timeout'.errorLog(name: 'NETWORK') // [NETWORK] Timeout
Wonzy Widget Namespace
v2.0.0 itibarıyla tüm widget'lara Wonzy namespace'i üzerinden erişilir.
import 'package:wonzy_core_utils/wonzy_core_utils.dart';
Wonzy.appBar
PreferredSizeWidget döndürür — Scaffold.appBar: ile doğrudan uyumlu:
Scaffold(
appBar: Wonzy.appBar(
// Başlık
title: 'Ana Sayfa',
titleWidget: CustomTitleWidget(), // title yerine geçer
titleStyle: TextStyle(fontSize: 20),
titleColor: Colors.white,
titleFontSize: 18,
titleFontWeight: FontWeight.bold,
centerTitle: true,
// Geri butonu
leadingIcon: Icons.menu,
leadingIconColor: Colors.white,
leadingIconSize: 24,
onLeadingPressed: () => openDrawer(),
leading: CustomWidget(), // leadingIcon yerine geçer
automaticallyImplyLeading: true,
// Eylemler
actions: [
Wonzy.button.icon(iconData: Icons.search, onPressed: () {}),
Wonzy.button.icon(iconData: Icons.more_vert, onPressed: () {}),
],
// Görünüm
backgroundColor: Colors.indigo,
gradient: LinearGradient(colors: [Colors.indigo, Colors.purple]),
elevation: 4,
shadowColor: Colors.black26,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(bottom: Radius.circular(16)),
),
borderRadius: 16, // alt köşeler için kısayol
// Alt bileşen (TabBar vb.)
bottom: TabBar(tabs: [...]),
// Durum çubuğu
systemOverlayStyle: SystemUiOverlayStyle.light,
),
)
Wonzy.button.standard
Yükleme durumu, gradient ve tam özelleştirme destekli genel amaçlı buton:
Wonzy.button.standard(
text: 'Giriş Yap',
onPressed: () => signIn(),
onLongPress: () => showOptions(),
// İkon
iconData: Icons.login,
iconSize: 20,
iconColor: Colors.white,
iconSpacing: 8,
// Boyut
width: double.infinity,
height: 48,
padding: EdgeInsets.symmetric(horizontal: 24),
borderRadius: 12,
// Renkler
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
disabledBackgroundColor: Colors.grey,
// Yükleme durumu
isLoading: _isLoading,
loadingColor: Colors.white,
loadingSize: 20,
// Devre dışı
isDisabled: false,
// Gradient
gradient: LinearGradient(colors: [Colors.indigo, Colors.purple]),
// Kenarlık
borderColor: Colors.indigoAccent,
borderWidth: 2,
// Yükseklik (elevation)
elevation: 4,
// İpucu
tooltip: 'Hesabınıza giriş yapın',
)
Wonzy.button.icon
Rozet desteği olan dairesel ikon butonu:
Wonzy.button.icon(
iconData: Icons.notifications,
onPressed: () => showNotifications(),
size: 48,
backgroundColor: Colors.indigo,
foregroundColor: Colors.white,
borderColor: Colors.white,
borderWidth: 2,
elevation: 4,
// Rozet
badgeCount: 5,
badgeColor: Colors.red,
badgeTextColor: Colors.white,
showBadge: true,
// Yükleme / devre dışı
isLoading: false,
isDisabled: false,
// Gradient
gradient: RadialGradient(colors: [Colors.indigo, Colors.purple]),
)
Wonzy.bottomSheet / Wonzy.bottomSheet.show
Özellik açısından zengin bottom sheet — widget olarak veya modal olarak kullanılabilir:
// ── Modal göster ──
await Wonzy.bottomSheet.show(
context,
title: 'Filtre Seçenekleri',
subtitle: 'Tercihlerinizi seçin',
child: FilterWidget(),
// Tutamaç
showHandle: true,
handleColor: Colors.grey,
// Kapat butonu
showCloseButton: true,
// Eylemler
primaryActionText: 'Uygula',
onPrimaryAction: () => applyFilter(),
secondaryActionText: 'Sıfırla',
onSecondaryAction: () => resetFilter(),
// Görünüm
backgroundColor: Colors.white,
borderRadius: 20,
elevation: 8,
// Boyut
maxHeight: 0.8, // ekranın %80'i
padding: EdgeInsets.all(16),
// Davranış
isDismissible: true,
enableDrag: true,
isDraggable: true,
useSafeArea: true,
// Sürüklenebilir seçenekler
initialChildSize: 0.5,
minChildSize: 0.25,
maxChildSize: 0.9,
snap: true,
// Kaydırma
isScrollable: true,
);
// ── Widget olarak (builder içinde) ──
Wonzy.bottomSheet(
title: 'Seçenekler',
children: [
ListTile(title: Text('Seçenek 1')),
ListTile(title: Text('Seçenek 2')),
],
footer: Wonzy.button.standard(text: 'Tamam', onPressed: () {}),
)
Wonzy.textField
A production-ready, type-driven smart text field built on top of FormBuilderTextField. Select a CustomFieldType and the widget automatically configures keyboard type, autofill hints, obscure mode, and validation rules — all with Turkish error messages by default.
Requires:
flutter_form_builderandform_builder_validators(already included as transitive dependencies).
CustomFieldType Enum
| Type | Keyboard | Autofill | Obscure | Default Min Length |
|---|---|---|---|---|
text |
text | — | false | — |
email |
emailAddress | false | — | |
phone |
phone | telephoneNumber | false | — |
password |
visiblePassword | password | true | 6 |
number |
number | — | false | — |
studentNumber |
number | — | false | 6 |
Temel Kullanım
// Basit metin alanı
Wonzy.textField(
name: 'username',
label: 'Kullanıcı Adı',
hint: 'Kullanıcı adınızı girin',
required: true,
)
// E-posta — otomatik klavye, otomatik doldurma ve doğrulama
Wonzy.textField(
name: 'email',
type: CustomFieldType.email,
label: 'E-posta',
required: true,
)
// Şifre — gizleme, göster/gizle ikonu, min 6 karakter
Wonzy.textField(
name: 'password',
type: CustomFieldType.password,
label: 'Şifre',
required: true,
)
// Telefon — sayısal klavye, telefon otodoldurma
Wonzy.textField(
name: 'phone',
type: CustomFieldType.phone,
label: 'Telefon',
required: true,
)
// Sayı — sayısal klavye ve doğrulama
Wonzy.textField(
name: 'age',
type: CustomFieldType.number,
label: 'Yaş',
)
// Öğrenci numarası — sayısal, min 6 karakter
Wonzy.textField(
name: 'student_no',
type: CustomFieldType.studentNumber,
label: 'Öğrenci No',
required: true,
)
Şifre Göster/Gizle & Temizle Butonu
// Şifre alanı (göster/gizle varsayılan olarak etkin)
Wonzy.textField(
name: 'password',
type: CustomFieldType.password,
label: 'Şifre',
showPasswordToggle: true, // 👁 geçiş ikonu (varsayılan: true)
)
// Temizle butonu (controller gerektirir)
final _controller = TextEditingController();
Wonzy.textField(
name: 'search',
label: 'Ara',
controller: _controller,
showClearButton: true, // ✕ metin varken temizleme ikonu
)
Odak Yönetimi & Gönderim Akışı
final _emailFocus = FocusNode();
final _passwordFocus = FocusNode();
// E-posta → Şifre otomatik odaklanma
Wonzy.textField(
name: 'email',
type: CustomFieldType.email,
label: 'E-posta',
focusNode: _emailFocus,
nextFocusNode: _passwordFocus, // "İleri" bas → odak buraya geçer
)
Wonzy.textField(
name: 'password',
type: CustomFieldType.password,
label: 'Şifre',
focusNode: _passwordFocus,
onSubmitted: (_) => _submit(), // "Tamam" bas → formu gönder
)
Doğrulama & Özel Hata Mesajları
Wonzy.textField(
name: 'email',
type: CustomFieldType.email,
label: 'E-posta',
required: true,
requiredMessage: 'E-posta adresi gereklidir',
invalidEmailMessage: 'Lütfen geçerli bir e-posta girin',
)
// Min/max uzunluk doğrulaması
Wonzy.textField(
name: 'bio',
label: 'Biyografi',
minLength: 10,
maxLengthValidator: 200,
maxLength: 200,
showCounter: true,
maxLines: 5,
minLengthMessage: 'En az 10 karakter yazmalısınız',
maxLengthMessage: 'En fazla 200 karakter olabilir',
)
// Özel doğrulayıcı
Wonzy.textField(
name: 'code',
label: 'Davet Kodu',
customValidator: (value) {
if (value != null && !value.startsWith('INV-')) {
return 'Kod "INV-" ile başlamalıdır';
}
return null;
},
)
Değer Dönüşümü
Wonzy.textField(
name: 'email',
type: CustomFieldType.email,
label: 'E-posta',
transform: (value) => value?.trim().toLowerCase(),
)
Görünüm Özelleştirme
Wonzy.textField(
name: 'note',
label: 'Not',
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.indigo, width: 2),
),
style: TextStyle(fontSize: 16),
labelStyle: TextStyle(color: Colors.grey),
)
// Tam decoration geçersizleştirme
Wonzy.textField(
name: 'custom',
decoration: InputDecoration(
labelText: 'Tam Özel',
filled: true,
fillColor: Colors.grey.shade100,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(20)),
),
)
İkonlar
Wonzy.textField(
name: 'email',
type: CustomFieldType.email,
label: 'E-posta',
prefixIcon: Icon(Icons.email_outlined),
suffixIcon: Icon(Icons.check_circle, color: Colors.green),
)
Tam Form Örneği
final _formKey = GlobalKey<FormBuilderState>();
final _passwordFocus = FocusNode();
final _searchController = TextEditingController();
FormBuilder(
key: _formKey,
child: Column(
children: [
Wonzy.textField(
name: 'email',
type: CustomFieldType.email,
label: 'E-posta',
prefixIcon: Icon(Icons.email_outlined),
required: true,
nextFocusNode: _passwordFocus,
transform: (v) => v?.trim().toLowerCase(),
),
SizedBox(height: 16),
Wonzy.textField(
name: 'password',
type: CustomFieldType.password,
label: 'Şifre',
prefixIcon: Icon(Icons.lock_outline),
required: true,
focusNode: _passwordFocus,
minLength: 8,
),
SizedBox(height: 16),
Wonzy.textField(
name: 'phone',
type: CustomFieldType.phone,
label: 'Telefon',
prefixIcon: Icon(Icons.phone_outlined),
),
SizedBox(height: 24),
Wonzy.button.standard(
text: 'Giriş Yap',
width: double.infinity,
onPressed: () {
if (_formKey.currentState?.saveAndValidate() ?? false) {
final data = _formKey.currentState!.value;
print(data); // {email: ..., password: ..., phone: ...}
}
},
child: Text('Giriş Yap'),
),
],
),
)
All Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
name * |
String |
— | FormBuilder field name (required) |
type |
CustomFieldType |
.text |
Field type — drives defaults |
label |
String? |
null |
Label text |
hint |
String? |
null |
Hint text |
helperText |
String? |
null |
Helper text below the field |
initialValue |
String? |
null |
Initial value |
controller |
TextEditingController? |
null |
External text controller |
focusNode |
FocusNode? |
null |
External focus node |
nextFocusNode |
FocusNode? |
null |
Focus moves here on submit |
enabled |
bool |
true |
Whether the field is enabled |
readOnly |
bool |
false |
Read-only mode |
autofocus |
bool |
false |
Auto-focus on build |
obscureText |
bool? |
null (type default) |
Obscure text override |
enableSuggestions |
bool |
true |
Keyboard suggestions |
autocorrect |
bool |
true |
Auto-correct |
maxLength |
int? |
null |
Max character count (with counter) |
maxLines |
int |
1 |
Max lines |
minLines |
int? |
null |
Min lines |
keyboardType |
TextInputType? |
null (type default) |
Keyboard type override |
textInputAction |
TextInputAction? |
null (auto: next/done) |
Keyboard action button |
inputFormatters |
List<TextInputFormatter>? |
null |
Input formatters |
autofillHints |
Iterable<String>? |
null (type default) |
Autofill hints override |
showCounter |
bool |
false |
Show character counter |
showClearButton |
bool |
false |
Show clear (×) icon (needs controller) |
showPasswordToggle |
bool |
true |
Show password toggle (password type only) |
prefixIcon |
Widget? |
null |
Leading icon |
suffixIcon |
Widget? |
null |
Trailing icon (combined with toggle/clear) |
onTap |
VoidCallback? |
null |
On tap callback |
onChanged |
ValueChanged<String?>? |
null |
On change callback |
onSubmitted |
ValueChanged<String?>? |
null |
On submit callback |
transform |
String? Function(String?)? |
null |
Value transformer before save |
autovalidateMode |
AutovalidateMode |
.onUserInteraction |
Validation trigger mode |
required |
bool |
false |
Required field rule |
minLength |
int? |
null (type default) |
Min length validation |
maxLengthValidator |
int? |
null |
Max length validation |
customValidator |
FormFieldValidator<String>? |
null |
Custom validator (appended last) |
requiredMessage |
String? |
'Bu alan zorunludur' |
Required error override |
invalidEmailMessage |
String? |
'Geçerli bir e-posta...' |
Email error override |
invalidPhoneMessage |
String? |
'Geçerli bir telefon...' |
Phone error override |
minLengthMessage |
String? |
'En az N karakter...' |
Min length error override |
maxLengthMessage |
String? |
'En fazla N karakter...' |
Max length error override |
numericMessage |
String? |
'Sadece rakam girin' |
Numeric error override |
decoration |
InputDecoration? |
null |
Full decoration override |
contentPadding |
EdgeInsetsGeometry? |
null |
Content padding |
border |
InputBorder? |
null |
Default border |
enabledBorder |
InputBorder? |
null |
Enabled border |
focusedBorder |
InputBorder? |
null |
Focused border |
errorBorder |
InputBorder? |
null |
Error border |
style |
TextStyle? |
null |
Field text style |
labelStyle |
TextStyle? |
null |
Label style |
hintStyle |
TextStyle? |
null |
Hint style |
Full Export Tree
Tüm public API tek bir barrel dosyası üzerinden sunulur — import 'package:wonzy_core_utils/wonzy_core_utils.dart';
lib/wonzy_core_utils.dart
│
├── lib/core_utils.dart (Extension barrel)
│ │
│ ├── Context Extensions
│ │ └── ContextExtension on BuildContext
│ │ (screenSize, width, height, theme, colorScheme, textTheme,
│ │ primaryColor, secondaryColor, ..., appBarTheme, cardTheme, ...)
│ │
│ ├── Layout Extensions
│ │ ├── ColumnCrossAxis / ColumnMainAxis on Column
│ │ │ (.crossStart, .crossCenter, .mainSpaceBetween, ...)
│ │ ├── RowCrossAxis / RowMainAxis on Row
│ │ │ (.crossStart, .mainEnd, .mainSpaceEvenly, ...)
│ │ ├── ColumnExtension on List<Widget>
│ │ │ (.column(spacing: ...))
│ │ └── RowExtension on List<Widget>
│ │ (.row(spacing: ...))
│ │
│ ├── Navigation Extensions
│ │ ├── NavigatorExtensions on BuildContext
│ │ │ (.pushPage, .pop, .pushReplacementPage, .pushAndRemoveUntilPage,
│ │ │ .pushNamed, .pushReplacementNamed)
│ │ └── RouteTransitions (static class)
│ │ (.fadeIn, .slide, .slideFromTop, .slideFromBottom, .scale,
│ │ .rotation, .size, .fadeScale, .fadeSlide, .fadeRotate,
│ │ .scaleRotate, .flipX, .flipY, .zoomIn, .zoomOut,
│ │ .bounceIn, .elasticIn, .slideScale)
│ │
│ ├── Primitive Extensions
│ │ ├── SizeExtensions on num
│ │ │ (.h, .w, .height, .width, .all, .horizontal, .vertical,
│ │ │ .radius, .ms, .seconds)
│ │ ├── StringExtensions on String
│ │ │ (.capitalize, .toTitleCase, .toSnakeCase, .toKebabCase,
│ │ │ .toCamelCase, .isNumeric, .isAlphabetic, .isAlphanumeric,
│ │ │ .reversed, .ellipsis, .containsIgnoreCase, .stripHtml,
│ │ │ .toBool, .toTurkishPhoneFormat, .toUsername, .toGmail, ...)
│ │ └── TextBuilderExtension on String
│ │ (.text → TextBuilder chainable API)
│ │
│ ├── Utility Extensions
│ │ └── LogExtensions on String
│ │ (.debugLog, .infoLog, .warningLog, .errorLog)
│ │
│ └── Widget Extensions
│ ├── PaddingExtensions on Widget
│ │ (.paddingAll, .paddingHorizontal, .paddingVertical,
│ │ .paddingSymmetric, .paddingOnly, .padding,
│ │ .marginAll, .marginHorizontal, .marginVertical, .marginOnly)
│ ├── AlignmentExtensions on Widget
│ │ (.center, .alignLeft, .alignRight, .alignTop, .alignBottom, .align)
│ ├── ContainerExtensions on Widget
│ │ (.container(...))
│ ├── FlexExtensions on Widget
│ │ (.expanded, .flexible)
│ ├── SizeConstraintExtensions on Widget
│ │ (.sized, .square, .expandedWidth, .expandedHeight, .constrained)
│ ├── WidgetDecorationExtensions on Widget
│ │ (.roundedBox, .withBackground, .withShadow, .asCard,
│ │ .onTap, .onInkTap, .onLongPress, .withVisibility, .withOpacity,
│ │ .rotated, .scaled, .translated, .withTooltip, .asHero,
│ │ .withAspectRatio, .safeArea, .ignorePointer, .absorbPointer,
│ │ .clipRect, .clipOval, .clipRounded, .asCircle, .withBorder)
│ └── ImageExtensions on Image
│ (.rounded, .circular, .bordered, .circleAvatar, .shadow,
│ .colorFiltered, .grayscale, .sepia, .opacity, .blurred,
│ .sized, .ratio, .gradientOverlay, .colorOverlay, .fadeIn)
│
│ String → Image Extensions
│ ├── StringImageExtensions on String
│ │ (.asAssetImage, .asNetworkImage, .asSmartNetworkImage,
│ │ .toAssetImageProvider, .toNetworkImageProvider,
│ │ .asDecorationImage, .asNetworkDecorationImage)
│ └── ImageProviderExtensions on ImageProvider
│ (.toImage, .toDecorationImage, .toCircleAvatar, .toInk)
│
└── lib/src/wonzy.dart (Wonzy Namespace)
├── Wonzy (final class — namespace)
│ (.appBar, .button, .bottomSheet, .textField)
│
├── Wonzy.appBar(...) → PreferredSizeWidget
├── Wonzy.button.standard(...)→ ElevatedButton tarzı buton
├── Wonzy.button.icon(...) → Rozet destekli ikon buton
├── Wonzy.bottomSheet(...) → CustomBottomSheet widget'ı
├── Wonzy.bottomSheet.show(...)→ Future<T?> modal
├── Wonzy.textField(...) → Form entegreli metin alanı
└── CustomFieldType (enum — dışa aktarılır)
Requirements
| Requirement | Version |
|---|---|
| Dart SDK | ^3.11.0 |
| Flutter | >=3.29.0 |
Contributing
See CONTRIBUTING.md for guidelines.
License
This project is licensed under the MIT License — see the LICENSE file for details.
Libraries
- core_utils
- wonzy_core_utils — Extension'lar katmanı.
- wonzy_core_utils
- wonzy_core_utils — Kanonik giriş noktası (v2.0.0+).