drip 0.1.0
drip: ^0.1.0 copied to clipboard
Minimalist Cubit-style state management for Flutter using Streams and InheritedWidget.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.1.0 - 2026-05-11 #
Changed #
- API simplified to a Cubit-style surface.
Drip<S>now exposes onlystate,stateStream,leak(newState), andclose(). No more event dispatch or interceptor pipeline. Dropper<D>is the newInheritedWidgetprovider.DripProvider<D>is kept as a convenience wrapper overMultiProviderwith a single child.- Tightened
analysis_options.yamlwith stricter lints (avoid_print,require_trailing_commas,prefer_const_constructors,use_super_parameters,cancel_subscriptions,close_sinks, etc.) andstrict-casts.
Added #
MultiProvider, backed bypackage:nested, for composing multiple drips without nested indentation.Dropper.of<D>/Dropper.read<D>/Dropper.watch<D>andBuildContext.read<D>()/BuildContext.watch<D>()extension.DropWidget<D, S, T>— selector widget that rebuilds only whenselector(state)returns a new value. SupportsList,Map, and primitive equality out of the box.Dripping<D, S>— listener-only widget that does not rebuild its child on state changes.DripObserver— global hook withonCreate/onChange(previous, next)/onClosecallbacks. Default is a no-op; install viaDrip.observer = MyObserver()to plug in logging, analytics, or undo history.ComputedDrip<S>— a [Drip] whose value is derived from other drips. Automatically re-evaluates when any source emits; only re-emits on!=. Sources can themselves beComputedDrips, so composition is transitive. Closes its source subscriptions onclose(). Fills the same niche as Riverpod's derived providers, with a single class and zero magic.AsyncDrip<T>and the sealedAsyncState<T>(AsyncIdle/AsyncLoading/AsyncData/AsyncError) for async data.AsyncDrip.run(() => future)emitsLoading -> Data | Errorautomatically;AsyncLoading.previouskeeps the last successful value for stale-while-revalidate UIs. Designed for Dart 3 exhaustive pattern matching withswitch.topics,repository, and richerdescriptioninpubspec.yamlto improve pub.dev discoverability.- GitHub Actions CI: format check, analyze, tests with coverage, and
pub publish --dry-run. Matrix on Flutterstable+beta.
Removed #
DripEvent,DripActionand thedispatchmethod (no event pipeline anymore).BaseInterceptor,MemoryInterceptor,ActionExecutorand theinterceptorsparameter onDrip's constructor.DefaultDripLoggerMixinand theloggerdependency.DripListenerwidget (useDrippinginstead).GenericStateChangeAction(no longer needed withoutdispatch).
Migration from 0.0.1 #
If you were using the previous (event/interceptor) API, the simplest upgrade path is:
// Before — 0.0.1
class CountAdded extends DripEvent<int> {}
class CounterDrip extends Drip<int> {
CounterDrip() : super(0);
@override
Stream<int> mutableStateOf(DripEvent event, int state) async* {
if (event is CountAdded) yield state + 1;
}
}
// dispatch
CounterDrip().dispatch(CountAdded());
// After — 0.1.0
class CounterDrip extends Drip<int> {
CounterDrip() : super(0);
void increment() => leak(state + 1);
}
// call
CounterDrip().increment();
Interceptors no longer exist as a first-class concept. If you need cross-cutting behavior (logging, undo history, analytics), wrap calls inside your Drip subclass or compose state holders.