Releases: Cratis/Scene
Release list
Release v2.0.0
Summary
PrimeReact 11 ships 80 modules where 10.9.8 shipped 117, replaces monolithic components with compositional part namespaces, and ships no CSS at all. All four Scene JavaScript packages move together.
Important
PrimeReact 11 is not MIT. primereact, primeicons 8, @primereact/core, @primereact/headless, @primeuix/themes and @primeuix/styled are all under the commercial PrimeUI license, and a license key is required regardless of how you style — the check runs in PrimeReactProvider on mount with no condition on unstyled, on theme, or on NODE_ENV. Without a key, every page logs a warning and shows an "Invalid PrimeUI License" banner in development and production alike. See the migration page.
Changed
@cratis/scene.primereact,@cratis/scene.components,@cratis/scene.blueprint.defaultand@cratis/scene.blueprint.componentsnow requireprimereact ^11.0.0,primeicons ^8.0.0and@cratis/components ^3.0.0, and declare@primereact/coreand@primereact/headlesswhere they import them directly.- 13 abstract names follow a PrimeReact rename without changing their Scene name —
dropdownis nowSelect,calendarisDatePicker,overlayPanelisPopover,tabViewisTabs, and so on. multiSelectis re-expressed overSelect'smultiple;orderListandpickListover@primereact/headlesshooks, which ship the behavior but no presentation.- Theming is rebuilt on
@primeuix/themespresets. A theme is now an object handed toPrimeReactProviderrather than a stylesheet to load, so switching neither fetches nor flashes, and a theme name can no longer 404.usePrimeReactThemereturns the provider configuration instead of mutating the DOM. - The theme catalog is 24 themes across the Aura, Lara, Nora and Material families, replacing the 25 PrimeTek v10 themes. Their license is recorded as PrimeUI Commercial.
PrimeReactProvideris now mandatory anywhere Scene components render — PrimeReact 11 throws without it rather than falling back to a default configuration.
Added
- 14 abstract names whose PrimeReact component was removed in v11 are now backed by Cratis-owned implementations:
menubar,megaMenu,tieredMenu,panelMenu,tabMenu,steps,dock,splitButton,confirmDialog,column,treeSelect,blockUI,scrollTopandimage. MenuItemandTreeNodeare exported from@cratis/scene.primereact. PrimeReact 11 removedprimereact/menuitemandprimereact/treenode, and the authored{ label, icon, items }shape was always Scene's vocabulary.
Removed
cascadeSelect,inputMask,treeTableandvirtualScrollerare no longer declared. PrimeReact 11 removed all four with no equivalent and no headless hook. Usedropdownwith grouped options ortreeSelectinstead ofcascadeSelect,inputTextwith validation instead ofinputMask,treeordataTableinstead oftreeTable, anddataTable's own scrolling instead ofvirtualScroller.applyPrimeReactThemeandprimeReactThemeStylesheetare gone. They swapped and resolved a compiled theme stylesheet, and PrimeReact 11 has none —primeReactThemePresetresolves a theme name to a preset object instead.- 13 v10 themes have no v11 counterpart and are not carried over:
saga-blue,vela-blue,arya-blue,bootstrap4-light-blue,bootstrap4-dark-blue,soho-light,soho-dark,viva-light,viva-dark,nano,mira,fluent-lightandtailwind-light.
Deprecated
- Reduced capabilities forced by PrimeReact 11:
passwordlosesfeedbackandtoggleMask,colorPickerloses its overlay mode,ratinglosescancel,listBoxlosesfilter,multiSelectlosesdisplayandmaxSelectedLabels,carousellosesnumScroll,paginatorlosesrowsPerPageOptions,dataTablelosessize='normal', andcolumnno longer carrieseditor,frozen,footer,colSpanorexpander.
Caution
Sidebar is not Sidebar. PrimeReact 10's Sidebar is v11's Drawer, and v11 gives the name Sidebar to an unrelated new app-shell primitive. A name-preserving port compiles cleanly and silently swaps an overlay for a static shell. Both affected sites — the sidebar adapter and the default blueprint's config panel — are on primereact/drawer.
🤖 Generated with Claude Code
Release v1.1.0
Added
UiProfilegainedLayoutandTheme— the application shell a target renders inside, and the visual theme it applies. Screenplay'sui profilecould already state both (layout AppShell,theme Aurora), but the model had nowhere to hold them, so translation dropped them.
Both belong on the profile rather than on a screen: a screen that named its own shell or theme would stop being portable across targets, which is the reason profile selection exists at all.
🤖 Generated with Claude Code
Release v1.0.0
Added
- Packages. A
ui profilelists packages by name;ScenePackageis the declaration behind such a name — what it contributes (components, layouts, screen and dialog templates, themes) and what else has to be active for it to work. Kinds areComponentLibrary,StylingandBlueprint. - Dependency resolution.
PackageDependencyResolverexpands a chosen set of packages into the complete list, ordered so a package always follows what it depends on — which is also the correct override priority. Missing dependencies, version conflicts and cycles are reported rather than guessed at.PackageCataloganswers what a package picker asks: which component libraries are a base to build on, and what else fits what is already selected. - Screen and dialog templates.
ScreenTemplateis a reusable shape that goes inside a layout, at module, feature or slice level;FitsSlotnames the slot on its parent it fills, andScreenTemplateResolverturns those names into a tree. The same rule applies at every level, so nesting has no depth limit.DialogTemplateis the same for overlays, which fill no slot. - Themes carry attribution.
Themegained design tokens plusAuthor,AuthorUrlandLicense, so a theme adopted from elsewhere credits its original creator. @cratis/scene.primereact— 87 component names across PrimeReact's families, and 25 of PrimeTek's free themes, each credited.@cratis/scene.components— the Arc-bound Cratis Components composites, with a binding registry so a screen can name a query or command that a host resolves to a real class at render time.@cratis/scene.tailwind— the styling package component libraries declare themselves written against.@cratis/scene.blueprint.default— application shells with eight menu modes, 23 screen templates, 3 dialog templates and two themes.@cratis/scene.blueprint.components— whole Arc-bound pages built from Cratis Components, layered on the default blueprint rather than shipping a rival shell.
Changed
- A layout and a template are now different things. A
Layoutis an application's base navigational look and an application has one; aScreenTemplategoes inside it and an application has many. They were previously the same word for both. FlowContainercarries itsKind. C# distinguished aFlowRowfrom aFlowColumnby type, but the TypeScript mirror could not — interfaces with identical members are the same type — so a renderer had no way to tell a row from a column.
🤖 Generated with Claude Code
Release v0.7.0
Added
Layout.Arrangement: an optionalFlowArrangement/FreeformSlotArrangementdescribing how a layout's own named slots position relative to each other, filling a gap where Screenplay'stemplate/row/column/grid/variantconstructs (which arrange slots) had nowhere to go in the object model - only a single slot's own filled content could be arranged before thisFlowSlotLeaf/SlotPlacement: the slot-referencing counterparts toFlowLeaf/ElementPlacement, used only within aLayout's own arrangement treeFreeformSlotArrangementEvaluator(+ TypeScriptevaluateFreeformSlotArrangement): selects aLayout's macro placement variant for a size class, mirroringFreeformArrangementEvaluator
Context
Found while implementing Cratis/Stage#37 (the Screenplay → Scene translation seam) - Screenplay's layout construct places named slots via template/variant blocks, but Layout had no field to receive that structure, only Slot.Arrangement for a slot's own content. Fully additive: no existing type's shape changed, and FlowArrangementEvaluator is reused unmodified since it never inspects leaf content.
Release v0.6.0
Added
UiStartermodel type: a packaged, versioned UI starting point bundling a package list, compatible themes, and a gallery of sample screen names (#6)StarterProfileBuilder/buildStarterProfile: builds the sandboxedUiProfilea starter's gallery boots through, scoped to exactly its own package list (#6)StarterThemeValidation/incompatibleStarterThemes: finds which of a starter's declared themes are incompatible with its own packages, reusing the theme compatibility engine (#6)
Release v0.5.0
Added
ThemeCompatibility.IncompatiblePackages()/incompatiblePackages()andIsCompatible()/isThemeCompatible()- reuse the exact rule Screenplay's compiler already applies (ValidateThemes): every package aui profiledeclares must be in the theme'scompatibleWithlist, with no implicit exemption forcore. Sharing this rule here means Stage's build-time warning and Studio's design-time theme-picker filtering don't each reimplement it. (#5)ThemeCompatibility.ApplicablePackages()/applicableThemePackages()- the renderer-facing half: the packages a profile activates that a theme also declares compatible, whichScene.Reactscopes token application to (rather than applying a theme's tokens globally). Computing it fresh from the current theme/profile pair, rather than caching a resolved result, is what makes theme switching a live re-resolution with no reload. (#5)- A shared JSON fixture corpus (
theme-compatibility-fixtures.json) asserted independently by both the C# and TypeScript specs, following the pattern established in #3/#4.
Notes
The theme token model's own shape (colors, spacing, typography) is explicitly out of scope for this issue, confirmed by its own text - this PR only builds the compatibility check and the package-scoping helper a future token-application layer in Scene.React will consume; it does not attempt to design or apply actual tokens.
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.
Release v0.3.0
Added
SizeClassCalculator.Compute()(C#) /computeSizeClass()(TypeScript) - computes the current width x height size class from actual available dimensions, shared by every renderer so they all agree on when a class boundary is crossed. (#4)FlowArrangementEvaluator.Evaluate()/evaluateFlowArrangement()- selects the most specific matchingwhen width/height <class>override's tree for the current size class (both dimensions targeted beats one; the last declared wins among equally specific matches), falling back to the base tree when nothing matches. (#4)FreeformArrangementEvaluator.Evaluate()/evaluateFreeformArrangement()- selects the placement variant with an exact size-class match, or nothing - deliberately no fallback, matching the language's own "warn, don't silently pick" design for a size class with no matching variant. (#4)FlowArrangementgained anOverrideslist (C#) /overrides(TypeScript) - the model previously had no field at all for Screenplay'swhen width/height <class>override construct, unlikeFreeformArrangementwhich was already keyed by size class.- A shared JSON fixture corpus (
layout-evaluation-fixtures.json) asserted independently by both the C# and TypeScript specs, following the same pattern established for the package resolver in #3/#9.
Notes
Per Scene#8's original design (confirmed against its merged PR description), Slot.Arrangement is per-slot, not per-layout - this evaluation engine works against that shape as-is and does not assume every slot in a layout shares one arrangement mode.
Release v0.2.0
Added
PackageResolver.Resolve()(C#,Cratis.Scene.Engine) andresolveComponentName()(TypeScript,@cratis/scene.engine) - resolve a bare or package-qualified component name against aui profile's package list. A bare name walks the package list from highest to lowest priority (corealways the lowest-priority fallback); a package-qualified name (e.g.Internal.Widgets.TrendChart) resolves directly against its named package, bypassing priority order entirely. (#3)- Every resolution also reports which other active packages declared the same bare name but were shadowed by the winner, directly answering the issue's own open question ("why did my button render as PrimeReact's and not core's") without needing separate CLI tooling. (#3)
- A shared JSON fixture corpus (
package-resolution-fixtures.json) asserted independently by both the C# and TypeScript specs, so the two implementations of the algorithm cannot drift apart - the same patternscene-model-shape.jsonalready establishes forScene.Model's shape. - New
Cratis.Scene.EngineC# project, sibling toScene.Model, mirroring the existing TypeScriptmodel/enginepackage split - keepsScene.Model's strict shape-parity manifest free of behavioral types.
Notes
Wiring this resolver into SceneElementView/ComponentRegistry's actual rendering path (resolving an entire element tree's component names before it renders) is left to Stage#39 and StudioIssues#160, which this issue explicitly lists as downstream consumers - not attempted here.
Release v0.1.0
Added
Cratis.Scene.Model(C#) — the platform-agnostic Screen object model: theSceneElement → VisualElement → FrameworkElement → Control → Panel/ItemsControl/ContentControl/ExternalComponentelement hierarchy,Layout(flow and freeform arrangement per slot, width × height size classes),Form(the three population/mapping tiers), contribution points and navigation, andUiProfile/Theme. No React, DOM or CSS vocabulary anywhere in this project.@cratis/scene.model— the TypeScript mirror, hand-maintained and guarded by a real cross-language parity spec: a sharedscene-model-shape.jsonmanifest that both a C# spec (reflection over the assembly) and a TypeScript spec (walking each type's ownPropertyNamesconst) assert against independently, so a desync on either side fails its own build.@cratis/scene.engine— theRenderer<TOutput>contract a renderer implements (one method per concrete element kind), and arenderElement()tree walk. Binding resolution is injected via aBindingResolvercallback rather than solved here — the profile/contribution/layout/theme resolution engines are separate, later issues.@cratis/scene.react— implements the renderer contract against real React/DOM, with a smallcorecomponent set (core:text/button/card) and Storybook wired at the package level.- Repository scaffold:
.ai/instruction corpus and its Copilot/Claude/Codex adapters, build/lint/format config, and CI workflows (dotnet + JS build, NuGet + npm trusted publishing, semver label gate) — copied fromCratis/Arc, the closest real dual-stack framework repo.
Notes
- The design-time editor building on this object model belongs in Studio (
StudioIssues#156), not here. - Verified end to end:
dotnet build/dotnet testclean (Debug + Release, 0 warnings),yarn ciclean across all three JS packages,yarn build-storybooksucceeds, and the parity spec genuinely fails on both sides when deliberately desynced (verified, then reverted).
(#1)