Release v0.4.0
Added
aggregateContributions()(@cratis/scene.engine) - collects every contribution targeting a given contribution point, ordered ascending by its explicitorder(unordered contributions sort after every ordered one, in their original relative order). Resolving which contribution point acontribute totargets already happens before aContributionexists inScene.Model(see its own doc comment), so there was no ambiguity left for the engine to resolve here, only ordering - this is narrower than the issue's original proposal, which assumed the engine would still walk a nearest-enclosing resolution; that already happened upstream. (#2)NavBarwidget (@cratis/scene.react) - renders the aggregatedNavigationcontributions. Hownavigate to <Screen>becomes a concrete route is a caller-suppliedrenderRoutecallback rather than a fixed URL scheme, so the same widget works unmodified across renderers, per the issue's own "configurable per renderer" requirement. (#2)extractNavigationItem()- reads aNavigationItemout of aNavigationcontribution'sExternalComponent.propertiesbag.
Notes
extractNavigationItem's property-bag key contract (label, targetScreen, routeParameterBindings, order, group - the same names as NavigationItem's own fields) is a Scene#2 design choice made without a real Screenplay-to-Scene translation to confirm it against - Stage#37 (the Screenplay → Scene seam) hasn't been built yet. Documented as an assumption in the function's own doc comment; Stage#37 should either match this contract or this function should move to match whatever it actually emits.