ionex 1.1.0
ionex: ^1.1.0 copied to clipboard
A lightweight, high-performance, molecular state management library for Flutter.
ionex #
Ionex is a tiny Flutter state-management package for small, explicit, and predictable UI state. It centers on a single typed reactive primitive, Ion<T>, and two lightweight widgets for observing and providing state without introducing a heavy framework.
Why Ionex? #
- Minimal API designed for concise state mutation
- Built on Flutter's native
ValueNotifierfor predictable updates - No bulky framework concepts or hidden lifecycle complexity
- Great for feature-level state, simple reactive UIs, and reusable controller objects
Highlights #
Ion<T>as a lightweight reactive state containerIonBuilder<T>for scoped rebuildsIonProvider<Ion<T>>for type-safe tree injection- Example app included in
example/lib/main.dart - Unit tests covering core behavior
Current project status #
- Version:
1.1.0 - Flutter tests: passing
- Flutter analyzer: no issues found
- License: MIT
- Changelog: available in
CHANGELOG.md
Installation #
Add ionex to your project:
flutter pub add ionex
Or add it directly to pubspec.yaml:
dependencies:
ionex: ^1.1.0
Then fetch dependencies:
flutter pub get
Requirements #
- Flutter SDK >= 3.0.0
- Dart SDK >= 3.0.0 < 4.0.0
Package layout #
lib/ionex.dart: public exportslib/src/core/ion.dart:Ion<T>reactive state primitivelib/src/widgets/ion_builder.dart: rebuilds only the widget subtree that depends on an Ionlib/src/widgets/ion_provider.dart: injects an Ion into the widget treeexample/lib/main.dart: runnable demonstration apptest/core/ion_test.dart: core unit tests
Core API #
Ion<T> #
Ion<T> is the fundamental reactive unit in Ionex. It stores a typed value and notifies listeners whenever the value changes.
final counter = Ion<int>(0);
counter.state; // 0
counter.set(1);
counter.update((current) => current + 1);
counter.reset(0);
Available methods #
set(newValue): replace the current state immediatelyupdate((current) => nextValue): derive a new state from the current onereset(initialValue): restore the ion to a known valuestate: access the current value synchronously
UI helpers #
IonBuilder<T> #
IonBuilder<T> listens to an Ion and rebuilds only the widget subtree that depends on it.
IonBuilder<int>(
ion: counter,
builder: (context, value) {
return Text('Count: $value');
},
);
IonProvider #
IonProvider installs an Ion into the widget tree so descendants can retrieve it without prop drilling.
final authStatus = Ion<String>('unauthenticated');
IonProvider<Ion<String>>(
ion: authStatus,
child: const ProfileScreen(),
);
Retrieve the injected Ion from the current BuildContext:
final authStatus = IonProvider.of<Ion<String>>(context);
print(authStatus.state);
Usage examples #
1. Simple counter #
import 'package:flutter/material.dart';
import 'package:ionex/ionex.dart';
final counter = Ion<int>(0);
class CounterView extends StatelessWidget {
const CounterView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: IonBuilder<int>(
ion: counter,
builder: (context, value) {
return Text('Count: $value');
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => counter.update((current) => current + 1),
child: const Icon(Icons.add),
),
);
}
}
2. Context-based state access #
import 'package:flutter/material.dart';
import 'package:ionex/ionex.dart';
final themeIon = Ion<ThemeMode>(ThemeMode.light);
final messageIon = Ion<String>('Hello from IonProvider Context!');
class AppRoot extends StatelessWidget {
const AppRoot({super.key});
@override
Widget build(BuildContext context) {
return IonBuilder<ThemeMode>(
ion: themeIon,
builder: (context, themeMode) {
return IonProvider<Ion<String>>(
ion: messageIon,
child: MaterialApp(
themeMode: themeMode,
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
home: Builder(
builder: (context) {
final message = IonProvider.of<Ion<String>>(context);
return Scaffold(
body: Center(
child: Text(message.state),
),
);
},
),
),
);
},
);
}
}
3. Resetting and deriving state #
final filter = Ion<String>('all');
final count = Ion<int>(0);
filter.reset('all');
count.update((current) => current + 5);
Example app #
The example app in example/lib/main.dart demonstrates two common flows:
- shared global state for counter and theme
- context-scoped state access with
IonProviderandIonProvider.of<T>(context)
Run the example:
cd example
flutter run
Testing and verification #
flutter test→ passedflutter analyze→ no issues found
The core tests cover:
- initialization and default state
set()updatesupdate()derivationreset()restoration- listener notifications on state changes
Changelog #
See CHANGELOG.md for full release notes.
License #
Ionex is distributed under the MIT License. See LICENSE for the full text.
Contributing #
Contributions are welcome. A good contribution generally includes:
- updating or adding tests for any behavior change
- updating documentation when the public API changes
- keeping examples aligned with the current package API
- verifying changes with
flutter testandflutter analyze