Build a PIN Code Input
Build a 4-digit PIN entry component inside the existing app container. It must behave like a real PIN pad: each box accepts exactly one digit, focus moves automatically between boxes as the user types and deletes, and the component signals when all four digits have been filled.
All DOM construction and event wiring must be done in main.js.
- Render 4 single-character text inputs with
data-testidvaluespin-digit-0,pin-digit-1,pin-digit-2, andpin-digit-3inside the app container. - Each input accepts only digit characters (0–9). Any non-digit keypress must be ignored and must not populate the input or advance focus.
- When a digit is entered, focus automatically moves to the next input. If the last input is filled, focus stays on it.
- When Backspace is pressed on an empty input, focus moves back to the previous input. If the first input is already focused, Backspace has no focus side-effect.
- When all 4 inputs contain a digit, dispatch a custom
completeevent on the app container withdetail: { pin: "XXXX" }where XXXX is the 4-digit string. - Render a button with
data-testid="clear-btn"that clears all inputs and returns focus to the first input. Thecompleteevent may fire again after clearing if all 4 digits are re-entered.
User types '1', '2', '3', '4'
complete event fires with detail.pin = '1234'
Each digit entry advances focus to the next box. After the 4th digit, the complete event fires.
User types '1', then 'a', then '2'
Inputs show '1', '', '2', '' — focus is on index 2
'a' is not a digit — it is ignored. Focus does not advance on a rejected keypress.
User types '1', then presses Backspace twice
First Backspace clears '1' in box 0 (stays on box 0). Second Backspace on an already-empty box 0 has no effect.
Backspace clears the current box's content. If the box is already empty, focus moves to the previous box.
- Use only vanilla JavaScript — no React, Vue, or other frameworks.
- The
completeevent must be dispatched on the element withdata-testid="app", not on any individual input.
- browser environment
- browser-eval runner
- 8000ms judge budget
This component manages 4 independent DOM nodes. How would you structure this if the number of digits was configurable via a `data-length` attribute on the container?