@smoregg/sdk 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -376,6 +376,7 @@ function useGamePlayer(config) {
376
376
  function createHostBridge(options) {
377
377
  const { parentOrigin = "*", gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;
378
378
  let transport = null;
379
+ window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
379
380
  const messageHandler = (e) => {
380
381
  if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
381
382
  const msg = e.data;
@@ -406,7 +407,6 @@ function createHostBridge(options) {
406
407
  onPlayerLeave(payload.sessionId);
407
408
  });
408
409
  }
409
- window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
410
410
  if (onReady) {
411
411
  onReady({ roomCode, players, leaderId });
412
412
  }
@@ -445,6 +445,7 @@ function createHostBridge(options) {
445
445
  function createPlayerBridge(options) {
446
446
  const { parentOrigin = "*", gameId, listeners, onReady } = options;
447
447
  let transport = null;
448
+ window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
448
449
  const messageHandler = (e) => {
449
450
  if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
450
451
  const msg = e.data;
@@ -466,7 +467,6 @@ function createPlayerBridge(options) {
466
467
  transport.on(`${gameId}:${event}`, handler);
467
468
  });
468
469
  }
469
- window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
470
470
  if (onReady) {
471
471
  onReady({ roomCode, isLeader: !!isLeader, mySessionId });
472
472
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../src/transport/protocol.ts","../../../src/transport/PostMessageTransport.ts","../../../src/context/RoomProvider.tsx","../../../src/iframe/IframeRoomProvider.tsx","../../../src/hooks/useGameHost.ts","../../../src/hooks/useGamePlayer.ts","../../../src/iframe/vanilla.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n */\n\nexport const SMORE_MSG_PREFIX = 'smore:' as const;\n\nexport interface SmoreReadyMessage {\n type: 'smore:ready';\n}\n\nexport interface SmoreInitMessage {\n type: 'smore:init';\n payload: {\n side: 'host' | 'player';\n roomCode: string;\n players: any[];\n leaderId: string | null;\n mySessionId?: string;\n isLeader?: boolean;\n };\n}\n\nexport interface SmoreEmitMessage {\n type: 'smore:emit';\n payload: {\n event: string;\n data?: any;\n ackId?: string;\n };\n}\n\nexport interface SmoreEventMessage {\n type: 'smore:event';\n payload: {\n event: string;\n data?: any;\n };\n}\n\nexport interface SmoreAckMessage {\n type: 'smore:ack';\n payload: {\n ackId: string;\n data?: any;\n };\n}\n\nexport interface SmoreUpdateMessage {\n type: 'smore:update';\n payload: {\n players?: any[];\n leaderId?: string | null;\n };\n}\n\nexport type SmoreMessage =\n | SmoreReadyMessage\n | SmoreInitMessage\n | SmoreEmitMessage\n | SmoreEventMessage\n | SmoreAckMessage\n | SmoreUpdateMessage;\n\nexport function isSmoreMessage(data: any): data is SmoreMessage {\n return data && typeof data === 'object' && typeof data.type === 'string' && data.type.startsWith(SMORE_MSG_PREFIX);\n}\n","/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `smore:emit` to parent and listens for `smore:event` from parent.\n */\n\nimport type { Transport, TransportEventHandler } from './types';\nimport type { SmoreEventMessage, SmoreAckMessage } from './protocol';\nimport { isSmoreMessage } from './protocol';\n\nexport class PostMessageTransport implements Transport {\n private handlers = new Map<string, Set<TransportEventHandler>>();\n private ackCallbacks = new Map<string, (...args: any[]) => void>();\n private ackCounter = 0;\n private parentOrigin: string;\n private boundMessageHandler: (e: MessageEvent) => void;\n\n constructor(parentOrigin: string = '*') {\n this.parentOrigin = parentOrigin;\n this.boundMessageHandler = this.handleMessage.bind(this);\n window.addEventListener('message', this.boundMessageHandler);\n }\n\n emit(event: string, ...args: any[]): void {\n // Detect if last arg is a callback (ack pattern)\n let data: any = args[0];\n let ackId: string | undefined;\n\n if (args.length >= 2 && typeof args[args.length - 1] === 'function') {\n data = args.length === 2 ? args[0] : args[0];\n const callback = args[args.length - 1];\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event, data, ackId } },\n this.parentOrigin,\n );\n }\n\n on(event: string, handler: TransportEventHandler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler);\n }\n\n destroy(): void {\n window.removeEventListener('message', this.boundMessageHandler);\n this.handlers.clear();\n this.ackCallbacks.clear();\n }\n\n private handleMessage(e: MessageEvent): void {\n // Origin validation: only accept messages from the expected parent\n if (this.parentOrigin !== '*' && e.origin !== this.parentOrigin) return;\n\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:event') {\n const { event, data } = (msg as SmoreEventMessage).payload;\n const set = this.handlers.get(event);\n if (set) {\n set.forEach((handler) => handler(data));\n }\n } else if (msg.type === 'smore:ack') {\n const { ackId, data } = (msg as SmoreAckMessage).payload;\n const cb = this.ackCallbacks.get(ackId);\n if (cb) {\n this.ackCallbacks.delete(ackId);\n cb(data);\n }\n }\n }\n}\n","/**\n * RoomProvider - SDK Room Context\n *\n * Foundation context that all other SDK hooks depend on.\n * Provides room state (players, roomCode, leaderId) for both host and player sides.\n *\n * Also provides a Transport abstraction via TransportContext.\n * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.\n * - IframeRoomProvider (external) provides a PostMessageTransport.\n *\n * Usage:\n * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>\n * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} mySessionId={...} isLeader={...} socket={...} isConnected={...}>\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { Player } from '@smoregg/shared';\nimport type { Socket } from 'socket.io-client';\nimport type { Transport } from '../transport/types';\nimport { DirectTransport } from '../transport/DirectTransport';\n\n// ===== Transport Context =====\n\nconst TransportContext = createContext<Transport | null>(null);\n\nexport function useTransport(): Transport {\n const transport = useContext(TransportContext);\n if (!transport) {\n throw new Error('useTransport must be used within a RoomProvider that supplies a Transport');\n }\n return transport;\n}\n\nexport { TransportContext };\n\n// ===== State Types =====\n\nexport interface RoomState {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n}\n\nexport interface HostRoomState extends RoomState {\n socket: Socket;\n}\n\nexport interface PlayerRoomState extends RoomState {\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n}\n\nexport interface RoomContextValue {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n side: 'host' | 'player';\n host: HostRoomState | null;\n player: PlayerRoomState | null;\n}\n\n// ===== Context =====\n\nexport const RoomContext = createContext<RoomContextValue | null>(null);\n\n// ===== Host Provider =====\n\ninterface HostRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n socket: Socket;\n children: React.ReactNode;\n}\n\nexport const HostRoomProvider: React.FC<HostRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n socket,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const hostState: HostRoomState = useMemo(\n () => ({ roomCode, players, connectedPlayers, leaderId, socket }),\n [roomCode, players, connectedPlayers, leaderId, socket]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'host' as const,\n host: hostState,\n player: null,\n }),\n [roomCode, players, connectedPlayers, leaderId, hostState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Player Provider =====\n\ninterface PlayerRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n children: React.ReactNode;\n}\n\nexport const PlayerRoomProvider: React.FC<PlayerRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const playerState: PlayerRoomState = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n }),\n [roomCode, players, connectedPlayers, leaderId, mySessionId, isLeader, socket, isConnected]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'player' as const,\n host: null,\n player: playerState,\n }),\n [roomCode, players, connectedPlayers, leaderId, playerState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Hooks =====\n\nexport function useRoom(): RoomContextValue {\n const context = useContext(RoomContext);\n if (!context) {\n throw new Error('useRoom must be used within HostRoomProvider or PlayerRoomProvider');\n }\n return context;\n}\n\nexport function useHostRoom(): HostRoomState {\n const context = useRoom();\n if (context.side !== 'host' || !context.host) {\n throw new Error('useHostRoom must be used within HostRoomProvider');\n }\n return context.host;\n}\n\nexport function usePlayerRoom(): PlayerRoomState {\n const context = useRoom();\n if (context.side !== 'player' || !context.player) {\n throw new Error('usePlayerRoom must be used within PlayerRoomProvider');\n }\n return context.player;\n}\n","/**\n * IframeRoomProvider - Entry point for external (iframe-hosted) games.\n *\n * Usage inside an external game's iframe:\n * ```tsx\n * import { IframeRoomProvider } from '@smoregg/sdk/iframe';\n * import { useGameHost } from '@smoregg/sdk/iframe';\n *\n * function App() {\n * return (\n * <IframeRoomProvider>\n * <MyGame />\n * </IframeRoomProvider>\n * );\n * }\n * ```\n *\n * Lifecycle:\n * 1. Mount → sends `smore:ready` to parent\n * 2. Receives `smore:init` from parent with room state\n * 3. Creates PostMessageTransport\n * 4. Renders children with RoomContext + TransportContext\n */\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage } from '../transport/protocol';\nimport type { SmoreInitMessage } from '../transport/protocol';\nimport { TransportContext, RoomContext } from '../context/RoomProvider';\nimport type { RoomContextValue, HostRoomState, PlayerRoomState } from '../context/RoomProvider';\n\n// ===== Provider =====\n\ninterface IframeRoomProviderProps {\n children: React.ReactNode;\n parentOrigin?: string;\n}\n\nexport const IframeRoomProvider: React.FC<IframeRoomProviderProps> = ({ children, parentOrigin = '*' }) => {\n const [initData, setInitData] = useState<SmoreInitMessage['payload'] | null>(null);\n const [transport, setTransport] = useState<PostMessageTransport | null>(null);\n\n // Step 1: Send ready, listen for init\n useEffect(() => {\n const handler = (e: MessageEvent) => {\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n if (msg.type === 'smore:init') {\n setInitData(msg.payload);\n }\n };\n\n window.addEventListener('message', handler);\n\n // Signal readiness\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n return () => window.removeEventListener('message', handler);\n }, [parentOrigin]);\n\n // Step 2: Create transport once init arrives\n useEffect(() => {\n if (!initData) return;\n const t = new PostMessageTransport(parentOrigin);\n setTransport(t);\n return () => t.destroy();\n }, [initData, parentOrigin]);\n\n // Build room context value (uses the SAME RoomContext from RoomProvider)\n const roomContextValue = useMemo<RoomContextValue | null>(() => {\n if (!initData) return null;\n\n const { side, roomCode, players, leaderId, mySessionId, isLeader } = initData;\n const connectedPlayers = players.filter((p: any) => p.connected !== false);\n\n if (side === 'host') {\n const hostState: HostRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n socket: null as any, // Not available in iframe — use transport\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'host',\n host: hostState,\n player: null,\n };\n } else {\n const playerState: PlayerRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId: mySessionId || '',\n isLeader: isLeader || false,\n socket: null as any, // Not available in iframe — use transport\n isConnected: true,\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'player',\n host: null,\n player: playerState,\n };\n }\n }, [initData]);\n\n if (!initData || !transport || !roomContextValue) {\n return null; // Waiting for parent init\n }\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={roomContextValue}>\n {children}\n </RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n","/**\n * useGameHost - Host-side game hook for the S'MORE SDK\n *\n * Provides host game developers with:\n * - Automatic room state access (via useHostRoom context)\n * - Input listening (dedicated socket events)\n * - Broadcasting to all/specific players\n * - Game over emission\n * - Player lifecycle callbacks\n *\n * Internally uses Transport abstraction so the same API works over\n * Socket.IO (bundled games) or postMessage (iframe games).\n */\nimport { useEffect, useCallback, useRef } from 'react';\nimport { useHostRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { HostRoomState } from '../context/RoomProvider';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype InputHandler = (playerId: string, data?: any) => void;\n\nexport interface UseGameHostConfig {\n /** Unique game identifier (e.g. 'fibbage', 'wasd') */\n gameId: string;\n\n /**\n * Map of action names to handler functions.\n * Listens directly on socket for `{gameId}:{key}` events.\n */\n onInput?: Record<string, InputHandler>;\n\n /**\n * Called when a player requests game state (e.g. after returning from background).\n * Return the current game state object to send back to that player.\n */\n onStateRequest?: (playerId: string) => Record<string, any>;\n\n /** Called when a player leaves the room. */\n onPlayerLeave?: (playerId: string) => void;\n\n /** Called when a player disconnects (may reconnect). */\n onPlayerDisconnect?: (playerId: string) => void;\n\n /** Called when a previously disconnected player reconnects. */\n onPlayerReconnect?: (playerId: string) => void;\n\n /**\n * Generic socket event listeners (for server broadcasts the host needs to receive).\n * Keys are full event names, values are handler functions.\n */\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGameHostReturn {\n /** Current room state from HostRoomProvider context. */\n room: HostRoomState;\n\n /** Broadcast an event to all players via the host socket. */\n broadcast: (event: string, data: any) => void;\n\n /** Send state/event to a specific player by sessionId. */\n sendToPlayer: (sessionId: string, event: string, data: any) => void;\n\n /** Emit game-over with optional results payload. */\n emitGameOver: (results?: any) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useGameHost(config: UseGameHostConfig): UseGameHostReturn {\n const { gameId, onInput, onStateRequest, onPlayerLeave, onPlayerDisconnect, onPlayerReconnect, listeners } = config;\n\n const hostRoom = useHostRoom();\n const transport = useTransport();\n\n // Stable refs to avoid stale closures in listeners\n const onInputRef = useRef(onInput);\n const onStateRequestRef = useRef(onStateRequest);\n const onPlayerLeaveRef = useRef(onPlayerLeave);\n const onPlayerDisconnectRef = useRef(onPlayerDisconnect);\n const onPlayerReconnectRef = useRef(onPlayerReconnect);\n\n useEffect(() => { onInputRef.current = onInput; }, [onInput]);\n useEffect(() => { onStateRequestRef.current = onStateRequest; }, [onStateRequest]);\n useEffect(() => { onPlayerLeaveRef.current = onPlayerLeave; }, [onPlayerLeave]);\n useEffect(() => { onPlayerDisconnectRef.current = onPlayerDisconnect; }, [onPlayerDisconnect]);\n useEffect(() => { onPlayerReconnectRef.current = onPlayerReconnect; }, [onPlayerReconnect]);\n\n // -------------------------------------------------------------------------\n // Dedicated input listeners (transport events)\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport || !onInputRef.current) return;\n\n const registeredEvents: Array<{ event: string; handler: (...args: any[]) => void }> = [];\n\n // For each handler key, listen on transport for \"{gameId}:{key}\"\n const inputMap = onInputRef.current;\n for (const key of Object.keys(inputMap)) {\n const eventName = `${gameId}:${key}`;\n const handler = (data: any) => {\n const currentHandler = onInputRef.current?.[key];\n if (currentHandler) {\n currentHandler(data?.sessionId ?? data?.playerId, data);\n }\n };\n transport.on(eventName, handler);\n registeredEvents.push({ event: eventName, handler });\n }\n\n return () => {\n for (const { event, handler } of registeredEvents) {\n transport.off(event, handler);\n }\n };\n }, [gameId, transport]);\n\n // -------------------------------------------------------------------------\n // State request handler\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const handler = (data: { requesterId: string }) => {\n const stateFn = onStateRequestRef.current;\n if (!stateFn) return;\n\n const gameState = stateFn(data.requesterId);\n transport.emit('game:state-response', {\n targetSessionId: data.requesterId,\n gameState: {\n gameId,\n ...gameState,\n },\n });\n };\n\n transport.on('game:state-request', handler);\n return () => {\n transport.off('game:state-request', handler);\n };\n }, [transport, gameId]);\n\n // -------------------------------------------------------------------------\n // Player lifecycle listeners\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const onLeft = (data: any) => {\n onPlayerLeaveRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onDisconnected = (data: any) => {\n onPlayerDisconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onReconnected = (data: any) => {\n onPlayerReconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n\n transport.on('room:player-left', onLeft);\n transport.on('room:player-disconnected', onDisconnected);\n transport.on('room:player-reconnected', onReconnected);\n\n return () => {\n transport.off('room:player-left', onLeft);\n transport.off('room:player-disconnected', onDisconnected);\n transport.off('room:player-reconnected', onReconnected);\n };\n }, [transport]);\n\n // -------------------------------------------------------------------------\n // Generic listeners\n // -------------------------------------------------------------------------\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const entries = Object.entries(listenersRef.current);\n const handlers = entries.map(([event, handler]) => {\n transport.on(event, handler);\n return () => { transport.off(event, handler); };\n });\n return () => handlers.forEach(fn => fn());\n }, [transport, listeners]);\n\n // -------------------------------------------------------------------------\n // Actions\n // -------------------------------------------------------------------------\n\n const broadcast = useCallback(\n (event: string, data: any) => {\n transport?.emit(event, data);\n },\n [transport],\n );\n\n const sendToPlayer = useCallback(\n (sessionId: string, event: string, data: any) => {\n transport?.emit('game:state-to-player', {\n targetSessionId: sessionId,\n gameId,\n event,\n state: data,\n });\n },\n [transport, gameId],\n );\n\n const emitGameOver = useCallback(\n (results?: any) => {\n transport?.emit('room:game-over', { gameId, results });\n },\n [transport, gameId],\n );\n\n return {\n room: hostRoom,\n broadcast,\n sendToPlayer,\n emitGameOver,\n };\n}\n","import { useEffect, useCallback, useState, useRef } from 'react';\nimport { usePlayerRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { PlayerRoomState } from '../context/RoomProvider';\n\nexport interface UseGamePlayerConfig {\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGamePlayerReturn {\n room: PlayerRoomState;\n emit: (event: string, data?: any, callback?: (response: any) => void) => void;\n /** Emit a tap input: sends `{gameId}:{action}` event */\n sendTapInput: (action: string) => void;\n /** Emit a hold input: sends `{gameId}:{action}:{type}` event */\n sendHoldInput: (action: string, type: 'START' | 'END') => void;\n isConnected: boolean;\n gameState: Record<string, any> | null;\n}\n\nexport function useGamePlayer(config: UseGamePlayerConfig): UseGamePlayerReturn {\n const room = usePlayerRoom();\n const transport = useTransport();\n const { isConnected } = room;\n const { gameId, listeners } = config;\n const [gameState, setGameState] = useState<Record<string, any> | null>(null);\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n // Transport listeners\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const cleanups: (() => void)[] = [];\n Object.entries(listenersRef.current).forEach(([event, handler]) => {\n transport.on(event, handler);\n cleanups.push(() => transport.off(event, handler));\n });\n return () => cleanups.forEach(fn => fn());\n }, [transport, listeners]);\n\n // Reconnection: game:state-response\n useEffect(() => {\n if (!transport) return;\n const handler = (state: any) => {\n if (state.gameId !== gameId) return;\n setGameState(state);\n };\n transport.on('game:state-response', handler);\n return () => { transport.off('game:state-response', handler); };\n }, [transport, gameId]);\n\n // game:state-to-player (Host push)\n useEffect(() => {\n if (!transport) return;\n const handler = (data: { gameId: string; state: any }) => {\n if (data.gameId !== gameId) return;\n setGameState(data.state);\n };\n transport.on('game:state-to-player', handler);\n return () => { transport.off('game:state-to-player', handler); };\n }, [transport, gameId]);\n\n // Visibility change\n useEffect(() => {\n if (!transport) return;\n const handler = () => {\n if (!document.hidden) {\n transport.emit('game:request-state', { gameId });\n }\n };\n document.addEventListener('visibilitychange', handler);\n return () => document.removeEventListener('visibilitychange', handler);\n }, [transport, gameId]);\n\n // API\n const emit = useCallback((event: string, data?: any, callback?: (response: any) => void) => {\n if (!transport) return;\n if (callback) {\n transport.emit(event, data, callback);\n } else {\n transport.emit(event, data);\n }\n }, [transport]);\n\n const sendTapInput = useCallback((action: string) => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}`);\n }, [transport, gameId]);\n\n const sendHoldInput = useCallback((action: string, type: 'START' | 'END') => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}:${type}`);\n }, [transport, gameId]);\n\n return { room, emit, sendTapInput, sendHoldInput, isConnected, gameState };\n}\n","/**\n * Vanilla JS bridge API for iframe-hosted games.\n * No React - pure JavaScript with PostMessage transport.\n */\n\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage, type SmoreInitMessage } from '../transport/protocol';\n\nexport interface HostBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n onInput?: Record<string, (playerId: string, data: any) => void>;\n onPlayerJoin?: (playerId: string) => void;\n onPlayerLeave?: (playerId: string) => void;\n onReady?: (room: { roomCode: string; players: any[]; leaderId: string | null }) => void;\n}\n\nexport interface HostBridge {\n broadcast: (event: string, data?: any) => void;\n sendToPlayer: (playerId: string, event: string, data?: any) => void;\n emitGameOver: (results: any) => void;\n destroy: () => void;\n}\n\nexport interface PlayerBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n onReady?: (room: { roomCode: string; isLeader: boolean; mySessionId: string }) => void;\n}\n\nexport interface PlayerBridge {\n emit: (event: string, data?: any) => void;\n onEvent: (event: string, handler: (data: any) => void) => () => void;\n destroy: () => void;\n}\n\nexport function createHostBridge(options: HostBridgeOptions): HostBridge {\n const { parentOrigin = '*', gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, players, leaderId } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'host') {\n console.error('[HostBridge] Received init for wrong side:', side);\n return;\n }\n\n // Create transport and wire up event handlers\n transport = new PostMessageTransport(parentOrigin);\n\n // Handle input events: {gameId}:input:{action}\n if (onInput) {\n Object.keys(onInput).forEach((action) => {\n const handler = onInput[action];\n transport!.on(`${gameId}:input:${action}`, (payload: any) => {\n const { playerId, data } = payload;\n handler(playerId, data);\n });\n });\n }\n\n // Handle player join/leave events\n if (onPlayerJoin) {\n transport.on('player:joined', (payload: any) => {\n onPlayerJoin(payload.sessionId);\n });\n }\n if (onPlayerLeave) {\n transport.on('player:left', (payload: any) => {\n onPlayerLeave(payload.sessionId);\n });\n }\n\n isInitialized = true;\n\n // Notify parent we're ready\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, players, leaderId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n broadcast: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot broadcast before init');\n return;\n }\n transport.emit(`${gameId}:broadcast:${event}`, data);\n },\n\n sendToPlayer: (playerId: string, event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot sendToPlayer before init');\n return;\n }\n transport.emit(`${gameId}:to-player:${event}`, { playerId, data });\n },\n\n emitGameOver: (results: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot emitGameOver before init');\n return;\n }\n transport.emit(`${gameId}:game-over`, results);\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n\nexport function createPlayerBridge(options: PlayerBridgeOptions): PlayerBridge {\n const { parentOrigin = '*', gameId, listeners, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, mySessionId, isLeader } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'player') {\n console.error('[PlayerBridge] Received init for wrong side:', side);\n return;\n }\n\n if (!mySessionId) {\n console.error('[PlayerBridge] Missing mySessionId in init payload');\n return;\n }\n\n // Create transport and wire up listeners\n transport = new PostMessageTransport(parentOrigin);\n\n // Wire up game-specific event listeners\n if (listeners) {\n Object.keys(listeners).forEach((event) => {\n const handler = listeners[event];\n transport!.on(`${gameId}:${event}`, handler);\n });\n }\n\n isInitialized = true;\n\n // Notify parent we're ready\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, isLeader: !!isLeader, mySessionId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n emit: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot emit before init');\n return;\n }\n transport.emit(`${gameId}:${event}`, data);\n },\n\n onEvent: (event: string, handler: (data: any) => void) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot onEvent before init');\n return () => {};\n }\n transport.on(`${gameId}:${event}`, handler);\n return () => {\n transport?.off(`${gameId}:${event}`, handler);\n };\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n"],"names":["createContext","useContext","useState","useEffect","useMemo","jsx","useRef","useCallback"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../src/transport/protocol.ts","../../../src/transport/PostMessageTransport.ts","../../../src/context/RoomProvider.tsx","../../../src/iframe/IframeRoomProvider.tsx","../../../src/hooks/useGameHost.ts","../../../src/hooks/useGamePlayer.ts","../../../src/iframe/vanilla.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n */\n\nexport const SMORE_MSG_PREFIX = 'smore:' as const;\n\nexport interface SmoreReadyMessage {\n type: 'smore:ready';\n}\n\nexport interface SmoreInitMessage {\n type: 'smore:init';\n payload: {\n side: 'host' | 'player';\n roomCode: string;\n players: any[];\n leaderId: string | null;\n mySessionId?: string;\n isLeader?: boolean;\n };\n}\n\nexport interface SmoreEmitMessage {\n type: 'smore:emit';\n payload: {\n event: string;\n data?: any;\n ackId?: string;\n };\n}\n\nexport interface SmoreEventMessage {\n type: 'smore:event';\n payload: {\n event: string;\n data?: any;\n };\n}\n\nexport interface SmoreAckMessage {\n type: 'smore:ack';\n payload: {\n ackId: string;\n data?: any;\n };\n}\n\nexport interface SmoreUpdateMessage {\n type: 'smore:update';\n payload: {\n players?: any[];\n leaderId?: string | null;\n };\n}\n\nexport type SmoreMessage =\n | SmoreReadyMessage\n | SmoreInitMessage\n | SmoreEmitMessage\n | SmoreEventMessage\n | SmoreAckMessage\n | SmoreUpdateMessage;\n\nexport function isSmoreMessage(data: any): data is SmoreMessage {\n return data && typeof data === 'object' && typeof data.type === 'string' && data.type.startsWith(SMORE_MSG_PREFIX);\n}\n","/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `smore:emit` to parent and listens for `smore:event` from parent.\n */\n\nimport type { Transport, TransportEventHandler } from './types';\nimport type { SmoreEventMessage, SmoreAckMessage } from './protocol';\nimport { isSmoreMessage } from './protocol';\n\nexport class PostMessageTransport implements Transport {\n private handlers = new Map<string, Set<TransportEventHandler>>();\n private ackCallbacks = new Map<string, (...args: any[]) => void>();\n private ackCounter = 0;\n private parentOrigin: string;\n private boundMessageHandler: (e: MessageEvent) => void;\n\n constructor(parentOrigin: string = '*') {\n this.parentOrigin = parentOrigin;\n this.boundMessageHandler = this.handleMessage.bind(this);\n window.addEventListener('message', this.boundMessageHandler);\n }\n\n emit(event: string, ...args: any[]): void {\n // Detect if last arg is a callback (ack pattern)\n let data: any = args[0];\n let ackId: string | undefined;\n\n if (args.length >= 2 && typeof args[args.length - 1] === 'function') {\n data = args.length === 2 ? args[0] : args[0];\n const callback = args[args.length - 1];\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event, data, ackId } },\n this.parentOrigin,\n );\n }\n\n on(event: string, handler: TransportEventHandler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler);\n }\n\n destroy(): void {\n window.removeEventListener('message', this.boundMessageHandler);\n this.handlers.clear();\n this.ackCallbacks.clear();\n }\n\n private handleMessage(e: MessageEvent): void {\n // Origin validation: only accept messages from the expected parent\n if (this.parentOrigin !== '*' && e.origin !== this.parentOrigin) return;\n\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:event') {\n const { event, data } = (msg as SmoreEventMessage).payload;\n const set = this.handlers.get(event);\n if (set) {\n set.forEach((handler) => handler(data));\n }\n } else if (msg.type === 'smore:ack') {\n const { ackId, data } = (msg as SmoreAckMessage).payload;\n const cb = this.ackCallbacks.get(ackId);\n if (cb) {\n this.ackCallbacks.delete(ackId);\n cb(data);\n }\n }\n }\n}\n","/**\n * RoomProvider - SDK Room Context\n *\n * Foundation context that all other SDK hooks depend on.\n * Provides room state (players, roomCode, leaderId) for both host and player sides.\n *\n * Also provides a Transport abstraction via TransportContext.\n * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.\n * - IframeRoomProvider (external) provides a PostMessageTransport.\n *\n * Usage:\n * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>\n * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} mySessionId={...} isLeader={...} socket={...} isConnected={...}>\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { Player } from '@smoregg/shared';\nimport type { Socket } from 'socket.io-client';\nimport type { Transport } from '../transport/types';\nimport { DirectTransport } from '../transport/DirectTransport';\n\n// ===== Transport Context =====\n\nconst TransportContext = createContext<Transport | null>(null);\n\nexport function useTransport(): Transport {\n const transport = useContext(TransportContext);\n if (!transport) {\n throw new Error('useTransport must be used within a RoomProvider that supplies a Transport');\n }\n return transport;\n}\n\nexport { TransportContext };\n\n// ===== State Types =====\n\nexport interface RoomState {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n}\n\nexport interface HostRoomState extends RoomState {\n socket: Socket;\n}\n\nexport interface PlayerRoomState extends RoomState {\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n}\n\nexport interface RoomContextValue {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n side: 'host' | 'player';\n host: HostRoomState | null;\n player: PlayerRoomState | null;\n}\n\n// ===== Context =====\n\nexport const RoomContext = createContext<RoomContextValue | null>(null);\n\n// ===== Host Provider =====\n\ninterface HostRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n socket: Socket;\n children: React.ReactNode;\n}\n\nexport const HostRoomProvider: React.FC<HostRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n socket,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const hostState: HostRoomState = useMemo(\n () => ({ roomCode, players, connectedPlayers, leaderId, socket }),\n [roomCode, players, connectedPlayers, leaderId, socket]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'host' as const,\n host: hostState,\n player: null,\n }),\n [roomCode, players, connectedPlayers, leaderId, hostState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Player Provider =====\n\ninterface PlayerRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n children: React.ReactNode;\n}\n\nexport const PlayerRoomProvider: React.FC<PlayerRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const playerState: PlayerRoomState = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n }),\n [roomCode, players, connectedPlayers, leaderId, mySessionId, isLeader, socket, isConnected]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'player' as const,\n host: null,\n player: playerState,\n }),\n [roomCode, players, connectedPlayers, leaderId, playerState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Hooks =====\n\nexport function useRoom(): RoomContextValue {\n const context = useContext(RoomContext);\n if (!context) {\n throw new Error('useRoom must be used within HostRoomProvider or PlayerRoomProvider');\n }\n return context;\n}\n\nexport function useHostRoom(): HostRoomState {\n const context = useRoom();\n if (context.side !== 'host' || !context.host) {\n throw new Error('useHostRoom must be used within HostRoomProvider');\n }\n return context.host;\n}\n\nexport function usePlayerRoom(): PlayerRoomState {\n const context = useRoom();\n if (context.side !== 'player' || !context.player) {\n throw new Error('usePlayerRoom must be used within PlayerRoomProvider');\n }\n return context.player;\n}\n","/**\n * IframeRoomProvider - Entry point for external (iframe-hosted) games.\n *\n * Usage inside an external game's iframe:\n * ```tsx\n * import { IframeRoomProvider } from '@smoregg/sdk/iframe';\n * import { useGameHost } from '@smoregg/sdk/iframe';\n *\n * function App() {\n * return (\n * <IframeRoomProvider>\n * <MyGame />\n * </IframeRoomProvider>\n * );\n * }\n * ```\n *\n * Lifecycle:\n * 1. Mount → sends `smore:ready` to parent\n * 2. Receives `smore:init` from parent with room state\n * 3. Creates PostMessageTransport\n * 4. Renders children with RoomContext + TransportContext\n */\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage } from '../transport/protocol';\nimport type { SmoreInitMessage } from '../transport/protocol';\nimport { TransportContext, RoomContext } from '../context/RoomProvider';\nimport type { RoomContextValue, HostRoomState, PlayerRoomState } from '../context/RoomProvider';\n\n// ===== Provider =====\n\ninterface IframeRoomProviderProps {\n children: React.ReactNode;\n parentOrigin?: string;\n}\n\nexport const IframeRoomProvider: React.FC<IframeRoomProviderProps> = ({ children, parentOrigin = '*' }) => {\n const [initData, setInitData] = useState<SmoreInitMessage['payload'] | null>(null);\n const [transport, setTransport] = useState<PostMessageTransport | null>(null);\n\n // Step 1: Send ready, listen for init\n useEffect(() => {\n const handler = (e: MessageEvent) => {\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n if (msg.type === 'smore:init') {\n setInitData(msg.payload);\n }\n };\n\n window.addEventListener('message', handler);\n\n // Signal readiness\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n return () => window.removeEventListener('message', handler);\n }, [parentOrigin]);\n\n // Step 2: Create transport once init arrives\n useEffect(() => {\n if (!initData) return;\n const t = new PostMessageTransport(parentOrigin);\n setTransport(t);\n return () => t.destroy();\n }, [initData, parentOrigin]);\n\n // Build room context value (uses the SAME RoomContext from RoomProvider)\n const roomContextValue = useMemo<RoomContextValue | null>(() => {\n if (!initData) return null;\n\n const { side, roomCode, players, leaderId, mySessionId, isLeader } = initData;\n const connectedPlayers = players.filter((p: any) => p.connected !== false);\n\n if (side === 'host') {\n const hostState: HostRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n socket: null as any, // Not available in iframe — use transport\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'host',\n host: hostState,\n player: null,\n };\n } else {\n const playerState: PlayerRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId: mySessionId || '',\n isLeader: isLeader || false,\n socket: null as any, // Not available in iframe — use transport\n isConnected: true,\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'player',\n host: null,\n player: playerState,\n };\n }\n }, [initData]);\n\n if (!initData || !transport || !roomContextValue) {\n return null; // Waiting for parent init\n }\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={roomContextValue}>\n {children}\n </RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n","/**\n * useGameHost - Host-side game hook for the S'MORE SDK\n *\n * Provides host game developers with:\n * - Automatic room state access (via useHostRoom context)\n * - Input listening (dedicated socket events)\n * - Broadcasting to all/specific players\n * - Game over emission\n * - Player lifecycle callbacks\n *\n * Internally uses Transport abstraction so the same API works over\n * Socket.IO (bundled games) or postMessage (iframe games).\n */\nimport { useEffect, useCallback, useRef } from 'react';\nimport { useHostRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { HostRoomState } from '../context/RoomProvider';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype InputHandler = (playerId: string, data?: any) => void;\n\nexport interface UseGameHostConfig {\n /** Unique game identifier (e.g. 'fibbage', 'wasd') */\n gameId: string;\n\n /**\n * Map of action names to handler functions.\n * Listens directly on socket for `{gameId}:{key}` events.\n */\n onInput?: Record<string, InputHandler>;\n\n /**\n * Called when a player requests game state (e.g. after returning from background).\n * Return the current game state object to send back to that player.\n */\n onStateRequest?: (playerId: string) => Record<string, any>;\n\n /** Called when a player leaves the room. */\n onPlayerLeave?: (playerId: string) => void;\n\n /** Called when a player disconnects (may reconnect). */\n onPlayerDisconnect?: (playerId: string) => void;\n\n /** Called when a previously disconnected player reconnects. */\n onPlayerReconnect?: (playerId: string) => void;\n\n /**\n * Generic socket event listeners (for server broadcasts the host needs to receive).\n * Keys are full event names, values are handler functions.\n */\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGameHostReturn {\n /** Current room state from HostRoomProvider context. */\n room: HostRoomState;\n\n /** Broadcast an event to all players via the host socket. */\n broadcast: (event: string, data: any) => void;\n\n /** Send state/event to a specific player by sessionId. */\n sendToPlayer: (sessionId: string, event: string, data: any) => void;\n\n /** Emit game-over with optional results payload. */\n emitGameOver: (results?: any) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useGameHost(config: UseGameHostConfig): UseGameHostReturn {\n const { gameId, onInput, onStateRequest, onPlayerLeave, onPlayerDisconnect, onPlayerReconnect, listeners } = config;\n\n const hostRoom = useHostRoom();\n const transport = useTransport();\n\n // Stable refs to avoid stale closures in listeners\n const onInputRef = useRef(onInput);\n const onStateRequestRef = useRef(onStateRequest);\n const onPlayerLeaveRef = useRef(onPlayerLeave);\n const onPlayerDisconnectRef = useRef(onPlayerDisconnect);\n const onPlayerReconnectRef = useRef(onPlayerReconnect);\n\n useEffect(() => { onInputRef.current = onInput; }, [onInput]);\n useEffect(() => { onStateRequestRef.current = onStateRequest; }, [onStateRequest]);\n useEffect(() => { onPlayerLeaveRef.current = onPlayerLeave; }, [onPlayerLeave]);\n useEffect(() => { onPlayerDisconnectRef.current = onPlayerDisconnect; }, [onPlayerDisconnect]);\n useEffect(() => { onPlayerReconnectRef.current = onPlayerReconnect; }, [onPlayerReconnect]);\n\n // -------------------------------------------------------------------------\n // Dedicated input listeners (transport events)\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport || !onInputRef.current) return;\n\n const registeredEvents: Array<{ event: string; handler: (...args: any[]) => void }> = [];\n\n // For each handler key, listen on transport for \"{gameId}:{key}\"\n const inputMap = onInputRef.current;\n for (const key of Object.keys(inputMap)) {\n const eventName = `${gameId}:${key}`;\n const handler = (data: any) => {\n const currentHandler = onInputRef.current?.[key];\n if (currentHandler) {\n currentHandler(data?.sessionId ?? data?.playerId, data);\n }\n };\n transport.on(eventName, handler);\n registeredEvents.push({ event: eventName, handler });\n }\n\n return () => {\n for (const { event, handler } of registeredEvents) {\n transport.off(event, handler);\n }\n };\n }, [gameId, transport]);\n\n // -------------------------------------------------------------------------\n // State request handler\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const handler = (data: { requesterId: string }) => {\n const stateFn = onStateRequestRef.current;\n if (!stateFn) return;\n\n const gameState = stateFn(data.requesterId);\n transport.emit('game:state-response', {\n targetSessionId: data.requesterId,\n gameState: {\n gameId,\n ...gameState,\n },\n });\n };\n\n transport.on('game:state-request', handler);\n return () => {\n transport.off('game:state-request', handler);\n };\n }, [transport, gameId]);\n\n // -------------------------------------------------------------------------\n // Player lifecycle listeners\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const onLeft = (data: any) => {\n onPlayerLeaveRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onDisconnected = (data: any) => {\n onPlayerDisconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onReconnected = (data: any) => {\n onPlayerReconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n\n transport.on('room:player-left', onLeft);\n transport.on('room:player-disconnected', onDisconnected);\n transport.on('room:player-reconnected', onReconnected);\n\n return () => {\n transport.off('room:player-left', onLeft);\n transport.off('room:player-disconnected', onDisconnected);\n transport.off('room:player-reconnected', onReconnected);\n };\n }, [transport]);\n\n // -------------------------------------------------------------------------\n // Generic listeners\n // -------------------------------------------------------------------------\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const entries = Object.entries(listenersRef.current);\n const handlers = entries.map(([event, handler]) => {\n transport.on(event, handler);\n return () => { transport.off(event, handler); };\n });\n return () => handlers.forEach(fn => fn());\n }, [transport, listeners]);\n\n // -------------------------------------------------------------------------\n // Actions\n // -------------------------------------------------------------------------\n\n const broadcast = useCallback(\n (event: string, data: any) => {\n transport?.emit(event, data);\n },\n [transport],\n );\n\n const sendToPlayer = useCallback(\n (sessionId: string, event: string, data: any) => {\n transport?.emit('game:state-to-player', {\n targetSessionId: sessionId,\n gameId,\n event,\n state: data,\n });\n },\n [transport, gameId],\n );\n\n const emitGameOver = useCallback(\n (results?: any) => {\n transport?.emit('room:game-over', { gameId, results });\n },\n [transport, gameId],\n );\n\n return {\n room: hostRoom,\n broadcast,\n sendToPlayer,\n emitGameOver,\n };\n}\n","import { useEffect, useCallback, useState, useRef } from 'react';\nimport { usePlayerRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { PlayerRoomState } from '../context/RoomProvider';\n\nexport interface UseGamePlayerConfig {\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGamePlayerReturn {\n room: PlayerRoomState;\n emit: (event: string, data?: any, callback?: (response: any) => void) => void;\n /** Emit a tap input: sends `{gameId}:{action}` event */\n sendTapInput: (action: string) => void;\n /** Emit a hold input: sends `{gameId}:{action}:{type}` event */\n sendHoldInput: (action: string, type: 'START' | 'END') => void;\n isConnected: boolean;\n gameState: Record<string, any> | null;\n}\n\nexport function useGamePlayer(config: UseGamePlayerConfig): UseGamePlayerReturn {\n const room = usePlayerRoom();\n const transport = useTransport();\n const { isConnected } = room;\n const { gameId, listeners } = config;\n const [gameState, setGameState] = useState<Record<string, any> | null>(null);\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n // Transport listeners\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const cleanups: (() => void)[] = [];\n Object.entries(listenersRef.current).forEach(([event, handler]) => {\n transport.on(event, handler);\n cleanups.push(() => transport.off(event, handler));\n });\n return () => cleanups.forEach(fn => fn());\n }, [transport, listeners]);\n\n // Reconnection: game:state-response\n useEffect(() => {\n if (!transport) return;\n const handler = (state: any) => {\n if (state.gameId !== gameId) return;\n setGameState(state);\n };\n transport.on('game:state-response', handler);\n return () => { transport.off('game:state-response', handler); };\n }, [transport, gameId]);\n\n // game:state-to-player (Host push)\n useEffect(() => {\n if (!transport) return;\n const handler = (data: { gameId: string; state: any }) => {\n if (data.gameId !== gameId) return;\n setGameState(data.state);\n };\n transport.on('game:state-to-player', handler);\n return () => { transport.off('game:state-to-player', handler); };\n }, [transport, gameId]);\n\n // Visibility change\n useEffect(() => {\n if (!transport) return;\n const handler = () => {\n if (!document.hidden) {\n transport.emit('game:request-state', { gameId });\n }\n };\n document.addEventListener('visibilitychange', handler);\n return () => document.removeEventListener('visibilitychange', handler);\n }, [transport, gameId]);\n\n // API\n const emit = useCallback((event: string, data?: any, callback?: (response: any) => void) => {\n if (!transport) return;\n if (callback) {\n transport.emit(event, data, callback);\n } else {\n transport.emit(event, data);\n }\n }, [transport]);\n\n const sendTapInput = useCallback((action: string) => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}`);\n }, [transport, gameId]);\n\n const sendHoldInput = useCallback((action: string, type: 'START' | 'END') => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}:${type}`);\n }, [transport, gameId]);\n\n return { room, emit, sendTapInput, sendHoldInput, isConnected, gameState };\n}\n","/**\n * Vanilla JS bridge API for iframe-hosted games.\n * No React - pure JavaScript with PostMessage transport.\n */\n\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage, type SmoreInitMessage } from '../transport/protocol';\n\nexport interface HostBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n onInput?: Record<string, (playerId: string, data: any) => void>;\n onPlayerJoin?: (playerId: string) => void;\n onPlayerLeave?: (playerId: string) => void;\n onReady?: (room: { roomCode: string; players: any[]; leaderId: string | null }) => void;\n}\n\nexport interface HostBridge {\n broadcast: (event: string, data?: any) => void;\n sendToPlayer: (playerId: string, event: string, data?: any) => void;\n emitGameOver: (results: any) => void;\n destroy: () => void;\n}\n\nexport interface PlayerBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n onReady?: (room: { roomCode: string; isLeader: boolean; mySessionId: string }) => void;\n}\n\nexport interface PlayerBridge {\n emit: (event: string, data?: any) => void;\n onEvent: (event: string, handler: (data: any) => void) => () => void;\n destroy: () => void;\n}\n\nexport function createHostBridge(options: HostBridgeOptions): HostBridge {\n const { parentOrigin = '*', gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n // Immediately signal ready to parent\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, players, leaderId } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'host') {\n console.error('[HostBridge] Received init for wrong side:', side);\n return;\n }\n\n // Create transport and wire up event handlers\n transport = new PostMessageTransport(parentOrigin);\n\n // Handle input events: {gameId}:input:{action}\n if (onInput) {\n Object.keys(onInput).forEach((action) => {\n const handler = onInput[action];\n transport!.on(`${gameId}:input:${action}`, (payload: any) => {\n const { playerId, data } = payload;\n handler(playerId, data);\n });\n });\n }\n\n // Handle player join/leave events\n if (onPlayerJoin) {\n transport.on('player:joined', (payload: any) => {\n onPlayerJoin(payload.sessionId);\n });\n }\n if (onPlayerLeave) {\n transport.on('player:left', (payload: any) => {\n onPlayerLeave(payload.sessionId);\n });\n }\n\n isInitialized = true;\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, players, leaderId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n broadcast: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot broadcast before init');\n return;\n }\n transport.emit(`${gameId}:broadcast:${event}`, data);\n },\n\n sendToPlayer: (playerId: string, event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot sendToPlayer before init');\n return;\n }\n transport.emit(`${gameId}:to-player:${event}`, { playerId, data });\n },\n\n emitGameOver: (results: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot emitGameOver before init');\n return;\n }\n transport.emit(`${gameId}:game-over`, results);\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n\nexport function createPlayerBridge(options: PlayerBridgeOptions): PlayerBridge {\n const { parentOrigin = '*', gameId, listeners, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n // Immediately signal ready to parent\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, mySessionId, isLeader } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'player') {\n console.error('[PlayerBridge] Received init for wrong side:', side);\n return;\n }\n\n if (!mySessionId) {\n console.error('[PlayerBridge] Missing mySessionId in init payload');\n return;\n }\n\n // Create transport and wire up listeners\n transport = new PostMessageTransport(parentOrigin);\n\n // Wire up game-specific event listeners\n if (listeners) {\n Object.keys(listeners).forEach((event) => {\n const handler = listeners[event];\n transport!.on(`${gameId}:${event}`, handler);\n });\n }\n\n isInitialized = true;\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, isLeader: !!isLeader, mySessionId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n emit: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot emit before init');\n return;\n }\n transport.emit(`${gameId}:${event}`, data);\n },\n\n onEvent: (event: string, handler: (data: any) => void) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot onEvent before init');\n return () => {};\n }\n transport.on(`${gameId}:${event}`, handler);\n return () => {\n transport?.off(`${gameId}:${event}`, handler);\n };\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n"],"names":["createContext","useContext","useState","useEffect","useMemo","jsx","useRef","useCallback"],"mappings":"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"}
@@ -374,6 +374,7 @@ function useGamePlayer(config) {
374
374
  function createHostBridge(options) {
375
375
  const { parentOrigin = "*", gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;
376
376
  let transport = null;
377
+ window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
377
378
  const messageHandler = (e) => {
378
379
  if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
379
380
  const msg = e.data;
@@ -404,7 +405,6 @@ function createHostBridge(options) {
404
405
  onPlayerLeave(payload.sessionId);
405
406
  });
406
407
  }
407
- window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
408
408
  if (onReady) {
409
409
  onReady({ roomCode, players, leaderId });
410
410
  }
@@ -443,6 +443,7 @@ function createHostBridge(options) {
443
443
  function createPlayerBridge(options) {
444
444
  const { parentOrigin = "*", gameId, listeners, onReady } = options;
445
445
  let transport = null;
446
+ window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
446
447
  const messageHandler = (e) => {
447
448
  if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
448
449
  const msg = e.data;
@@ -464,7 +465,6 @@ function createPlayerBridge(options) {
464
465
  transport.on(`${gameId}:${event}`, handler);
465
466
  });
466
467
  }
467
- window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
468
468
  if (onReady) {
469
469
  onReady({ roomCode, isLeader: !!isLeader, mySessionId });
470
470
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/transport/protocol.ts","../../../src/transport/PostMessageTransport.ts","../../../src/context/RoomProvider.tsx","../../../src/iframe/IframeRoomProvider.tsx","../../../src/hooks/useGameHost.ts","../../../src/hooks/useGamePlayer.ts","../../../src/iframe/vanilla.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n */\n\nexport const SMORE_MSG_PREFIX = 'smore:' as const;\n\nexport interface SmoreReadyMessage {\n type: 'smore:ready';\n}\n\nexport interface SmoreInitMessage {\n type: 'smore:init';\n payload: {\n side: 'host' | 'player';\n roomCode: string;\n players: any[];\n leaderId: string | null;\n mySessionId?: string;\n isLeader?: boolean;\n };\n}\n\nexport interface SmoreEmitMessage {\n type: 'smore:emit';\n payload: {\n event: string;\n data?: any;\n ackId?: string;\n };\n}\n\nexport interface SmoreEventMessage {\n type: 'smore:event';\n payload: {\n event: string;\n data?: any;\n };\n}\n\nexport interface SmoreAckMessage {\n type: 'smore:ack';\n payload: {\n ackId: string;\n data?: any;\n };\n}\n\nexport interface SmoreUpdateMessage {\n type: 'smore:update';\n payload: {\n players?: any[];\n leaderId?: string | null;\n };\n}\n\nexport type SmoreMessage =\n | SmoreReadyMessage\n | SmoreInitMessage\n | SmoreEmitMessage\n | SmoreEventMessage\n | SmoreAckMessage\n | SmoreUpdateMessage;\n\nexport function isSmoreMessage(data: any): data is SmoreMessage {\n return data && typeof data === 'object' && typeof data.type === 'string' && data.type.startsWith(SMORE_MSG_PREFIX);\n}\n","/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `smore:emit` to parent and listens for `smore:event` from parent.\n */\n\nimport type { Transport, TransportEventHandler } from './types';\nimport type { SmoreEventMessage, SmoreAckMessage } from './protocol';\nimport { isSmoreMessage } from './protocol';\n\nexport class PostMessageTransport implements Transport {\n private handlers = new Map<string, Set<TransportEventHandler>>();\n private ackCallbacks = new Map<string, (...args: any[]) => void>();\n private ackCounter = 0;\n private parentOrigin: string;\n private boundMessageHandler: (e: MessageEvent) => void;\n\n constructor(parentOrigin: string = '*') {\n this.parentOrigin = parentOrigin;\n this.boundMessageHandler = this.handleMessage.bind(this);\n window.addEventListener('message', this.boundMessageHandler);\n }\n\n emit(event: string, ...args: any[]): void {\n // Detect if last arg is a callback (ack pattern)\n let data: any = args[0];\n let ackId: string | undefined;\n\n if (args.length >= 2 && typeof args[args.length - 1] === 'function') {\n data = args.length === 2 ? args[0] : args[0];\n const callback = args[args.length - 1];\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event, data, ackId } },\n this.parentOrigin,\n );\n }\n\n on(event: string, handler: TransportEventHandler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler);\n }\n\n destroy(): void {\n window.removeEventListener('message', this.boundMessageHandler);\n this.handlers.clear();\n this.ackCallbacks.clear();\n }\n\n private handleMessage(e: MessageEvent): void {\n // Origin validation: only accept messages from the expected parent\n if (this.parentOrigin !== '*' && e.origin !== this.parentOrigin) return;\n\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:event') {\n const { event, data } = (msg as SmoreEventMessage).payload;\n const set = this.handlers.get(event);\n if (set) {\n set.forEach((handler) => handler(data));\n }\n } else if (msg.type === 'smore:ack') {\n const { ackId, data } = (msg as SmoreAckMessage).payload;\n const cb = this.ackCallbacks.get(ackId);\n if (cb) {\n this.ackCallbacks.delete(ackId);\n cb(data);\n }\n }\n }\n}\n","/**\n * RoomProvider - SDK Room Context\n *\n * Foundation context that all other SDK hooks depend on.\n * Provides room state (players, roomCode, leaderId) for both host and player sides.\n *\n * Also provides a Transport abstraction via TransportContext.\n * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.\n * - IframeRoomProvider (external) provides a PostMessageTransport.\n *\n * Usage:\n * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>\n * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} mySessionId={...} isLeader={...} socket={...} isConnected={...}>\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { Player } from '@smoregg/shared';\nimport type { Socket } from 'socket.io-client';\nimport type { Transport } from '../transport/types';\nimport { DirectTransport } from '../transport/DirectTransport';\n\n// ===== Transport Context =====\n\nconst TransportContext = createContext<Transport | null>(null);\n\nexport function useTransport(): Transport {\n const transport = useContext(TransportContext);\n if (!transport) {\n throw new Error('useTransport must be used within a RoomProvider that supplies a Transport');\n }\n return transport;\n}\n\nexport { TransportContext };\n\n// ===== State Types =====\n\nexport interface RoomState {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n}\n\nexport interface HostRoomState extends RoomState {\n socket: Socket;\n}\n\nexport interface PlayerRoomState extends RoomState {\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n}\n\nexport interface RoomContextValue {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n side: 'host' | 'player';\n host: HostRoomState | null;\n player: PlayerRoomState | null;\n}\n\n// ===== Context =====\n\nexport const RoomContext = createContext<RoomContextValue | null>(null);\n\n// ===== Host Provider =====\n\ninterface HostRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n socket: Socket;\n children: React.ReactNode;\n}\n\nexport const HostRoomProvider: React.FC<HostRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n socket,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const hostState: HostRoomState = useMemo(\n () => ({ roomCode, players, connectedPlayers, leaderId, socket }),\n [roomCode, players, connectedPlayers, leaderId, socket]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'host' as const,\n host: hostState,\n player: null,\n }),\n [roomCode, players, connectedPlayers, leaderId, hostState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Player Provider =====\n\ninterface PlayerRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n children: React.ReactNode;\n}\n\nexport const PlayerRoomProvider: React.FC<PlayerRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const playerState: PlayerRoomState = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n }),\n [roomCode, players, connectedPlayers, leaderId, mySessionId, isLeader, socket, isConnected]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'player' as const,\n host: null,\n player: playerState,\n }),\n [roomCode, players, connectedPlayers, leaderId, playerState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Hooks =====\n\nexport function useRoom(): RoomContextValue {\n const context = useContext(RoomContext);\n if (!context) {\n throw new Error('useRoom must be used within HostRoomProvider or PlayerRoomProvider');\n }\n return context;\n}\n\nexport function useHostRoom(): HostRoomState {\n const context = useRoom();\n if (context.side !== 'host' || !context.host) {\n throw new Error('useHostRoom must be used within HostRoomProvider');\n }\n return context.host;\n}\n\nexport function usePlayerRoom(): PlayerRoomState {\n const context = useRoom();\n if (context.side !== 'player' || !context.player) {\n throw new Error('usePlayerRoom must be used within PlayerRoomProvider');\n }\n return context.player;\n}\n","/**\n * IframeRoomProvider - Entry point for external (iframe-hosted) games.\n *\n * Usage inside an external game's iframe:\n * ```tsx\n * import { IframeRoomProvider } from '@smoregg/sdk/iframe';\n * import { useGameHost } from '@smoregg/sdk/iframe';\n *\n * function App() {\n * return (\n * <IframeRoomProvider>\n * <MyGame />\n * </IframeRoomProvider>\n * );\n * }\n * ```\n *\n * Lifecycle:\n * 1. Mount → sends `smore:ready` to parent\n * 2. Receives `smore:init` from parent with room state\n * 3. Creates PostMessageTransport\n * 4. Renders children with RoomContext + TransportContext\n */\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage } from '../transport/protocol';\nimport type { SmoreInitMessage } from '../transport/protocol';\nimport { TransportContext, RoomContext } from '../context/RoomProvider';\nimport type { RoomContextValue, HostRoomState, PlayerRoomState } from '../context/RoomProvider';\n\n// ===== Provider =====\n\ninterface IframeRoomProviderProps {\n children: React.ReactNode;\n parentOrigin?: string;\n}\n\nexport const IframeRoomProvider: React.FC<IframeRoomProviderProps> = ({ children, parentOrigin = '*' }) => {\n const [initData, setInitData] = useState<SmoreInitMessage['payload'] | null>(null);\n const [transport, setTransport] = useState<PostMessageTransport | null>(null);\n\n // Step 1: Send ready, listen for init\n useEffect(() => {\n const handler = (e: MessageEvent) => {\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n if (msg.type === 'smore:init') {\n setInitData(msg.payload);\n }\n };\n\n window.addEventListener('message', handler);\n\n // Signal readiness\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n return () => window.removeEventListener('message', handler);\n }, [parentOrigin]);\n\n // Step 2: Create transport once init arrives\n useEffect(() => {\n if (!initData) return;\n const t = new PostMessageTransport(parentOrigin);\n setTransport(t);\n return () => t.destroy();\n }, [initData, parentOrigin]);\n\n // Build room context value (uses the SAME RoomContext from RoomProvider)\n const roomContextValue = useMemo<RoomContextValue | null>(() => {\n if (!initData) return null;\n\n const { side, roomCode, players, leaderId, mySessionId, isLeader } = initData;\n const connectedPlayers = players.filter((p: any) => p.connected !== false);\n\n if (side === 'host') {\n const hostState: HostRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n socket: null as any, // Not available in iframe — use transport\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'host',\n host: hostState,\n player: null,\n };\n } else {\n const playerState: PlayerRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId: mySessionId || '',\n isLeader: isLeader || false,\n socket: null as any, // Not available in iframe — use transport\n isConnected: true,\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'player',\n host: null,\n player: playerState,\n };\n }\n }, [initData]);\n\n if (!initData || !transport || !roomContextValue) {\n return null; // Waiting for parent init\n }\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={roomContextValue}>\n {children}\n </RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n","/**\n * useGameHost - Host-side game hook for the S'MORE SDK\n *\n * Provides host game developers with:\n * - Automatic room state access (via useHostRoom context)\n * - Input listening (dedicated socket events)\n * - Broadcasting to all/specific players\n * - Game over emission\n * - Player lifecycle callbacks\n *\n * Internally uses Transport abstraction so the same API works over\n * Socket.IO (bundled games) or postMessage (iframe games).\n */\nimport { useEffect, useCallback, useRef } from 'react';\nimport { useHostRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { HostRoomState } from '../context/RoomProvider';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype InputHandler = (playerId: string, data?: any) => void;\n\nexport interface UseGameHostConfig {\n /** Unique game identifier (e.g. 'fibbage', 'wasd') */\n gameId: string;\n\n /**\n * Map of action names to handler functions.\n * Listens directly on socket for `{gameId}:{key}` events.\n */\n onInput?: Record<string, InputHandler>;\n\n /**\n * Called when a player requests game state (e.g. after returning from background).\n * Return the current game state object to send back to that player.\n */\n onStateRequest?: (playerId: string) => Record<string, any>;\n\n /** Called when a player leaves the room. */\n onPlayerLeave?: (playerId: string) => void;\n\n /** Called when a player disconnects (may reconnect). */\n onPlayerDisconnect?: (playerId: string) => void;\n\n /** Called when a previously disconnected player reconnects. */\n onPlayerReconnect?: (playerId: string) => void;\n\n /**\n * Generic socket event listeners (for server broadcasts the host needs to receive).\n * Keys are full event names, values are handler functions.\n */\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGameHostReturn {\n /** Current room state from HostRoomProvider context. */\n room: HostRoomState;\n\n /** Broadcast an event to all players via the host socket. */\n broadcast: (event: string, data: any) => void;\n\n /** Send state/event to a specific player by sessionId. */\n sendToPlayer: (sessionId: string, event: string, data: any) => void;\n\n /** Emit game-over with optional results payload. */\n emitGameOver: (results?: any) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useGameHost(config: UseGameHostConfig): UseGameHostReturn {\n const { gameId, onInput, onStateRequest, onPlayerLeave, onPlayerDisconnect, onPlayerReconnect, listeners } = config;\n\n const hostRoom = useHostRoom();\n const transport = useTransport();\n\n // Stable refs to avoid stale closures in listeners\n const onInputRef = useRef(onInput);\n const onStateRequestRef = useRef(onStateRequest);\n const onPlayerLeaveRef = useRef(onPlayerLeave);\n const onPlayerDisconnectRef = useRef(onPlayerDisconnect);\n const onPlayerReconnectRef = useRef(onPlayerReconnect);\n\n useEffect(() => { onInputRef.current = onInput; }, [onInput]);\n useEffect(() => { onStateRequestRef.current = onStateRequest; }, [onStateRequest]);\n useEffect(() => { onPlayerLeaveRef.current = onPlayerLeave; }, [onPlayerLeave]);\n useEffect(() => { onPlayerDisconnectRef.current = onPlayerDisconnect; }, [onPlayerDisconnect]);\n useEffect(() => { onPlayerReconnectRef.current = onPlayerReconnect; }, [onPlayerReconnect]);\n\n // -------------------------------------------------------------------------\n // Dedicated input listeners (transport events)\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport || !onInputRef.current) return;\n\n const registeredEvents: Array<{ event: string; handler: (...args: any[]) => void }> = [];\n\n // For each handler key, listen on transport for \"{gameId}:{key}\"\n const inputMap = onInputRef.current;\n for (const key of Object.keys(inputMap)) {\n const eventName = `${gameId}:${key}`;\n const handler = (data: any) => {\n const currentHandler = onInputRef.current?.[key];\n if (currentHandler) {\n currentHandler(data?.sessionId ?? data?.playerId, data);\n }\n };\n transport.on(eventName, handler);\n registeredEvents.push({ event: eventName, handler });\n }\n\n return () => {\n for (const { event, handler } of registeredEvents) {\n transport.off(event, handler);\n }\n };\n }, [gameId, transport]);\n\n // -------------------------------------------------------------------------\n // State request handler\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const handler = (data: { requesterId: string }) => {\n const stateFn = onStateRequestRef.current;\n if (!stateFn) return;\n\n const gameState = stateFn(data.requesterId);\n transport.emit('game:state-response', {\n targetSessionId: data.requesterId,\n gameState: {\n gameId,\n ...gameState,\n },\n });\n };\n\n transport.on('game:state-request', handler);\n return () => {\n transport.off('game:state-request', handler);\n };\n }, [transport, gameId]);\n\n // -------------------------------------------------------------------------\n // Player lifecycle listeners\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const onLeft = (data: any) => {\n onPlayerLeaveRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onDisconnected = (data: any) => {\n onPlayerDisconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onReconnected = (data: any) => {\n onPlayerReconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n\n transport.on('room:player-left', onLeft);\n transport.on('room:player-disconnected', onDisconnected);\n transport.on('room:player-reconnected', onReconnected);\n\n return () => {\n transport.off('room:player-left', onLeft);\n transport.off('room:player-disconnected', onDisconnected);\n transport.off('room:player-reconnected', onReconnected);\n };\n }, [transport]);\n\n // -------------------------------------------------------------------------\n // Generic listeners\n // -------------------------------------------------------------------------\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const entries = Object.entries(listenersRef.current);\n const handlers = entries.map(([event, handler]) => {\n transport.on(event, handler);\n return () => { transport.off(event, handler); };\n });\n return () => handlers.forEach(fn => fn());\n }, [transport, listeners]);\n\n // -------------------------------------------------------------------------\n // Actions\n // -------------------------------------------------------------------------\n\n const broadcast = useCallback(\n (event: string, data: any) => {\n transport?.emit(event, data);\n },\n [transport],\n );\n\n const sendToPlayer = useCallback(\n (sessionId: string, event: string, data: any) => {\n transport?.emit('game:state-to-player', {\n targetSessionId: sessionId,\n gameId,\n event,\n state: data,\n });\n },\n [transport, gameId],\n );\n\n const emitGameOver = useCallback(\n (results?: any) => {\n transport?.emit('room:game-over', { gameId, results });\n },\n [transport, gameId],\n );\n\n return {\n room: hostRoom,\n broadcast,\n sendToPlayer,\n emitGameOver,\n };\n}\n","import { useEffect, useCallback, useState, useRef } from 'react';\nimport { usePlayerRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { PlayerRoomState } from '../context/RoomProvider';\n\nexport interface UseGamePlayerConfig {\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGamePlayerReturn {\n room: PlayerRoomState;\n emit: (event: string, data?: any, callback?: (response: any) => void) => void;\n /** Emit a tap input: sends `{gameId}:{action}` event */\n sendTapInput: (action: string) => void;\n /** Emit a hold input: sends `{gameId}:{action}:{type}` event */\n sendHoldInput: (action: string, type: 'START' | 'END') => void;\n isConnected: boolean;\n gameState: Record<string, any> | null;\n}\n\nexport function useGamePlayer(config: UseGamePlayerConfig): UseGamePlayerReturn {\n const room = usePlayerRoom();\n const transport = useTransport();\n const { isConnected } = room;\n const { gameId, listeners } = config;\n const [gameState, setGameState] = useState<Record<string, any> | null>(null);\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n // Transport listeners\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const cleanups: (() => void)[] = [];\n Object.entries(listenersRef.current).forEach(([event, handler]) => {\n transport.on(event, handler);\n cleanups.push(() => transport.off(event, handler));\n });\n return () => cleanups.forEach(fn => fn());\n }, [transport, listeners]);\n\n // Reconnection: game:state-response\n useEffect(() => {\n if (!transport) return;\n const handler = (state: any) => {\n if (state.gameId !== gameId) return;\n setGameState(state);\n };\n transport.on('game:state-response', handler);\n return () => { transport.off('game:state-response', handler); };\n }, [transport, gameId]);\n\n // game:state-to-player (Host push)\n useEffect(() => {\n if (!transport) return;\n const handler = (data: { gameId: string; state: any }) => {\n if (data.gameId !== gameId) return;\n setGameState(data.state);\n };\n transport.on('game:state-to-player', handler);\n return () => { transport.off('game:state-to-player', handler); };\n }, [transport, gameId]);\n\n // Visibility change\n useEffect(() => {\n if (!transport) return;\n const handler = () => {\n if (!document.hidden) {\n transport.emit('game:request-state', { gameId });\n }\n };\n document.addEventListener('visibilitychange', handler);\n return () => document.removeEventListener('visibilitychange', handler);\n }, [transport, gameId]);\n\n // API\n const emit = useCallback((event: string, data?: any, callback?: (response: any) => void) => {\n if (!transport) return;\n if (callback) {\n transport.emit(event, data, callback);\n } else {\n transport.emit(event, data);\n }\n }, [transport]);\n\n const sendTapInput = useCallback((action: string) => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}`);\n }, [transport, gameId]);\n\n const sendHoldInput = useCallback((action: string, type: 'START' | 'END') => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}:${type}`);\n }, [transport, gameId]);\n\n return { room, emit, sendTapInput, sendHoldInput, isConnected, gameState };\n}\n","/**\n * Vanilla JS bridge API for iframe-hosted games.\n * No React - pure JavaScript with PostMessage transport.\n */\n\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage, type SmoreInitMessage } from '../transport/protocol';\n\nexport interface HostBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n onInput?: Record<string, (playerId: string, data: any) => void>;\n onPlayerJoin?: (playerId: string) => void;\n onPlayerLeave?: (playerId: string) => void;\n onReady?: (room: { roomCode: string; players: any[]; leaderId: string | null }) => void;\n}\n\nexport interface HostBridge {\n broadcast: (event: string, data?: any) => void;\n sendToPlayer: (playerId: string, event: string, data?: any) => void;\n emitGameOver: (results: any) => void;\n destroy: () => void;\n}\n\nexport interface PlayerBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n onReady?: (room: { roomCode: string; isLeader: boolean; mySessionId: string }) => void;\n}\n\nexport interface PlayerBridge {\n emit: (event: string, data?: any) => void;\n onEvent: (event: string, handler: (data: any) => void) => () => void;\n destroy: () => void;\n}\n\nexport function createHostBridge(options: HostBridgeOptions): HostBridge {\n const { parentOrigin = '*', gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, players, leaderId } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'host') {\n console.error('[HostBridge] Received init for wrong side:', side);\n return;\n }\n\n // Create transport and wire up event handlers\n transport = new PostMessageTransport(parentOrigin);\n\n // Handle input events: {gameId}:input:{action}\n if (onInput) {\n Object.keys(onInput).forEach((action) => {\n const handler = onInput[action];\n transport!.on(`${gameId}:input:${action}`, (payload: any) => {\n const { playerId, data } = payload;\n handler(playerId, data);\n });\n });\n }\n\n // Handle player join/leave events\n if (onPlayerJoin) {\n transport.on('player:joined', (payload: any) => {\n onPlayerJoin(payload.sessionId);\n });\n }\n if (onPlayerLeave) {\n transport.on('player:left', (payload: any) => {\n onPlayerLeave(payload.sessionId);\n });\n }\n\n isInitialized = true;\n\n // Notify parent we're ready\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, players, leaderId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n broadcast: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot broadcast before init');\n return;\n }\n transport.emit(`${gameId}:broadcast:${event}`, data);\n },\n\n sendToPlayer: (playerId: string, event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot sendToPlayer before init');\n return;\n }\n transport.emit(`${gameId}:to-player:${event}`, { playerId, data });\n },\n\n emitGameOver: (results: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot emitGameOver before init');\n return;\n }\n transport.emit(`${gameId}:game-over`, results);\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n\nexport function createPlayerBridge(options: PlayerBridgeOptions): PlayerBridge {\n const { parentOrigin = '*', gameId, listeners, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, mySessionId, isLeader } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'player') {\n console.error('[PlayerBridge] Received init for wrong side:', side);\n return;\n }\n\n if (!mySessionId) {\n console.error('[PlayerBridge] Missing mySessionId in init payload');\n return;\n }\n\n // Create transport and wire up listeners\n transport = new PostMessageTransport(parentOrigin);\n\n // Wire up game-specific event listeners\n if (listeners) {\n Object.keys(listeners).forEach((event) => {\n const handler = listeners[event];\n transport!.on(`${gameId}:${event}`, handler);\n });\n }\n\n isInitialized = true;\n\n // Notify parent we're ready\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, isLeader: !!isLeader, mySessionId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n emit: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot emit before init');\n return;\n }\n transport.emit(`${gameId}:${event}`, data);\n },\n\n onEvent: (event: string, handler: (data: any) => void) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot onEvent before init');\n return () => {};\n }\n transport.on(`${gameId}:${event}`, handler);\n return () => {\n transport?.off(`${gameId}:${event}`, handler);\n };\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/transport/protocol.ts","../../../src/transport/PostMessageTransport.ts","../../../src/context/RoomProvider.tsx","../../../src/iframe/IframeRoomProvider.tsx","../../../src/hooks/useGameHost.ts","../../../src/hooks/useGamePlayer.ts","../../../src/iframe/vanilla.ts"],"sourcesContent":["/**\n * postMessage protocol types for iframe ↔ parent communication.\n */\n\nexport const SMORE_MSG_PREFIX = 'smore:' as const;\n\nexport interface SmoreReadyMessage {\n type: 'smore:ready';\n}\n\nexport interface SmoreInitMessage {\n type: 'smore:init';\n payload: {\n side: 'host' | 'player';\n roomCode: string;\n players: any[];\n leaderId: string | null;\n mySessionId?: string;\n isLeader?: boolean;\n };\n}\n\nexport interface SmoreEmitMessage {\n type: 'smore:emit';\n payload: {\n event: string;\n data?: any;\n ackId?: string;\n };\n}\n\nexport interface SmoreEventMessage {\n type: 'smore:event';\n payload: {\n event: string;\n data?: any;\n };\n}\n\nexport interface SmoreAckMessage {\n type: 'smore:ack';\n payload: {\n ackId: string;\n data?: any;\n };\n}\n\nexport interface SmoreUpdateMessage {\n type: 'smore:update';\n payload: {\n players?: any[];\n leaderId?: string | null;\n };\n}\n\nexport type SmoreMessage =\n | SmoreReadyMessage\n | SmoreInitMessage\n | SmoreEmitMessage\n | SmoreEventMessage\n | SmoreAckMessage\n | SmoreUpdateMessage;\n\nexport function isSmoreMessage(data: any): data is SmoreMessage {\n return data && typeof data === 'object' && typeof data.type === 'string' && data.type.startsWith(SMORE_MSG_PREFIX);\n}\n","/**\n * PostMessageTransport - Transport over window.postMessage for iframe-hosted games.\n *\n * Used inside an iframe. Sends `smore:emit` to parent and listens for `smore:event` from parent.\n */\n\nimport type { Transport, TransportEventHandler } from './types';\nimport type { SmoreEventMessage, SmoreAckMessage } from './protocol';\nimport { isSmoreMessage } from './protocol';\n\nexport class PostMessageTransport implements Transport {\n private handlers = new Map<string, Set<TransportEventHandler>>();\n private ackCallbacks = new Map<string, (...args: any[]) => void>();\n private ackCounter = 0;\n private parentOrigin: string;\n private boundMessageHandler: (e: MessageEvent) => void;\n\n constructor(parentOrigin: string = '*') {\n this.parentOrigin = parentOrigin;\n this.boundMessageHandler = this.handleMessage.bind(this);\n window.addEventListener('message', this.boundMessageHandler);\n }\n\n emit(event: string, ...args: any[]): void {\n // Detect if last arg is a callback (ack pattern)\n let data: any = args[0];\n let ackId: string | undefined;\n\n if (args.length >= 2 && typeof args[args.length - 1] === 'function') {\n data = args.length === 2 ? args[0] : args[0];\n const callback = args[args.length - 1];\n ackId = `ack_${++this.ackCounter}`;\n this.ackCallbacks.set(ackId, callback);\n }\n\n window.parent.postMessage(\n { type: 'smore:emit', payload: { event, data, ackId } },\n this.parentOrigin,\n );\n }\n\n on(event: string, handler: TransportEventHandler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (!handler) {\n this.handlers.delete(event);\n return;\n }\n this.handlers.get(event)?.delete(handler);\n }\n\n destroy(): void {\n window.removeEventListener('message', this.boundMessageHandler);\n this.handlers.clear();\n this.ackCallbacks.clear();\n }\n\n private handleMessage(e: MessageEvent): void {\n // Origin validation: only accept messages from the expected parent\n if (this.parentOrigin !== '*' && e.origin !== this.parentOrigin) return;\n\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:event') {\n const { event, data } = (msg as SmoreEventMessage).payload;\n const set = this.handlers.get(event);\n if (set) {\n set.forEach((handler) => handler(data));\n }\n } else if (msg.type === 'smore:ack') {\n const { ackId, data } = (msg as SmoreAckMessage).payload;\n const cb = this.ackCallbacks.get(ackId);\n if (cb) {\n this.ackCallbacks.delete(ackId);\n cb(data);\n }\n }\n }\n}\n","/**\n * RoomProvider - SDK Room Context\n *\n * Foundation context that all other SDK hooks depend on.\n * Provides room state (players, roomCode, leaderId) for both host and player sides.\n *\n * Also provides a Transport abstraction via TransportContext.\n * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.\n * - IframeRoomProvider (external) provides a PostMessageTransport.\n *\n * Usage:\n * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>\n * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} mySessionId={...} isLeader={...} socket={...} isConnected={...}>\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { Player } from '@smoregg/shared';\nimport type { Socket } from 'socket.io-client';\nimport type { Transport } from '../transport/types';\nimport { DirectTransport } from '../transport/DirectTransport';\n\n// ===== Transport Context =====\n\nconst TransportContext = createContext<Transport | null>(null);\n\nexport function useTransport(): Transport {\n const transport = useContext(TransportContext);\n if (!transport) {\n throw new Error('useTransport must be used within a RoomProvider that supplies a Transport');\n }\n return transport;\n}\n\nexport { TransportContext };\n\n// ===== State Types =====\n\nexport interface RoomState {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n}\n\nexport interface HostRoomState extends RoomState {\n socket: Socket;\n}\n\nexport interface PlayerRoomState extends RoomState {\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n}\n\nexport interface RoomContextValue {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n side: 'host' | 'player';\n host: HostRoomState | null;\n player: PlayerRoomState | null;\n}\n\n// ===== Context =====\n\nexport const RoomContext = createContext<RoomContextValue | null>(null);\n\n// ===== Host Provider =====\n\ninterface HostRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n socket: Socket;\n children: React.ReactNode;\n}\n\nexport const HostRoomProvider: React.FC<HostRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n socket,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const hostState: HostRoomState = useMemo(\n () => ({ roomCode, players, connectedPlayers, leaderId, socket }),\n [roomCode, players, connectedPlayers, leaderId, socket]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'host' as const,\n host: hostState,\n player: null,\n }),\n [roomCode, players, connectedPlayers, leaderId, hostState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Player Provider =====\n\ninterface PlayerRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n children: React.ReactNode;\n}\n\nexport const PlayerRoomProvider: React.FC<PlayerRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const playerState: PlayerRoomState = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n }),\n [roomCode, players, connectedPlayers, leaderId, mySessionId, isLeader, socket, isConnected]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'player' as const,\n host: null,\n player: playerState,\n }),\n [roomCode, players, connectedPlayers, leaderId, playerState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Hooks =====\n\nexport function useRoom(): RoomContextValue {\n const context = useContext(RoomContext);\n if (!context) {\n throw new Error('useRoom must be used within HostRoomProvider or PlayerRoomProvider');\n }\n return context;\n}\n\nexport function useHostRoom(): HostRoomState {\n const context = useRoom();\n if (context.side !== 'host' || !context.host) {\n throw new Error('useHostRoom must be used within HostRoomProvider');\n }\n return context.host;\n}\n\nexport function usePlayerRoom(): PlayerRoomState {\n const context = useRoom();\n if (context.side !== 'player' || !context.player) {\n throw new Error('usePlayerRoom must be used within PlayerRoomProvider');\n }\n return context.player;\n}\n","/**\n * IframeRoomProvider - Entry point for external (iframe-hosted) games.\n *\n * Usage inside an external game's iframe:\n * ```tsx\n * import { IframeRoomProvider } from '@smoregg/sdk/iframe';\n * import { useGameHost } from '@smoregg/sdk/iframe';\n *\n * function App() {\n * return (\n * <IframeRoomProvider>\n * <MyGame />\n * </IframeRoomProvider>\n * );\n * }\n * ```\n *\n * Lifecycle:\n * 1. Mount → sends `smore:ready` to parent\n * 2. Receives `smore:init` from parent with room state\n * 3. Creates PostMessageTransport\n * 4. Renders children with RoomContext + TransportContext\n */\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage } from '../transport/protocol';\nimport type { SmoreInitMessage } from '../transport/protocol';\nimport { TransportContext, RoomContext } from '../context/RoomProvider';\nimport type { RoomContextValue, HostRoomState, PlayerRoomState } from '../context/RoomProvider';\n\n// ===== Provider =====\n\ninterface IframeRoomProviderProps {\n children: React.ReactNode;\n parentOrigin?: string;\n}\n\nexport const IframeRoomProvider: React.FC<IframeRoomProviderProps> = ({ children, parentOrigin = '*' }) => {\n const [initData, setInitData] = useState<SmoreInitMessage['payload'] | null>(null);\n const [transport, setTransport] = useState<PostMessageTransport | null>(null);\n\n // Step 1: Send ready, listen for init\n useEffect(() => {\n const handler = (e: MessageEvent) => {\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n if (msg.type === 'smore:init') {\n setInitData(msg.payload);\n }\n };\n\n window.addEventListener('message', handler);\n\n // Signal readiness\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n return () => window.removeEventListener('message', handler);\n }, [parentOrigin]);\n\n // Step 2: Create transport once init arrives\n useEffect(() => {\n if (!initData) return;\n const t = new PostMessageTransport(parentOrigin);\n setTransport(t);\n return () => t.destroy();\n }, [initData, parentOrigin]);\n\n // Build room context value (uses the SAME RoomContext from RoomProvider)\n const roomContextValue = useMemo<RoomContextValue | null>(() => {\n if (!initData) return null;\n\n const { side, roomCode, players, leaderId, mySessionId, isLeader } = initData;\n const connectedPlayers = players.filter((p: any) => p.connected !== false);\n\n if (side === 'host') {\n const hostState: HostRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n socket: null as any, // Not available in iframe — use transport\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'host',\n host: hostState,\n player: null,\n };\n } else {\n const playerState: PlayerRoomState = {\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId: mySessionId || '',\n isLeader: isLeader || false,\n socket: null as any, // Not available in iframe — use transport\n isConnected: true,\n };\n return {\n roomCode, players, connectedPlayers, leaderId,\n side: 'player',\n host: null,\n player: playerState,\n };\n }\n }, [initData]);\n\n if (!initData || !transport || !roomContextValue) {\n return null; // Waiting for parent init\n }\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={roomContextValue}>\n {children}\n </RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n","/**\n * useGameHost - Host-side game hook for the S'MORE SDK\n *\n * Provides host game developers with:\n * - Automatic room state access (via useHostRoom context)\n * - Input listening (dedicated socket events)\n * - Broadcasting to all/specific players\n * - Game over emission\n * - Player lifecycle callbacks\n *\n * Internally uses Transport abstraction so the same API works over\n * Socket.IO (bundled games) or postMessage (iframe games).\n */\nimport { useEffect, useCallback, useRef } from 'react';\nimport { useHostRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { HostRoomState } from '../context/RoomProvider';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype InputHandler = (playerId: string, data?: any) => void;\n\nexport interface UseGameHostConfig {\n /** Unique game identifier (e.g. 'fibbage', 'wasd') */\n gameId: string;\n\n /**\n * Map of action names to handler functions.\n * Listens directly on socket for `{gameId}:{key}` events.\n */\n onInput?: Record<string, InputHandler>;\n\n /**\n * Called when a player requests game state (e.g. after returning from background).\n * Return the current game state object to send back to that player.\n */\n onStateRequest?: (playerId: string) => Record<string, any>;\n\n /** Called when a player leaves the room. */\n onPlayerLeave?: (playerId: string) => void;\n\n /** Called when a player disconnects (may reconnect). */\n onPlayerDisconnect?: (playerId: string) => void;\n\n /** Called when a previously disconnected player reconnects. */\n onPlayerReconnect?: (playerId: string) => void;\n\n /**\n * Generic socket event listeners (for server broadcasts the host needs to receive).\n * Keys are full event names, values are handler functions.\n */\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGameHostReturn {\n /** Current room state from HostRoomProvider context. */\n room: HostRoomState;\n\n /** Broadcast an event to all players via the host socket. */\n broadcast: (event: string, data: any) => void;\n\n /** Send state/event to a specific player by sessionId. */\n sendToPlayer: (sessionId: string, event: string, data: any) => void;\n\n /** Emit game-over with optional results payload. */\n emitGameOver: (results?: any) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useGameHost(config: UseGameHostConfig): UseGameHostReturn {\n const { gameId, onInput, onStateRequest, onPlayerLeave, onPlayerDisconnect, onPlayerReconnect, listeners } = config;\n\n const hostRoom = useHostRoom();\n const transport = useTransport();\n\n // Stable refs to avoid stale closures in listeners\n const onInputRef = useRef(onInput);\n const onStateRequestRef = useRef(onStateRequest);\n const onPlayerLeaveRef = useRef(onPlayerLeave);\n const onPlayerDisconnectRef = useRef(onPlayerDisconnect);\n const onPlayerReconnectRef = useRef(onPlayerReconnect);\n\n useEffect(() => { onInputRef.current = onInput; }, [onInput]);\n useEffect(() => { onStateRequestRef.current = onStateRequest; }, [onStateRequest]);\n useEffect(() => { onPlayerLeaveRef.current = onPlayerLeave; }, [onPlayerLeave]);\n useEffect(() => { onPlayerDisconnectRef.current = onPlayerDisconnect; }, [onPlayerDisconnect]);\n useEffect(() => { onPlayerReconnectRef.current = onPlayerReconnect; }, [onPlayerReconnect]);\n\n // -------------------------------------------------------------------------\n // Dedicated input listeners (transport events)\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport || !onInputRef.current) return;\n\n const registeredEvents: Array<{ event: string; handler: (...args: any[]) => void }> = [];\n\n // For each handler key, listen on transport for \"{gameId}:{key}\"\n const inputMap = onInputRef.current;\n for (const key of Object.keys(inputMap)) {\n const eventName = `${gameId}:${key}`;\n const handler = (data: any) => {\n const currentHandler = onInputRef.current?.[key];\n if (currentHandler) {\n currentHandler(data?.sessionId ?? data?.playerId, data);\n }\n };\n transport.on(eventName, handler);\n registeredEvents.push({ event: eventName, handler });\n }\n\n return () => {\n for (const { event, handler } of registeredEvents) {\n transport.off(event, handler);\n }\n };\n }, [gameId, transport]);\n\n // -------------------------------------------------------------------------\n // State request handler\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const handler = (data: { requesterId: string }) => {\n const stateFn = onStateRequestRef.current;\n if (!stateFn) return;\n\n const gameState = stateFn(data.requesterId);\n transport.emit('game:state-response', {\n targetSessionId: data.requesterId,\n gameState: {\n gameId,\n ...gameState,\n },\n });\n };\n\n transport.on('game:state-request', handler);\n return () => {\n transport.off('game:state-request', handler);\n };\n }, [transport, gameId]);\n\n // -------------------------------------------------------------------------\n // Player lifecycle listeners\n // -------------------------------------------------------------------------\n useEffect(() => {\n if (!transport) return;\n\n const onLeft = (data: any) => {\n onPlayerLeaveRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onDisconnected = (data: any) => {\n onPlayerDisconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n const onReconnected = (data: any) => {\n onPlayerReconnectRef.current?.(data?.sessionId ?? data?.playerId);\n };\n\n transport.on('room:player-left', onLeft);\n transport.on('room:player-disconnected', onDisconnected);\n transport.on('room:player-reconnected', onReconnected);\n\n return () => {\n transport.off('room:player-left', onLeft);\n transport.off('room:player-disconnected', onDisconnected);\n transport.off('room:player-reconnected', onReconnected);\n };\n }, [transport]);\n\n // -------------------------------------------------------------------------\n // Generic listeners\n // -------------------------------------------------------------------------\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const entries = Object.entries(listenersRef.current);\n const handlers = entries.map(([event, handler]) => {\n transport.on(event, handler);\n return () => { transport.off(event, handler); };\n });\n return () => handlers.forEach(fn => fn());\n }, [transport, listeners]);\n\n // -------------------------------------------------------------------------\n // Actions\n // -------------------------------------------------------------------------\n\n const broadcast = useCallback(\n (event: string, data: any) => {\n transport?.emit(event, data);\n },\n [transport],\n );\n\n const sendToPlayer = useCallback(\n (sessionId: string, event: string, data: any) => {\n transport?.emit('game:state-to-player', {\n targetSessionId: sessionId,\n gameId,\n event,\n state: data,\n });\n },\n [transport, gameId],\n );\n\n const emitGameOver = useCallback(\n (results?: any) => {\n transport?.emit('room:game-over', { gameId, results });\n },\n [transport, gameId],\n );\n\n return {\n room: hostRoom,\n broadcast,\n sendToPlayer,\n emitGameOver,\n };\n}\n","import { useEffect, useCallback, useState, useRef } from 'react';\nimport { usePlayerRoom } from '../context/RoomProvider';\nimport { useTransport } from '../context/RoomProvider';\nimport type { PlayerRoomState } from '../context/RoomProvider';\n\nexport interface UseGamePlayerConfig {\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n}\n\nexport interface UseGamePlayerReturn {\n room: PlayerRoomState;\n emit: (event: string, data?: any, callback?: (response: any) => void) => void;\n /** Emit a tap input: sends `{gameId}:{action}` event */\n sendTapInput: (action: string) => void;\n /** Emit a hold input: sends `{gameId}:{action}:{type}` event */\n sendHoldInput: (action: string, type: 'START' | 'END') => void;\n isConnected: boolean;\n gameState: Record<string, any> | null;\n}\n\nexport function useGamePlayer(config: UseGamePlayerConfig): UseGamePlayerReturn {\n const room = usePlayerRoom();\n const transport = useTransport();\n const { isConnected } = room;\n const { gameId, listeners } = config;\n const [gameState, setGameState] = useState<Record<string, any> | null>(null);\n const listenersRef = useRef(listeners);\n listenersRef.current = listeners;\n\n // Transport listeners\n useEffect(() => {\n if (!transport || !listenersRef.current) return;\n const cleanups: (() => void)[] = [];\n Object.entries(listenersRef.current).forEach(([event, handler]) => {\n transport.on(event, handler);\n cleanups.push(() => transport.off(event, handler));\n });\n return () => cleanups.forEach(fn => fn());\n }, [transport, listeners]);\n\n // Reconnection: game:state-response\n useEffect(() => {\n if (!transport) return;\n const handler = (state: any) => {\n if (state.gameId !== gameId) return;\n setGameState(state);\n };\n transport.on('game:state-response', handler);\n return () => { transport.off('game:state-response', handler); };\n }, [transport, gameId]);\n\n // game:state-to-player (Host push)\n useEffect(() => {\n if (!transport) return;\n const handler = (data: { gameId: string; state: any }) => {\n if (data.gameId !== gameId) return;\n setGameState(data.state);\n };\n transport.on('game:state-to-player', handler);\n return () => { transport.off('game:state-to-player', handler); };\n }, [transport, gameId]);\n\n // Visibility change\n useEffect(() => {\n if (!transport) return;\n const handler = () => {\n if (!document.hidden) {\n transport.emit('game:request-state', { gameId });\n }\n };\n document.addEventListener('visibilitychange', handler);\n return () => document.removeEventListener('visibilitychange', handler);\n }, [transport, gameId]);\n\n // API\n const emit = useCallback((event: string, data?: any, callback?: (response: any) => void) => {\n if (!transport) return;\n if (callback) {\n transport.emit(event, data, callback);\n } else {\n transport.emit(event, data);\n }\n }, [transport]);\n\n const sendTapInput = useCallback((action: string) => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}`);\n }, [transport, gameId]);\n\n const sendHoldInput = useCallback((action: string, type: 'START' | 'END') => {\n if (!transport) return;\n transport.emit(`${gameId}:${action}:${type}`);\n }, [transport, gameId]);\n\n return { room, emit, sendTapInput, sendHoldInput, isConnected, gameState };\n}\n","/**\n * Vanilla JS bridge API for iframe-hosted games.\n * No React - pure JavaScript with PostMessage transport.\n */\n\nimport { PostMessageTransport } from '../transport/PostMessageTransport';\nimport { isSmoreMessage, type SmoreInitMessage } from '../transport/protocol';\n\nexport interface HostBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n onInput?: Record<string, (playerId: string, data: any) => void>;\n onPlayerJoin?: (playerId: string) => void;\n onPlayerLeave?: (playerId: string) => void;\n onReady?: (room: { roomCode: string; players: any[]; leaderId: string | null }) => void;\n}\n\nexport interface HostBridge {\n broadcast: (event: string, data?: any) => void;\n sendToPlayer: (playerId: string, event: string, data?: any) => void;\n emitGameOver: (results: any) => void;\n destroy: () => void;\n}\n\nexport interface PlayerBridgeOptions {\n parentOrigin?: string;\n gameId: string;\n listeners?: Record<string, (data: any) => void>;\n onReady?: (room: { roomCode: string; isLeader: boolean; mySessionId: string }) => void;\n}\n\nexport interface PlayerBridge {\n emit: (event: string, data?: any) => void;\n onEvent: (event: string, handler: (data: any) => void) => () => void;\n destroy: () => void;\n}\n\nexport function createHostBridge(options: HostBridgeOptions): HostBridge {\n const { parentOrigin = '*', gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n // Immediately signal ready to parent\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, players, leaderId } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'host') {\n console.error('[HostBridge] Received init for wrong side:', side);\n return;\n }\n\n // Create transport and wire up event handlers\n transport = new PostMessageTransport(parentOrigin);\n\n // Handle input events: {gameId}:input:{action}\n if (onInput) {\n Object.keys(onInput).forEach((action) => {\n const handler = onInput[action];\n transport!.on(`${gameId}:input:${action}`, (payload: any) => {\n const { playerId, data } = payload;\n handler(playerId, data);\n });\n });\n }\n\n // Handle player join/leave events\n if (onPlayerJoin) {\n transport.on('player:joined', (payload: any) => {\n onPlayerJoin(payload.sessionId);\n });\n }\n if (onPlayerLeave) {\n transport.on('player:left', (payload: any) => {\n onPlayerLeave(payload.sessionId);\n });\n }\n\n isInitialized = true;\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, players, leaderId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n broadcast: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot broadcast before init');\n return;\n }\n transport.emit(`${gameId}:broadcast:${event}`, data);\n },\n\n sendToPlayer: (playerId: string, event: string, data?: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot sendToPlayer before init');\n return;\n }\n transport.emit(`${gameId}:to-player:${event}`, { playerId, data });\n },\n\n emitGameOver: (results: any) => {\n if (!transport) {\n console.warn('[HostBridge] Cannot emitGameOver before init');\n return;\n }\n transport.emit(`${gameId}:game-over`, results);\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n\nexport function createPlayerBridge(options: PlayerBridgeOptions): PlayerBridge {\n const { parentOrigin = '*', gameId, listeners, onReady } = options;\n\n let transport: PostMessageTransport | null = null;\n let isInitialized = false;\n\n // Immediately signal ready to parent\n window.parent.postMessage({ type: 'smore:ready' }, parentOrigin);\n\n const messageHandler = (e: MessageEvent) => {\n if (parentOrigin !== '*' && e.origin !== parentOrigin) return;\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:init') {\n const { side, roomCode, mySessionId, isLeader } = (msg as SmoreInitMessage).payload;\n\n if (side !== 'player') {\n console.error('[PlayerBridge] Received init for wrong side:', side);\n return;\n }\n\n if (!mySessionId) {\n console.error('[PlayerBridge] Missing mySessionId in init payload');\n return;\n }\n\n // Create transport and wire up listeners\n transport = new PostMessageTransport(parentOrigin);\n\n // Wire up game-specific event listeners\n if (listeners) {\n Object.keys(listeners).forEach((event) => {\n const handler = listeners[event];\n transport!.on(`${gameId}:${event}`, handler);\n });\n }\n\n isInitialized = true;\n\n // Call onReady callback\n if (onReady) {\n onReady({ roomCode, isLeader: !!isLeader, mySessionId });\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n return {\n emit: (event: string, data?: any) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot emit before init');\n return;\n }\n transport.emit(`${gameId}:${event}`, data);\n },\n\n onEvent: (event: string, handler: (data: any) => void) => {\n if (!transport) {\n console.warn('[PlayerBridge] Cannot onEvent before init');\n return () => {};\n }\n transport.on(`${gameId}:${event}`, handler);\n return () => {\n transport?.off(`${gameId}:${event}`, handler);\n };\n },\n\n destroy: () => {\n window.removeEventListener('message', messageHandler);\n transport?.destroy();\n transport = null;\n isInitialized = false;\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -377,6 +377,7 @@
377
377
  function createHostBridge(options) {
378
378
  const { parentOrigin = "*", gameId, onInput, onPlayerJoin, onPlayerLeave, onReady } = options;
379
379
  let transport = null;
380
+ window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
380
381
  const messageHandler = (e) => {
381
382
  if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
382
383
  const msg = e.data;
@@ -407,7 +408,6 @@
407
408
  onPlayerLeave(payload.sessionId);
408
409
  });
409
410
  }
410
- window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
411
411
  if (onReady) {
412
412
  onReady({ roomCode, players, leaderId });
413
413
  }
@@ -446,6 +446,7 @@
446
446
  function createPlayerBridge(options) {
447
447
  const { parentOrigin = "*", gameId, listeners, onReady } = options;
448
448
  let transport = null;
449
+ window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
449
450
  const messageHandler = (e) => {
450
451
  if (parentOrigin !== "*" && e.origin !== parentOrigin) return;
451
452
  const msg = e.data;
@@ -467,7 +468,6 @@
467
468
  transport.on(`${gameId}:${event}`, handler);
468
469
  });
469
470
  }
470
- window.parent.postMessage({ type: "smore:ready" }, parentOrigin);
471
471
  if (onReady) {
472
472
  onReady({ roomCode, isLeader: !!isLeader, mySessionId });
473
473
  }