componentview

package
v0.0.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package componentview is the typed per-component complement to the generic leewaywidgets.Table2CardEmitter (ADR-0075). Where Table2CardEmitter renders any leeway table structurally, this renders *recognised* components with bespoke widgets: each registered RendererI is an ECS "system that draws", matched to entities that carry its component. A Dispatcher lays the detected components out as a collapsible single-record report — one foldable panel per component, the archetype made visible — and routes anything unrecognised to a generic fallback.

Detection and typed decode live in this package too, as Binder (see componentview_detect.go): Bind ties a component kind to the leeway DTO that reads it, and Binder.Components decodes a row into the components it carries by asking each bound kind in turn. That is ADR-0075's detect-then-render, finally built on ADR-0146's read contract.

Rendering does not depend on it — Dispatcher.RenderReport takes decoded Component values from anywhere, so a caller with its own decode path is unaffected. Earlier revisions of this doc claimed the package was free of leeway-codec dependencies; it no longer is, because the detection half had to live somewhere and the renderer↔component mapping is what this package owns.

Index

Constants

This section is empty.

Variables

View Source
var PackageProps = packageprops.Props{
	WASMWASI:         packageprops.WASMBlocked,
	WASMJS:           packageprops.WASMBlocked,
	WASMFreestanding: packageprops.WASMBlocked,
}

PackageProps records this package's curated properties (ADR-0080).

Blocked: rendering leeway components means reading them reflectively, and the reflective marshaller's closure reaches arrow-go — componentview → leeway/marshall/go/marshallreflect → arrow/array, which the survey classifies unsupported-external. The dependency is what the widget is for.

Declared amenable at the 2026-06-12 rollout, which was true then; the marshallreflect edge came later and nothing was checking.

Functions

This section is empty.

Types

type BatteryVal

type BatteryVal struct{ Charge uint64 }

IdentityVal, BatteryVal and TaskedVal are the decoded carriers the seed renderers expect. Tasked is tags-only for now — its time window (timeRange) is deferred together with the timeline widget (stage-2 defers timeRange).

type Binder added in v0.0.17

type Binder struct {

	// Lookup resolves ref-channel membership names to ids for every binding.
	// Nil means every membership is verbatim.
	Lookup marshallreflect.LookupI
	// contains filtered or unexported fields
}

Binder detects the components of a row. It holds the bindings and, alongside them, a component.Registry of their contracts — the catalogue answering which kinds are known and which slots they claim.

func NewBinder added in v0.0.17

func NewBinder() *Binder

NewBinder returns an empty Binder.

func (*Binder) Add added in v0.0.17

func (inst *Binder) Add(b Binding) (err error)

Add registers a binding. Two bindings claiming the same slot is NOT an error: components overlap when stages fuse facts they each know only part of, and no process holds the global component vocabulary to judge it. Use Registry().SlotClaims() to see what overlaps.

A repeated KIND is an error — the report renders one panel per kind, so two bindings for one kind would silently drop a reader.

func (*Binder) Bindings added in v0.0.17

func (inst *Binder) Bindings() []Binding

Bindings returns the bindings in registration order.

func (*Binder) Components added in v0.0.17

func (inst *Binder) Components(readers *marshallreflect.SectionReaders, i int) (out []Component, err error)

Components decodes row i into the components it carries, ready for Dispatcher.RenderReport. Absent components are omitted — the dispatcher's ShowAbsent draws them from the registry instead.

A component the row carries but does not CONFORM to (a slot holding more attributes than its DTO admits, which fusion can produce) is reported as an error rather than silently dropped: it is present, and rendering the report without it would misstate the archetype.

func (*Binder) Detect added in v0.0.17

func (inst *Binder) Detect(readers *marshallreflect.SectionReaders, i int) (out []KindPresence, err error)

Detect reports each bound component's presence on row i, in registration order, without decoding any value. Cheap enough to run per row over a heterogeneous table: it reads only the membership columns of the sections its bindings claim.

func (*Binder) Registry added in v0.0.17

func (inst *Binder) Registry() *component.Registry

Registry exposes the contracts of the bound components.

type Binding added in v0.0.17

type Binding struct {
	// contains filtered or unexported fields
}

Binding ties a component kind to the DTO that reads it. Build one with Bind.

func Bind added in v0.0.17

func Bind[T any](kind ComponentKindE, project func(T) any) (b Binding, err error)

Bind binds a component kind to the leeway DTO T that reads it, projecting the decoded DTO to the carrier the kind's renderer expects.

T is a COMPONENT DTO — it declares only the slots its component owns, not a row's worth of fields. That is what makes detection meaningful: a fat DTO spanning several components can only ever answer "is all of this here?".

func (Binding) Contract added in v0.0.17

func (inst Binding) Contract() mappingplan.ReadContract

Contract is the read contract of the binding's DTO: the (section, membership) slots it claims and the attribute arity each admits.

func (Binding) Kind added in v0.0.17

func (inst Binding) Kind() ComponentKindE

Kind reports which component the binding reads.

type Component

type Component struct {
	Kind  ComponentKindE
	Value any
}

Component is one decoded component on an entity: its kind plus the typed value the kind's renderer understands (type-asserted by that renderer). A nil Value renders as present-but-empty.

type ComponentKindE

type ComponentKindE string

ComponentKindE names a recognised leeway component — a section or section-bundle treated as one logical thing. The seed kinds are the ecsdemo drone components; fact-components register their own.

const (
	KindIdentity ComponentKindE = "identity"
	KindBattery  ComponentKindE = "battery"
	KindTasked   ComponentKindE = "tasked"
)

type Dispatcher

type Dispatcher struct {

	// ShowAbsent renders registered-but-absent components as dimmed lines.
	ShowAbsent bool
	// DefaultOpen sets the initial expanded state of each component panel.
	DefaultOpen bool
	// Fallback renders a present component that no renderer claims — a consumer
	// wires this to the generic Table2CardEmitter. Nil renders a short note.
	Fallback func(ids *c.WidgetIdStack, comp Component)
	// contains filtered or unexported fields
}

Dispatcher renders one entity's components as a collapsible single-record report: a foldable panel per registered component present on the entity, optionally a dimmed line per registered-but-absent component (so the archetype is legible at a glance), and a generic fallback panel for any present component no renderer claims.

func NewDispatcher

func NewDispatcher(reg *Registry) (inst *Dispatcher)

func (*Dispatcher) RenderReport

func (inst *Dispatcher) RenderReport(ids *c.WidgetIdStack, comps []Component)

RenderReport draws the report for one entity's decoded components. Collapse state is keyed by component kind, so it survives clicking through records.

type IdentityVal

type IdentityVal struct{ Status string }

IdentityVal, BatteryVal and TaskedVal are the decoded carriers the seed renderers expect. Tasked is tags-only for now — its time window (timeRange) is deferred together with the timeline widget (stage-2 defers timeRange).

type KindPresence added in v0.0.17

type KindPresence struct {
	Kind     ComponentKindE
	Presence mappingplan.PresenceE
}

KindPresence is one component's verdict for a row.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry holds the per-kind renderers in a stable registration order, which is also the report's rendering order.

func DefaultRegistry

func DefaultRegistry() (inst *Registry)

DefaultRegistry returns a Registry seeded with the light-version drone renderers in archetype order: identity, battery, tasked.

func NewRegistry

func NewRegistry() (inst *Registry)

func (*Registry) Register

func (inst *Registry) Register(rend RendererI)

Register adds (or replaces) the renderer for its kind. First registration of a kind fixes its slot in the rendering order.

type RendererI

type RendererI interface {
	Kind() ComponentKindE
	Title() string
	Render(ids *c.WidgetIdStack, value any)
}

RendererI draws one component kind from its decoded value. Implementations type-assert value to their own carrier.

type TaskedVal

type TaskedVal struct{ Tags []string }

IdentityVal, BatteryVal and TaskedVal are the decoded carriers the seed renderers expect. Tasked is tags-only for now — its time window (timeRange) is deferred together with the timeline widget (stage-2 defers timeRange).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL