Source: pre-release audit (planning session). PR theme: adapter surface. Changesets: minor (gcode-preview-core + 4 adapters; gcode-renderer-three for keyboard keys). Consider splitting into two PRs (M3+M6 API / M4 a11y) if the diff gets large.
Three related additions to the adapter public surface, all threaded through gcode-preview-core into all 4 adapters at parity.
M3 — Surface capabilities + warnings in the adapter event surface
The library's differentiator is capability-honesty, but adapter consumers only get onReady({ segments, layers, complete }). capabilities + warnings live in state.summary (controller.ts:106-113) yet appear in no event/callback — so a consumer can't gate their own color-mode UI the way tools/demo does (which reads the raw handle / ir.header.capabilities). Add capabilities + warnings to the ready payload (or a dedicated capability event).
M6 — Declarative view / cameraState prop
setView/getCameraState/setCameraState (#268) are reachable only via the imperative handle, while every other capability (colorMode, cameraMode, theme, scrub, scrubTime…) is a first-class prop. Add a view prop + a cameraState two-way binding across all 4 adapters, matching the established pattern.
M4 — Keyboard-operable camera (DD-004 a11y)
Embedded viewer is mouse-only:
- Adapter canvases have
aria-label but no tabindex (e.g. React component.ts:215-219; svelte/vue/element equivalents) → not focusable. Only the standalone demo canvas sets tabindex="0".
scene.ts constructs OrbitControls but never enables keyboard (listenToKeyDown() / .keys).
Add tabindex="0" to adapter canvases + enable OrbitControls keys so an embedded consumer's camera is keyboard-operable. (Verify the tabindex/keys absence before implementing.)
Acceptance criteria
Source: pre-release audit (planning session). PR theme: adapter surface. Changesets: minor (
gcode-preview-core+ 4 adapters;gcode-renderer-threefor keyboard keys). Consider splitting into two PRs (M3+M6 API / M4 a11y) if the diff gets large.Three related additions to the adapter public surface, all threaded through
gcode-preview-coreinto all 4 adapters at parity.M3 — Surface
capabilities+warningsin the adapter event surfaceThe library's differentiator is capability-honesty, but adapter consumers only get
onReady({ segments, layers, complete }).capabilities+warningslive instate.summary(controller.ts:106-113) yet appear in no event/callback — so a consumer can't gate their own color-mode UI the waytools/demodoes (which reads the raw handle /ir.header.capabilities). Addcapabilities+warningsto thereadypayload (or a dedicated capability event).M6 — Declarative
view/cameraStatepropsetView/getCameraState/setCameraState(#268) are reachable only via the imperative handle, while every other capability (colorMode, cameraMode, theme, scrub, scrubTime…) is a first-class prop. Add aviewprop + acameraStatetwo-way binding across all 4 adapters, matching the established pattern.M4 — Keyboard-operable camera (DD-004 a11y)
Embedded viewer is mouse-only:
aria-labelbut notabindex(e.g. Reactcomponent.ts:215-219; svelte/vue/element equivalents) → not focusable. Only the standalone demo canvas setstabindex="0".scene.tsconstructsOrbitControlsbut never enables keyboard (listenToKeyDown()/.keys).Add
tabindex="0"to adapter canvases + enable OrbitControls keys so an embedded consumer's camera is keyboard-operable. (Verify thetabindex/keys absence before implementing.)Acceptance criteria
capabilities+warningssurfaced via thereadypayload / event across all 4 adapters; behavioral-suite coverage added.viewprop +cameraStatebinding on all 4 adapters; behavioral-suite coverage added.tabindex) and camera is keyboard-orbitable; DD-004 keyboard-operability satisfied for embedders, not just the demo page.docs/manualupdated; typedoc on new public props/types.