// Rover Accessory Controls // Purpose: Renders every generic control advertised by a selected rover as one ordered control surface. // Scope: Reusable content only; mobile and desktop parents own placement, expansion, and visibility. import { useCallback } from 'react'; import { useControlActions, useControlSelector } from '../../controls/index.js'; import useCanControlRover from '../../hooks/useCanControlRover.js'; import AccessoryControlField from './AccessoryControlField.jsx'; import useRoverAccessories from './useRoverAccessories.js'; const EMPTY_ACCESSORY_VALUES = Object.freeze({}); export default function RoverAccessoryControls({ roverId, className = '' }) { const { peripherals } = useRoverAccessories(roverId); const canControl = useCanControlRover(roverId); const { setPeripheralControl } = useControlActions(); const values = useControlSelector( (control) => control.state.peripheralValues?.[String(roverId)] || EMPTY_ACCESSORY_VALUES, ); const send = useCallback( (peripheralId, controlId, value) => setPeripheralControl(peripheralId, controlId, value), [setPeripheralControl], ); if (peripherals.length === 0) return null; return (
{peripherals.map((peripheral) => (
{/* The firmware's array order is authoritative. Mapping directly over it keeps physical authoring order intact across every UI host. */}

{peripheral.name}

{peripheral.controls.map((control) => ( ))}
))}
); }