id - always a fresh idSeed() value. Mirrors the tabs
instrumentation handle: a label-keyed id would collide when
two steps share a label.
kind - fixed at 'step'. The instrumentation path does not
project nested <mat-step> groups (Material's stepper has no
group-of-steps concept; group-aware semantics belong to the
<cngx-stepper> thin-wrapper organism).
label - snapshot signal resolved through a four-tier fallback at
registration time so cngx-side phrases (announcements,
aria-label composition, telemetry) never read empty when
Material consumers project a <ng-template matStepLabel>:
MatStep.label when it is a plain string - the canonical
shape and the only one that emits a runtime change Material
itself observes.
MatStep.ariaLabel when the consumer set the input -
designed exactly as the substitute for template labels.
Static-text read from MatStep.stepLabel.template via a
throwaway detached EmbeddedViewRef (readMatStepLabelTemplateText).
Captures literal matStepLabel markup; dynamic interpolation
bails through to (4).
Step <id> - deterministic, derived from the cngx handle
id. Always non-empty.
Documented limitation: runtime label changes do not propagate.
CDK's CdkStep does not expose a _stateChanges Subject
analogous to MatTab._stateChanges, so cngx cannot re-trigger
the snapshot when Material flips the input later. Surface the
same Material-internal coupling family typed in
MaterialPrivateSurfaces.CompletedOverrideSource.
disabled - fixed false. Material owns step gating via
linear + editable + completed; surfacing a cngx-side
disabled would duplicate Material's own click-time enforcement
and is ignored by <mat-stepper> itself.
state - computed() over MatStep.hasError / MatStep.completed.
CdkStep.completed's getter reads _completedOverride() - a
WritableSignal<boolean | null> typed in
MaterialPrivateSurfaces.CompletedOverrideSource. The cngx
computed transitively tracks that signal through the getter and
re-fires whenever Material flips completion. hasError is a
plain property setter on CdkStep, NOT a Signal - a hasError
write that is not paired with a completed change does not
re-trigger this computed. In practice Material wizards write the
two together (step.hasError = true; step.completed = false in
error-handler patterns and inside Material's own error-state
matchers) so the limitation is benign for the documented usage
pattern.