raku_router 0.3.0
raku_router: ^0.3.0 copied to clipboard
A tiny, code-generation-free, UI-agnostic router for Flutter: type-safe sealed routes, declarative deep linking, and built-in nested tabs with per-branch back stacks.
0.3.0 #
Hardening and the API freeze review on the way to 1.0. Contains breaking
changes — see Breaking below for the migration notes.
Fixes
- A malformed deep link no longer crashes the app. A
parsethat throws on bad input (p.asInt('id')on/notes/abc,Enum.values.byName) or a URL with invalid percent-encoding is now a non-match: the URL falls through to a catch-all route oronUnknown. URLs are untrusted input. - A redirect now protects its whole subtree. A deep link (or
go) checks the redirect of every route on the rebuilt path, not just the leaf's — so a sign-in redirect on/adminalso covers/admin/users/1. - Browser back/forward honours
RouteGuard. On the web, a URL change that would remove a guarded page is vetoed (onPopBlockedruns, the address bar is put back); previously it slipped through. - System back closes an open dialog / bottom sheet first. It used to pop the
page underneath along with it. Works for overlays on the root navigator, on a
tab's navigator, and with a plain
RouteStackView. onPopBlockednow gets acontextinside the guarded page's own stack, so a confirmingcontext.pop()pops the right page inside a tab.- A slow async redirect can no longer overwrite a newer navigation.
- Declaring the same route type in two
route(...)s now asserts (it used to be silently overwritten).
New
RakuRouter.go/push/current/routeOf— navigate without aBuildContext(push notifications, auth listeners):gorebuilds the location like a deep link,pushlands at the right level,currentis aValueListenable<RakuRoute>of the active leaf,routeOfmaps a URL to a typed route (ornull) and never throws.context.go(route)— the in-widget form ofgo.raku(title:)— fallback tab title for routes without atitle:, so the label no longer goes stale when leaving a titled route.- URL matching rules are now defined and tested: case-sensitive, trailing and
doubled slashes ignored,
#fragmentignored, last value wins for a repeated query key.
Breaking
- One default transition everywhere:
RouteStackView,BranchedStackViewandRakuPagenow default toRakuTransitions.slideIn(wasfade), likeraku(...). TheirtransitionsBuilderis nullable (null = the default). PasstransitionsBuilder: RakuTransitions.fadefor the old look. - Smaller public surface. No longer exported:
RouteTree,RouteMatch,ScreenMatch,TabsMatch,RakuNavigator;RouteStack.reconcileRoutes,handlePageRemovedandresolveare internal.ScreenNode/TabsNodecan only be built withroute(...)/tabs(...). RakuRoute.sameDestinationis removed — use==.RakuRouter,RouteParams,RoutePath,RakuEntry,RouteBranch,ScreenNodeandTabsNodeare nowfinalclasses.
0.2.0 #
Additive features on the way to a stable 1.0 — no breaking changes.
- Navigator observers —
raku(observers: …)attachesNavigatorObservers (FirebaseAnalyticsObserver,SentryNavigatorObserver,RouteObserver, …) to the root and every tab-branch navigator. It's a factory (() => [...]): one observer instance can attach to only oneNavigator, so each navigator gets fresh instances — and an observer therefore sees in-tab pushes too. - Catch-all routes (typed 404) — a trailing
*in aroute(...)path matches any URL a concrete route doesn't. Nest it for a subtree-scoped not-found (shown inside the tab), or put it at the top level for a global one; most-specific wins, concrete always beats wildcard, else it falls through toonUnknown. The unmatched tail arrives typed viaRouteParams.rest, and the route round-trips so the 404 URL is preserved. - Route → URL —
raku(...)now returns aRakuRouterexposinghrefOf(route)/uriOf(route), the tree's reverse direction, for share links, deep links, and<a href>s. - Browser tab titles —
route(..., title: (route) => '…')sets the tab / task-switcher label of the active leaf. Opt-in; the platform is untouched when no route declares a title. context.replaceSilently(route)— updates the address bar in place (no new history entry), wrappingRouter.neglect. For transient, shareable URL state like a search query or filter.
0.1.0 #
First public release — a tiny, code-generation-free, UI-agnostic router for Flutter.
Highlights:
- Type-safe routes, no codegen — routes are plain
sealedclasses; an exhaustiveswitchis your route table. - Declarative deep linking —
raku(routes: […])maps a URL's structure to a typed navigation stack, both ways, with no hand-written parsing. - Nested tabs built in — each branch keeps its own persistent back stack and tabs nest arbitrarily.
- Guards & redirects —
RouteGuard(predictive-back aware) and loop-protectedRouteRedirect. - Built-in transitions —
slideIn,none,fade,slide,riseUp, all Material/Cupertino-free. - No dependencies beyond
flutter— no state-management or design-system coupling. Supports all 6 platforms; WASM-ready. SDK floor: Dart 3.6 / Flutter 3.27.