DeclaredView
A VIEW a section declares: a tree of Milpa components, the definitions and renderers it needs, and the signals the page must seed for it — the plugin declares, the host reconciles (greenhouse decisions/0211). The narrow shape an {@see AdminSection} already had — one `component` plus its `definition` and `renderer` — is this same thing said for one node. A view says it for a TREE: several components, in the order the plugin wants them, each with its own props, each painted by the renderer the plugin brings. Nothing else changes: the host still registers the names ({@see \Milpa\Admin\Components\ComponentBook}), still refuses the ones it registers itself, still paints the section header above the tree, and still emits ONE runtime for the whole page — every declaring renderer's `.css` and `.js` ({@see \Milpa\Live\Contracts\Rendering\DeclaresClientAssets}) reach `LiveBoot::html()` merged and deduplicated, so a module the guest shares with the host is loaded once. ```php new AdminSection( id: 'agent', title: 'Agent', order: 60, group: AdminSection::GROUP_AGENT, view: new DeclaredView( markup: '<milpa:desktop-tabs id="agent-tabs"/><milpa:desktop-conversation id="agent-conversation"/>', definitions: ['desktop-tabs' => $tabs, 'desktop-conversation' => $conversation], renderers: ['desktop-tabs' => $renderer, 'desktop-conversation' => $renderer], props: ['desktop-conversation' => ['session' => $id]], signals: ['desktop.theme' => 'dark'], ), ); ``` **The markup.** Every ROOT of the tree is a Milpa element (`<milpa:name/>` or `<milpa-name/>`); ordinary HTML is allowed INSIDE a component's node, as the compiler has always allowed it. Each root is compiled on its own, so one that throws paints its failure inside its own region and the rest of the view — and the whole panel around it — still stands (greenhouse decisions/0211, «contained errors»). **The names.** `definitions` and `renderers` are keyed by component name and must name exactly the same set: a definition with no renderer cannot be painted, and a renderer for a name nobody defines is a registration that would never resolve. A view may still NAME, in its markup, a component the panel registers itself (`metric-card`, `dashboard-panel`…) without declaring it — naming is free, redefining is refused. **The seeds.** `signals`, `persist` and `computed` are what this view needs in the page's three seed tags. The host merges them with its own and emits each tag ONCE ({@see \Milpa\Admin\View\LiveSeeds}); a key two declarers give DIFFERENT values is a conflict that names both, never a silent last-one-wins.
DeclaredView::__construct()
public function __construct(string $markup, array $definitions = [], array $renderers = [], array $props = [], array $signals = [], array $persist = [], array $computed = [], ?Milpa\Live\ValueObjects\ClientAssets $assets = null, ?Closure $signalsFromContext = null):Parameters
| Name | Type | Description |
|---|---|---|
| $markup | string | the component tree to compile — one or more `<milpa:…>` roots |
| $definitions | array<string, ComponentDefinitionInterface> | component name → the definition the plugin brings |
| $renderers | array<string, ComponentRendererInterface> | component name → the renderer that paints it; the same keys as `$definitions` |
| $props | array<string, array<string, mixed>> | component name → props merged UNDER the markup's own attributes |
| $signals | array<string, mixed> | signal name → seed value for `#milpa-live-signals` |
| $persist | list<string> | signal names the runtime must persist (`#milpa-live-persist`) |
| $computed | array<string, mixed> | signal name → derivation for `#milpa-live-computed` |
| $assets | ?Milpa\Live\ValueObjects\ClientAssets | |
| $signalsFromContext | (\Closure(ComponentContext): array<string, mixed> | null) | additional seeds resolved with the active view's authenticated render context |
Throws
\InvalidArgumentException when the markup is empty, or the definitions and renderers do not
name the same components, or a name or a persisted signal is blank
DeclaredView::names()
public function names(): arrayThe component names this view brings — what the host registers under the section's own layer.
DeclaredView::seedsNothing()
public function seedsNothing(): boolTrue when the view seeds nothing — the page's three tags carry only the host's own.
DeclaredView::resolveSignals()
public function resolveSignals(Milpa\Live\ValueObjects\ComponentContext $context): arrayResolve identity-dependent values at render time, never while discovering the catalogue. Static declarations and contextual values keep the same name/conflict rules as the host. The host calls this only for the active view (greenhouse 0396/0714).
Parameters
| Name | Type | Description |
|---|---|---|
| $context | Milpa\Live\ValueObjects\ComponentContext |
Throws
\InvalidArgumentException for an invalid signal name
SeedConflictException for conflicting static and contextual declarations