It's just because of the chess.js API. It tells you if any given move is a checkmate, so you know to ignore those moves without playing them, but to find out if a move is a stalemate, you need to "play it" on a cloned game and then see if the opponent has any legal moves.
But given that a legal move by definition ends with the king not in check, the distinction often kind of goes away. In implementation terms, I think you basically have to just look at every possible move of every piece and see if any of them end without being in check.
Stalemate can and almost always does involve pieces that can't move because they would create check.
Yeah, that's true, I see what you're saying. I guess knowing the king is already in check allows for optimisations, since you have to either move the king, capture the attacker or block the line of attack, and nothing else is legal. And if you're double-checked you have to move the king, no matter what. As opposed to stalemate where you really do have to check the moves of every piece.
(My implementation: https://incoherency.co.uk/chess-steg/ and explanation at https://incoherency.co.uk/blog/stories/chess-steg.html )