PURPOSE
Controlled React editor for the AnchorMap of a weapon-workbench component. Lets the designer add, rename via kind change, parameterize, and delete named attachment points (pivot / edge / radial) that other components or weapons snap to when building composite effects.
OWNS
- Local UI draft state:
draftName,draftKind,error. - Validation gate
canAddderived fromdraftNamelength,isValidAnchorName, and uniqueness against currentanchors. - Per-row controls: kind
select, optional radiusinput(radial only), deletebutton(disabled forcenter). - Inline error display fed by thrown errors from the anchor mutators.
READS FROM
- Props
anchors: AnchorMapandonChange: (next: AnchorMap) => void. @engine/vfx-workbench/anchor-typesforaddAnchor,removeAnchor,updateAnchor,isValidAnchorName, and typesAnchorMap,AnchorSpec,AnchorKind.
PUSHES TO
- Parent via
onChange(next)with the result ofaddAnchor,removeAnchor, orupdateAnchor. The component is fully controlled; it never mutates state in place.
DOES NOT
- Persist anchors. Persistence is the parent’s responsibility.
- Resolve anchor positions in world space — purely a metadata editor.
- Render a preview of the anchor on the component.
- Allow deletion of the reserved
centeranchor. - Allow renaming an existing anchor (only kind/radius edits and add/delete).
- Validate radius bounds beyond
parseFloatof the input value.
Signals
onChange(next: AnchorMap)after every successful add / delete / kind change / radius change.- Errors thrown by mutator functions are caught and surfaced via the local
errorstring (red text under the editor).
Entry points
- Default kind defaults applied on add:
edgegetsdirection: 'forward';radialgetsradius: 16. data-testidhooks:anchor-kind-<name>,anchor-radius-<name>,delete-anchor-<name>,new-anchor-name,new-anchor-kind,add-anchor.- Imported by parent screens in
src/starship-survivors/screens/weapon-workbench/that own a component’sAnchorMap.
Pattern notes
- Pure controlled component — single
onChangeupward, no internal copy ofanchors. - All mutations go through the engine helpers (
addAnchor/removeAnchor/updateAnchor) so invariants (name validity,centerprotection, uniqueness) live in one place and throw on violation. - Error handling catches thrown
Errorobjects and falls back toString(e)so the UI never blanks on a non-Error throw. - Add button is gated by
canAddto prevent invalid submissions; kind dropdown drives spec shape (radius input appears only forradial). - Inline styles only; no external CSS dependency. Fonts:
Cal Sansfor the header label,Space Groteskfor help copy, monospace for anchor names.