Release v3.1.0
Added
- Translation from a compiled Screenplay application into
Cratis.Scene.Modelinstances - the seam between the Screenplay language and the object model Scene's engine and renderers consume (#37) EventModelLoader.LoadSceneApplicationFromDirectoryAsync, alongside the existingLoadFromDirectoryAsync, to load the translated model from a directory of.playfiles
Changed
- The translation follows Screenplay 4.0.0's taxonomy, which splits what used to share the word "layout": an application-level
layout(the navigational shell, one in force), a module-scopedscreen template(a reusable shape inside that shell, naming the slot it fits withfits slot), and adialog template(the same, for content that opens over the application). A screen names the template it fills; the shell is resolved once for the application, because a screen never names it.
Fixed
EventModelLoadermerging multiple.playfiles together now carriesui profile,themeandlayoutdeclarations through - previously only modules/concepts/policies survived a multi-file merge, so a real project split across files would lose them entirely- A screen's
navigate todirective is now translated instead of failing the conversion
Context
Screen/Layout/ScreenTemplate/DialogTemplate/Form/Contribution translate close to directly. The shape gaps that remain are documented inline rather than silently worked around:
ui profile'sthemeandlayoutreferences, a form'son submit navigate to, and a slot'scontributeshave no field on the corresponding Scene types yet - all called out as deliberate, documented gaps rather than silently dropped.- A screen with no
templatedirective (a Level 1 "intent" screen, where Studio generates the component) fills the layout'scontentslot directly and names no template - which is exactly whatScreen.ScreenTemplatedocumentsnullto mean. Nothing is synthesized for it. - A document that declares no
layoutat all gets one synthesized shell for the whole application, never one per screen.
Every screen directive (data, action, navigate, section, title, table, summary, code) converts to one ExternalComponent named core:<kind>, with its own fields folded into the open properties bag. This is deliberately mechanical rather than a bespoke SceneElement subtype per widget - the core:* components don't need to exist in Scene.React yet for the translated model to be correct; rendering them is a separate, later concern.