casl_flutter 1.0.0
casl_flutter: ^1.0.0 copied to clipboard
Flutter bindings for casl: an ability in the widget tree, a Can widget, and context.can(...) — so a screen draws what a user may actually do.
Changelog #
1.0.0 · 2026-08-14 #
There are breaking changes — see
casl's migration guide, which covers both
packages. The one that touches real call sites here is CanResult.reason.
Added #
-
Typed widgets.
Can<A>andCanBuilder<A>are generic over the action type, so pinning it with a typedef makes a typo stop compiling:typedef AppCan = Can<AppAction>; AppCan(AppAction.delete, article, child: const DeleteButton()); AppCan('reed', article, child: const DeleteButton()); // no longer compilesNothing changes at runtime. An
AppActionis aString, so oneAbilityProviderserves typed and untyped screens side by side, and the rules travel over the wire unchanged. -
AbilityNotifier, the ability as aChangeNotifier. Provider, Riverpod, Bloc andListenableBuilderall speakListenable; none of them speakability.on('updated', …). It listens without owning: disposing it stops it listening and leaves the ability alone. -
CanResult.message, the resolved text — see below.
Fixed #
- A rules change during a build no longer throws.
AbilityProvidercalledsetStatestraight from the ability's event, so a screen that fetched on its first frame, a locator that initialised lazily or a router redirect would raise setState() or markNeedsBuild() called during build. It now checks the scheduler phase and republishes at the end of the frame when the framework is mid-build. React'suseSyncExternalStoreis safe by construction; aStatefulWidgethas to ask. - A provider may now be disposed while the ability is emitting — the Flutter
face of the
ConcurrentModificationErrorfixed incasl. An update that tears the provider out of the tree disposes it, and disposal unsubscribes, from inside the event.
Changed #
CanResult.reasonis now the forbidding rule's own words, or null. It used to resolve throughForbiddenError.message, so it was never null when disallowed — andTooltip(message: can.reason ?? ''), straight out of this README, always renderedCannot execute "delete" on "Article".reasonnow means what@casl/reactmeans by it;CanResult.messageis the resolved text for callers that want a fallback.
Not changed, on purpose #
CanBuilderstill has nonot. It would invertallowedand leavereasondescribing a refusal the builder had just been told did not happen.!can.allowedsays the same thing and cannot be misread.
0.1.0 #
- Initial release:
AbilityProvider,Can,CanBuilder, and theBuildContextextensions.