Skip to content
/ fluiver Public

An expressive extensions and helpers package focused on productivity.

License

Notifications You must be signed in to change notification settings

esenmx/fluiver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

166 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fluiver

pub license

Write less. Build more.

Fluiver keeps everyday Flutter reads to a single dot (context. / list.) without sacrificing clarity. Extensions feel native, stay autocomplete-friendly, and avoid boilerplate.

dependencies:
  fluiver: ^2.2.0

Install

Add fluiver to your pubspec.yaml, then import package:fluiver/fluiver.dart.


Quickstart

// Single-dot reads
final color = context.primaryColor;
final width = context.screenWidth;
final title = context.titleLargeTextStyle;

// Padded row with spacing
PaddedRow(
  padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
  spacing: 8,
  children: const [Icon(Icons.home), Text('Home')],
);

Fluiver vs. vanilla Flutter (single-dot wins)

// ❌ Vanilla Flutter
final primary = Theme.of(context).colorScheme.primary;
final width = MediaQuery.of(context).size.width;
final title = Theme.of(context).textTheme.titleLarge!;

// ✅ With fluiver (one dot, cleaner, readable)
final primary = context.primaryColor;
final width = context.screenWidth;
final title = context.titleLargeTextStyle;
final widgets = items.separated(() => const Divider()).toList();

Debounced search — the right way

final _debounce = Debounce(const Duration(milliseconds: 400));

TextField(
  onChanged: (query) => _debounce(() => searchApi(query)),
)

Nested grids without performance issues

ListView(
  children: [
    const Text('Featured'),
    FlexGrid(
      crossAxisCount: 3,
      crossAxisSpacing: 8,
      mainAxisSpacing: 8,
      children: products.map((p) => ProductCard(p)).toList(),
    ),
    const Text('Recent'),
    FlexGrid(
      crossAxisCount: 2,
      children: recentItems.map((r) => ItemTile(r)).toList(),
    ),
  ],
);

Extensions at a glance

BuildContext

context.screenWidth; context.screenHeight;
context.isPlatformDark; context.isThemeDark;
context.primaryColor; context.surfaceColor; context.errorColor;
context.bodyLargeTextStyle; context.titleMediumTextStyle;

DateTime

dateTime.addDays(7);
dateTime.addMonths(1);
dateTime.truncateTime();
dateTime.isToday;
birthDate.age();

String

'hello'.capitalize;          // Hello
'john doe'.capitalizeAll;    // John Doe
'John Doe'.initials();       // JD

Object

// Scope function
int? value = 'not42'.let(int.tryParse);

Iterable

list.separated(() => Divider());

Map & Stream

stream.whereType<int>();

Widgets

PaddedFlex / PaddedRow / PaddedColumn

Apply padding before layout while keeping the full Flex API (spacing, alignment, direction, clip behavior).

PaddedColumn(
  padding: const EdgeInsets.all(12),
  spacing: 6,
  children: const [Text('Title'), Text('Subtitle')],
);

FlexGrid

Non-scrolling grid built with custom RenderObject. Drop-in replacement for GridView with shrinkWrap: true — without the performance penalty.

FlexGrid(
  crossAxisCount: 3,
  mainAxisSpacing: 8,
  crossAxisSpacing: 8,
  padding: EdgeInsets.all(16),
  children: [...],
)

TickerBuilder

Frame-by-frame rebuilds with elapsed duration. Perfect for timers and animations.

TickerBuilder(
  builder: (context, elapsed) => Text('${elapsed.inSeconds}s'),
)

Helpers

Debounce & Throttle

final debounce = Debounce(Duration(milliseconds: 300));
onChanged: (text) => debounce(() => search(text));

final throttle = ThrottleFirst(Duration(seconds: 1));
onTap: () => throttle(() => submit());

Observers

React to system changes without boilerplate.

LocaleObserver((locales) => ...);
BrightnessObserver((brightness) => ...);
AppLifecycleObserver((state) => ...);

Connectivity

if (await hasDeviceConnection()) {
  // Online
}

Philosophy

  • Single-dot first — one autocomplete hit (context. / list.) for common needs without sacrificing clarity.
  • Expressive — names read like English and stay concise.
  • Minimal — only the helpers you actually reach for.
  • Performant — custom render objects where it matters.

Agent Rules

Add these rules to your Cursor/Claude Code/AntiGravity "Rules for AI" to generate optimal fluiver code:

@fluiver_rules

Context Access: ALWAYS use context.extension formula.

  • Theme.of(context).colorScheme.primary
  • context.primaryColor
  • Theme.of(context).textTheme.titleLarge
  • context.titleLargeTextStyle
  • MediaQuery.of(context).size.width
  • context.screenWidth

Layout Efficiency: Prefer declarative widgets over imperative nesting.

  • Padding(padding: EdgeInsets.all(16), child: Column(...))
  • PaddedColumn(padding: EdgeInsets.all(16), ...)

About

An expressive extensions and helpers package focused on productivity.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published