@praxisjs/router
Changelog for @praxisjs/router — client-side routing with @Router, @Route, @Lazy, @Params, and @Location.
@praxisjs/router
2.1.0
Named routes — give routes a name and navigate by name instead of hardcoding paths.
name?: stringfield onRouteDefinitionand on the@Route({ path, name, meta })options objectpush({ name, params?, query?, hash? })andreplace({ name, ... })— navigate by name; params are interpolated into the path patternrouter.resolvePath({ name, params? })— convert a named target to a path string without navigatingNamedNavigationTargetandNavigationInputtypes exported from the package<Link to={{ name, params?, query?, hash? }}>—toprop now acceptsstring | NamedNavigationTarget
Route meta — attach arbitrary metadata to any route definition.
meta?: Record<string, unknown>field onRouteDefinition/@Routeoptionslocation().meta— current route meta object (defaults to{}when unset)location().name— current route name (string | undefined)router.meta— reactiveComputed<RouteMeta>shorthand forlocation().meta@Meta()— new field decorator; injectsrouter.metainto any component fielduseMeta()— composable returningrouter.metaRouteMetatype exported from the package
Navigation lifecycle hooks — post-navigation callbacks for analytics, focus management, and side effects.
afterEnter?: (to, from) => void— per-route hook inRouteDefinition; fires after the component is resolved, before globalafterEachhandlersrouter.afterEach(handler)— global hook; fires after every completed navigation (not called whenbeforeEnterblocks); returns an unregister function- Hook execution order:
beforeEnter → component resolved → afterEnter → afterEach → scrollBehavior
Scroll restoration — configurable scroll behavior per navigation.
scrollBehavior?: ScrollBehavioroption added toRouterOptions/createRouter/@Router- Receives
(to, from, savedPosition)—savedPositionis non-null on back/forward navigations - Return
{ top, left }to scroll to coordinates,{ el }to scroll an element into view, orfalseto skip scrolling; can return aPromise - Scroll position of the departing page is automatically saved into
history.statebefore eachpush(); restored viasavedPositionon popstate - Exported:
ScrollPosition,ScrollBehavior,SavedScrollPosition,RouterOptions
2.0.0
Breaking — route type aliases changed
RouteParams, RouteQuery, and RouteLocation are now signal/computed types. Field annotations no longer require importing Signal or Computed.
| Decorator | Before | After |
|---|---|---|
@Params() | Computed<RouteParams> | RouteParams |
@Query() | Computed<RouteQuery> | RouteQuery |
@Location() | Signal<RouteLocation> | RouteLocation |
@InjectLayout() | Signal<RouteComponent | null> | LayoutInstance |
If you typed beforeEnter guards explicitly with the old RouteLocation, remove the annotation (TypeScript infers from context) or use Parameters<RouteDefinition['beforeEnter']>[0].
1.2.0
Optional route segments — append ? to any named segment to make it optional.
{ path: '/posts/:slug?', component: PostPage }/posts/hello-world→params().slug === 'hello-world'/posts/→params().slug === ''(absent segment defaults to empty string)
1.1.0
Breaking — API renames
| Changed | Before | After |
|---|---|---|
| Root app decorator | @RouterConfig([...]) | @Router([...]) |
| Router field decorator | @InjectRouter() router!: Router | @Router() router!: RouterInstance |
| Router class (type annotation) | Router | RouterInstance |
| Class export | export { Router } | export { RouterInstance } |
Layout system — routes can now declare a persistent shell component that wraps the matched page without re-mounting on navigation.
layout?property onRouteDefinition— attach a layout to any route directly;RouterViewrenders<Layout>around the matched page- Layout inheritance via
children— when a route has child routes, itscomponentautomatically becomes the layout for all of them <RouterOutlet>— new component for use inside layouts (StatelessComponent); reactively renders the current page without needing thechildrenprop@InjectLayout()— field decorator injectingRouterInstance.currentLayoutas a reactive signal, following the same pattern as@Router(),@Params(), etc.RouterInstance.currentLayout— reactive signal exposing the currently active layout component- Lazy layouts —
layout: Lazy(() => import('./MyLayout'))works identically to lazy page components
@Router decorator (renamed from @RouterConfig) — now implemented with createClassDecorator and ClassBehavior, consistent with the rest of the decorator API. RouterBehavior.create() re-activates the correct router on each component instantiation, resolving singleton conflicts when multiple @Router-decorated classes share the same module scope (e.g. Storybook stories loaded together).
Navigation sequence — concurrent push() calls no longer race. A monotonic _navSeq counter ensures only the most recent navigation commits its result; stale in-flight resolutions are silently discarded.
1.0.13
Updated dependencies — @praxisjs/[email protected], @praxisjs/[email protected], @praxisjs/[email protected].
1.0.12
<Link> now accepts a style prop — both a CSS string (style="color:red") and a style object (style={styleObject}).
1.0.1
@Lazyinline fix —Lazy(() => import('./Page'))used directly in route definitions now renders correctly. The returned function was missing the__isLazymarker so the router treated it as a plain component@Routeco-location —@RouterConfignow accepts classes decorated with@Routedirectly. The path is read from__routePathautomatically — no{ path, component }wrapper needed- Lazy-loaded pages must use
export default class— the loader resolvesmodule.defaultat runtime
1.0.0
Breaking — full decorator-based API
All functional routing APIs removed:
| Removed | Replacement |
|---|---|
createRouter() | @RouterConfig on the root component |
lazy() | @Lazy decorator or Lazy() inline |
useRouter() | @Router() field decorator |
useParams() | @Params() field decorator |
useQuery() | @Query() field decorator |
useLocation() | @Location() field decorator |
0.2.4
Bug fix: beforeEnter guards that return a redirect string no longer recurse infinitely. Navigation aborts after 10 redirect hops with a console warning.
0.2.0
Migrated to TC39 decorator context API. Introduced StatefulComponent / StatelessComponent.
0.1.0
Initial beta release.