Add component packages, blueprints and the layout/template distinction - #16
Merged
Conversation
A `ui profile` lists packages by name; nothing until now said what a name means or what else has to be active for it to work. `ScenePackage` is that declaration - kind, version, dependencies, and what the package contributes (components, layouts, themes). `PackageDependencyResolver` expands a chosen set into the complete, topologically ordered list a profile needs, so a package always outranks what it depends on. Missing dependencies, version conflicts and cycles are reported rather than silently resolved. `PackageCatalog` answers the questions a picker asks: which component libraries are a base to build on, and what else fits what is already chosen. `Theme` gains design tokens plus author, link and license, so a theme adopted from elsewhere credits its original creator rather than appearing to be ours. Both languages assert the same `package-dependency-fixtures.json` corpus, the pattern already used for model shape, package resolution, layout evaluation and theme compatibility. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A layout and a template were the same word for two different things. They are now separate, and the difference is the point: A `Layout` is an application's base navigational look - the shell. An application has one, and selects it. A `ScreenTemplate` is a reusable shape that goes inside that shell, at module, feature or slice level, and an application has many. A `DialogTemplate` is the same for content that opens over the application rather than sitting inside it. `ScreenTemplate.FitsSlot` is what makes them compose. A template states the name of the slot it fills, never which container owns it - so a feature's template says "I go in the module content area" rather than naming one module, and stays reusable. `ScreenTemplateResolver` turns those names into a tree by finding which layout or template declares each. The same rule applies at every level, so nesting has no depth limit and no second mechanism. What it cannot resolve, it reports: a slot nothing declares, a slot name two containers declare, and templates that nest inside themselves. Guessing a parent renders content in the wrong region, which is far harder to diagnose than being told the name is ambiguous. `PackageKind.Layout` becomes `Blueprint` - the package that ships a coherent set of layouts, templates and the components filling them, and which an application selects one of. `ScenePackage` gains `ScreenTemplates` and `DialogTemplates` beside `Layouts`, and `validatePackageBundle` checks all three. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two component libraries a `ui profile` can now resolve against, and the Tailwind styling package both declare a dependency on. PrimeReact contributes 87 component names across its families, mapped onto the real components, plus 25 of PrimeTek's free themes. Cratis Components contributes 37 more - the Arc-bound data, form and dialog composites - and declares PrimeReact and Tailwind as dependencies, which is the case the whole dependency mechanism exists for. Both deliberately reuse names the packages beneath them already declare - `button`, `card`, `table`, `dialog` - because that is what override priority is for: a profile listing core, PrimeReact and Cratis Components resolves `table` to the last one and reports the others as shadowed. Themes carry their attribution. Every one of PrimeReact's is PrimeTek's work under MIT, and says so through `author`, `authorUrl` and `license` rather than appearing to be ours. A Scene element carries plain values, so it cannot carry the query or command class an Arc-bound component needs. Cratis Components resolves that with a binding registry: a host registers real generated proxies under the names a screen refers to, and an unregistered name renders a placeholder naming what is missing rather than throwing - which is the state a design-time preview is usually in. The root tsconfig now references every package, so a workspace typecheck actually covers them; it did not before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lumns The default blueprint ships what an application needs to look like a product on day one: two layouts (an application shell and a full-page shell for sign-in and error screens), 16 shell components implementing all eight PrimeTek menu modes, 23 screen templates and 3 dialog templates with seeded content, and a light and a dark theme. The three-level chain is real, not illustrative: `ModuleWorkspace` fits the shell's content slot, `FeatureSection` fits a slot the module template declares, and `SliceSection` fits one the feature's declares - each proven by a spec through the real resolver. `FlowContainer` gains a `Kind`. C# tells a `FlowRow` from a `FlowColumn` by type, but the TypeScript mirror cannot: interfaces with identical members are the same type, and there are no runtime types to test. A renderer walking an arrangement tree had no way to tell a row from a column - the one thing it most needs to know - so the two stacks could not agree on what a layout meant. The kind carries that decision as data, and `flowNodeKind` exposes the guards for it, matching how `elementKind` already distinguishes element kinds. The Tailwind package gains the bundle spec every package owes; without one its test run failed outright rather than passing vacuously. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Eleven Arc-bound screen templates and three dialog templates built from Cratis Components composites, so a data list, a master-detail screen or a command form is a template an application picks rather than a page it assembles. It is the first blueprint layered on another. It declares no layouts and depends on `Cratis.Blueprint.Default` for the application shell instead of shipping a rival one - which is what the dependency is for, and what keeps an application from ending up with a sidebar from one design language and a form from another. Templates carry query and command *names*, not classes. The binding registry turns a name into a class at render time, and a name nothing registered renders as a placeholder saying so - which is the state a design-time preview is normally in, and should look incomplete rather than quietly wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`body` is a good name for a slot at every level of a nesting chain, so several templates legitimately declare one - and a bare `body` then has no single answer. Both blueprints hit this: the components blueprint had to pick `content`/`body`/`primary` to keep every fitted name unique, and the default blueprint's own three-level chain does not resolve once both are in scope together. A `FitsSlot` may now name its container - `ModuleWorkspace.body` - and resolve straight to it. The same rule component names already use: a bare name searches, a qualified one goes to what it names. A qualifier naming a container that does not declare that slot stays unplaced rather than quietly falling back to a search. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`**/packages/*` is NuGet's Package Restore rule, and it matched `Source/JavaScript/model/packages/` and `react/packages/` - so the package model, `ScenePackage`, `ScenePackageBundle` and `validatePackageBundle` were never committed at all. Nothing caught it locally: the files are on disk, so every build, spec and typecheck was green. CI clones fresh, found no `./packages` module, and failed on the first workspace it reached. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Added
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.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.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.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
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