The masked class-code input is duplicated byte-for-byte:
data-microbit-org's ClassCodeInput.tsx and classroom's
ClassroomDetailsJoinStep.tsx (~lines 46–65) carry identical
react-formatted-input-hook config — mask "## - ## - ## - ##", uppercase
8-character onInsert — one wrapped in a component, one inlined.
Candidate: a library ClassCodeInput as a bare control, taking its
chrome (label, helper text) from its surroundings, since the two apps label
it differently by design. It would bring a react-formatted-input-hook
dependency into the library.
Out of scope: classroom's second mask ("##", the classroom-name number
part) is single-site and stays app-side.
I don't have a strong view on whether/when we do this but it seemed worth
recording the commonality.
The masked class-code input is duplicated byte-for-byte:
data-microbit-org's
ClassCodeInput.tsxand classroom'sClassroomDetailsJoinStep.tsx(~lines 46–65) carry identicalreact-formatted-input-hook config — mask
"## - ## - ## - ##", uppercase8-character
onInsert— one wrapped in a component, one inlined.Candidate: a library
ClassCodeInputas a bare control, taking itschrome (label, helper text) from its surroundings, since the two apps label
it differently by design. It would bring a react-formatted-input-hook
dependency into the library.
Out of scope: classroom's second mask (
"##", the classroom-name numberpart) is single-site and stays app-side.
I don't have a strong view on whether/when we do this but it seemed worth
recording the commonality.