import { useEffect } from 'react' import api from '../api.js' import { useGameAccountSignup } from '../lib/useShardFeatures.js' import CreateGameAccountForm from './CreateGameAccountForm.jsx' // ── This module's fill for the `player.invite.accepted` slot ─────────────── // // Core's invite-acceptance page (`routes/player/AcceptInvite.jsx`) used to render // this step itself: it read `gameAccountSignup` out of core's public settings and // posted to `api.player.shard.createAccount`. Both of those are ours, and the // page they sat on is not — an invite is a core concept and staff get invited // too. So slice 3 declared a third extension slot rather than moving the page or // leaving core importing a module component. MODULE_API.md §3.7. // // **The whole decision about whether there is a step at all is on this side.** // Core renders the shell and a "skip" control whenever the slot is filled, and // hands us `onDone`. If this shard does not offer website-created game accounts // there is nothing to do here, so we call `onDone` and the invitee goes straight // to the portal — which is exactly what core's own code did when the flag was // off, only now the flag is not core's to read. // // The spinner while the answer is in flight is the honest cost of that split: the // invitee sees core's chrome for one cached request before this either renders or // stands aside. Rendering the form optimistically and retracting it would be // worse, and asking core to wait on a module before painting would put a module's // latency in front of a core page. export default function InviteGameAccountStep({ onDone }) { const signupOk = useGameAccountSignup() useEffect(() => { if (signupOk === false) onDone() }, [signupOk, onDone]) // `null` is "not yet", not "no" — see useGameAccountSignup. if (signupOk !== true) { return (
) } return ( <>

Your account is ready. Create a game account now to play, or skip and do it later from your portal.

) }