@smoregg/sdk 0.1.0

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.
Files changed (137) hide show
  1. package/dist/cjs/components/DirectionPad.cjs +68 -0
  2. package/dist/cjs/components/DirectionPad.cjs.map +1 -0
  3. package/dist/cjs/components/DirectionPad.module.css.cjs +12 -0
  4. package/dist/cjs/components/DirectionPad.module.css.cjs.map +1 -0
  5. package/dist/cjs/components/HoldButton.cjs +57 -0
  6. package/dist/cjs/components/HoldButton.cjs.map +1 -0
  7. package/dist/cjs/components/HoldButton.module.css.cjs +12 -0
  8. package/dist/cjs/components/HoldButton.module.css.cjs.map +1 -0
  9. package/dist/cjs/components/SwipeArea.cjs +58 -0
  10. package/dist/cjs/components/SwipeArea.cjs.map +1 -0
  11. package/dist/cjs/components/SwipeArea.module.css.cjs +12 -0
  12. package/dist/cjs/components/SwipeArea.module.css.cjs.map +1 -0
  13. package/dist/cjs/components/TapButton.cjs +58 -0
  14. package/dist/cjs/components/TapButton.cjs.map +1 -0
  15. package/dist/cjs/components/TapButton.module.css.cjs +12 -0
  16. package/dist/cjs/components/TapButton.module.css.cjs.map +1 -0
  17. package/dist/cjs/context/RoomProvider.cjs +118 -0
  18. package/dist/cjs/context/RoomProvider.cjs.map +1 -0
  19. package/dist/cjs/hooks/useExternalGames.cjs +49 -0
  20. package/dist/cjs/hooks/useExternalGames.cjs.map +1 -0
  21. package/dist/cjs/hooks/useGameHost.cjs +135 -0
  22. package/dist/cjs/hooks/useGameHost.cjs.map +1 -0
  23. package/dist/cjs/hooks/useGamePlayer.cjs +75 -0
  24. package/dist/cjs/hooks/useGamePlayer.cjs.map +1 -0
  25. package/dist/cjs/iframe/index.cjs +508 -0
  26. package/dist/cjs/iframe/index.cjs.map +1 -0
  27. package/dist/cjs/index.cjs +32 -0
  28. package/dist/cjs/index.cjs.map +1 -0
  29. package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs +33 -0
  30. package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs.map +1 -0
  31. package/dist/cjs/server/index.cjs +45 -0
  32. package/dist/cjs/server/index.cjs.map +1 -0
  33. package/dist/cjs/transport/DirectTransport.cjs +23 -0
  34. package/dist/cjs/transport/DirectTransport.cjs.map +1 -0
  35. package/dist/cjs/transport/PostMessageTransport.cjs +72 -0
  36. package/dist/cjs/transport/PostMessageTransport.cjs.map +1 -0
  37. package/dist/cjs/transport/protocol.cjs +10 -0
  38. package/dist/cjs/transport/protocol.cjs.map +1 -0
  39. package/dist/esm/components/DirectionPad.js +66 -0
  40. package/dist/esm/components/DirectionPad.js.map +1 -0
  41. package/dist/esm/components/DirectionPad.module.css.js +8 -0
  42. package/dist/esm/components/DirectionPad.module.css.js.map +1 -0
  43. package/dist/esm/components/HoldButton.js +55 -0
  44. package/dist/esm/components/HoldButton.js.map +1 -0
  45. package/dist/esm/components/HoldButton.module.css.js +8 -0
  46. package/dist/esm/components/HoldButton.module.css.js.map +1 -0
  47. package/dist/esm/components/SwipeArea.js +56 -0
  48. package/dist/esm/components/SwipeArea.js.map +1 -0
  49. package/dist/esm/components/SwipeArea.module.css.js +8 -0
  50. package/dist/esm/components/SwipeArea.module.css.js.map +1 -0
  51. package/dist/esm/components/TapButton.js +56 -0
  52. package/dist/esm/components/TapButton.js.map +1 -0
  53. package/dist/esm/components/TapButton.module.css.js +8 -0
  54. package/dist/esm/components/TapButton.module.css.js.map +1 -0
  55. package/dist/esm/context/RoomProvider.js +109 -0
  56. package/dist/esm/context/RoomProvider.js.map +1 -0
  57. package/dist/esm/hooks/useExternalGames.js +47 -0
  58. package/dist/esm/hooks/useExternalGames.js.map +1 -0
  59. package/dist/esm/hooks/useGameHost.js +133 -0
  60. package/dist/esm/hooks/useGameHost.js.map +1 -0
  61. package/dist/esm/hooks/useGamePlayer.js +73 -0
  62. package/dist/esm/hooks/useGamePlayer.js.map +1 -0
  63. package/dist/esm/iframe/index.js +502 -0
  64. package/dist/esm/iframe/index.js.map +1 -0
  65. package/dist/esm/index.js +11 -0
  66. package/dist/esm/index.js.map +1 -0
  67. package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js +29 -0
  68. package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js.map +1 -0
  69. package/dist/esm/server/index.js +43 -0
  70. package/dist/esm/server/index.js.map +1 -0
  71. package/dist/esm/transport/DirectTransport.js +21 -0
  72. package/dist/esm/transport/DirectTransport.js.map +1 -0
  73. package/dist/esm/transport/PostMessageTransport.js +70 -0
  74. package/dist/esm/transport/PostMessageTransport.js.map +1 -0
  75. package/dist/esm/transport/protocol.js +7 -0
  76. package/dist/esm/transport/protocol.js.map +1 -0
  77. package/dist/types/components/DirectionPad.d.ts +21 -0
  78. package/dist/types/components/DirectionPad.d.ts.map +1 -0
  79. package/dist/types/components/HoldButton.d.ts +22 -0
  80. package/dist/types/components/HoldButton.d.ts.map +1 -0
  81. package/dist/types/components/IframeGameBridge.d.ts +40 -0
  82. package/dist/types/components/IframeGameBridge.d.ts.map +1 -0
  83. package/dist/types/components/SwipeArea.d.ts +19 -0
  84. package/dist/types/components/SwipeArea.d.ts.map +1 -0
  85. package/dist/types/components/TapButton.d.ts +19 -0
  86. package/dist/types/components/TapButton.d.ts.map +1 -0
  87. package/dist/types/components/index.d.ts +8 -0
  88. package/dist/types/components/index.d.ts.map +1 -0
  89. package/dist/types/context/RoomProvider.d.ts +69 -0
  90. package/dist/types/context/RoomProvider.d.ts.map +1 -0
  91. package/dist/types/context/index.d.ts +3 -0
  92. package/dist/types/context/index.d.ts.map +1 -0
  93. package/dist/types/dev/DevSimulator.d.ts +31 -0
  94. package/dist/types/dev/DevSimulator.d.ts.map +1 -0
  95. package/dist/types/dev/index.d.ts +2 -0
  96. package/dist/types/dev/index.d.ts.map +1 -0
  97. package/dist/types/hooks/index.d.ts +4 -0
  98. package/dist/types/hooks/index.d.ts.map +1 -0
  99. package/dist/types/hooks/useExternalGames.d.ts +32 -0
  100. package/dist/types/hooks/useExternalGames.d.ts.map +1 -0
  101. package/dist/types/hooks/useGameHost.d.ts +40 -0
  102. package/dist/types/hooks/useGameHost.d.ts.map +1 -0
  103. package/dist/types/hooks/useGamePlayer.d.ts +17 -0
  104. package/dist/types/hooks/useGamePlayer.d.ts.map +1 -0
  105. package/dist/types/iframe/IframeRoomProvider.d.ts +31 -0
  106. package/dist/types/iframe/IframeRoomProvider.d.ts.map +1 -0
  107. package/dist/types/iframe/index.d.ts +18 -0
  108. package/dist/types/iframe/index.d.ts.map +1 -0
  109. package/dist/types/iframe/vanilla.d.ts +40 -0
  110. package/dist/types/iframe/vanilla.d.ts.map +1 -0
  111. package/dist/types/index.d.ts +34 -0
  112. package/dist/types/index.d.ts.map +1 -0
  113. package/dist/types/server/createGameRelay.d.ts +26 -0
  114. package/dist/types/server/createGameRelay.d.ts.map +1 -0
  115. package/dist/types/server/index.d.ts +3 -0
  116. package/dist/types/server/index.d.ts.map +1 -0
  117. package/dist/types/transport/DirectTransport.d.ts +14 -0
  118. package/dist/types/transport/DirectTransport.d.ts.map +1 -0
  119. package/dist/types/transport/PostMessageTransport.d.ts +20 -0
  120. package/dist/types/transport/PostMessageTransport.d.ts.map +1 -0
  121. package/dist/types/transport/index.d.ts +6 -0
  122. package/dist/types/transport/index.d.ts.map +1 -0
  123. package/dist/types/transport/protocol.d.ts +50 -0
  124. package/dist/types/transport/protocol.d.ts.map +1 -0
  125. package/dist/types/transport/types.d.ts +14 -0
  126. package/dist/types/transport/types.d.ts.map +1 -0
  127. package/dist/types/types.d.ts +33 -0
  128. package/dist/types/types.d.ts.map +1 -0
  129. package/dist/umd/smore-sdk-iframe.umd.js +511 -0
  130. package/dist/umd/smore-sdk-iframe.umd.js.map +1 -0
  131. package/dist/umd/smore-sdk-iframe.umd.min.js +2 -0
  132. package/dist/umd/smore-sdk-iframe.umd.min.js.map +1 -0
  133. package/dist/umd/smore-sdk.umd.js +709 -0
  134. package/dist/umd/smore-sdk.umd.js.map +1 -0
  135. package/dist/umd/smore-sdk.umd.min.js +2 -0
  136. package/dist/umd/smore-sdk.umd.min.js.map +1 -0
  137. package/package.json +87 -0
@@ -0,0 +1,43 @@
1
+ function createGameRelay(config) {
2
+ return function setupHandlers(io, socket, getRoomHostSocketId, getPlayerSocketId) {
3
+ const { gameId, playerToHost, hostBroadcast, hostToPlayer } = config;
4
+ playerToHost?.forEach(({ from, toHost, withAck }) => {
5
+ socket.on(from, (data, callback) => {
6
+ const roomCode = socket.roomCode;
7
+ if (!roomCode) {
8
+ if (withAck && callback) callback({ success: false, error: "No room" });
9
+ return;
10
+ }
11
+ const hostSocketId = getRoomHostSocketId(roomCode);
12
+ if (!hostSocketId) {
13
+ if (withAck && callback) callback({ success: false, error: "No host" });
14
+ return;
15
+ }
16
+ io.to(hostSocketId).emit(toHost || from, {
17
+ sessionId: socket.sessionId,
18
+ ...data
19
+ });
20
+ if (withAck && callback) callback({ success: true });
21
+ });
22
+ });
23
+ hostBroadcast?.forEach(({ from, toPlayers }) => {
24
+ socket.on(from, (data) => {
25
+ const roomCode = socket.roomCode;
26
+ if (!roomCode) return;
27
+ socket.to(roomCode).emit(toPlayers || from, data);
28
+ });
29
+ });
30
+ hostToPlayer?.forEach(({ from, toPlayer }) => {
31
+ socket.on(from, (data) => {
32
+ if (!getPlayerSocketId) return;
33
+ const targetSocketId = getPlayerSocketId(data.sessionId);
34
+ if (!targetSocketId) return;
35
+ const { sessionId, ...rest } = data;
36
+ io.to(targetSocketId).emit(toPlayer || from, rest);
37
+ });
38
+ });
39
+ };
40
+ }
41
+
42
+ export { createGameRelay };
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/server/createGameRelay.ts"],"sourcesContent":["import type { Server, Socket } from 'socket.io';\n\nexport interface RelayEvent {\n from: string;\n toHost?: string;\n withAck?: boolean;\n}\n\nexport interface BroadcastEvent {\n from: string;\n toPlayers?: string;\n}\n\nexport interface TargetedEvent {\n from: string;\n toPlayer?: string;\n}\n\nexport interface CreateGameRelayConfig {\n gameId: string;\n playerToHost?: RelayEvent[];\n hostBroadcast?: BroadcastEvent[];\n hostToPlayer?: TargetedEvent[];\n}\n\nexport type GameRelaySetup = (\n io: Server,\n socket: Socket & { sessionId?: string; roomCode?: string },\n getRoomHostSocketId: (roomCode: string) => string | null,\n getPlayerSocketId?: (sessionId: string) => string | null,\n) => void;\n\nexport function createGameRelay(config: CreateGameRelayConfig): GameRelaySetup {\n return function setupHandlers(io, socket, getRoomHostSocketId, getPlayerSocketId) {\n const { gameId, playerToHost, hostBroadcast, hostToPlayer } = config;\n\n // Player → Host relay\n playerToHost?.forEach(({ from, toHost, withAck }) => {\n socket.on(from, (data: any, callback?: Function) => {\n const roomCode = (socket as any).roomCode;\n if (!roomCode) {\n if (withAck && callback) callback({ success: false, error: 'No room' });\n return;\n }\n const hostSocketId = getRoomHostSocketId(roomCode);\n if (!hostSocketId) {\n if (withAck && callback) callback({ success: false, error: 'No host' });\n return;\n }\n io.to(hostSocketId).emit(toHost || from, {\n sessionId: (socket as any).sessionId,\n ...data,\n });\n if (withAck && callback) callback({ success: true });\n });\n });\n\n // Host → All Players broadcast\n hostBroadcast?.forEach(({ from, toPlayers }) => {\n socket.on(from, (data: any) => {\n const roomCode = (socket as any).roomCode;\n if (!roomCode) return;\n socket.to(roomCode).emit(toPlayers || from, data);\n });\n });\n\n // Host → Specific Player\n hostToPlayer?.forEach(({ from, toPlayer }) => {\n socket.on(from, (data: { sessionId: string; [key: string]: any }) => {\n if (!getPlayerSocketId) return;\n const targetSocketId = getPlayerSocketId(data.sessionId);\n if (!targetSocketId) return;\n const { sessionId, ...rest } = data;\n io.to(targetSocketId).emit(toPlayer || from, rest);\n });\n });\n };\n}\n"],"names":[],"mappings":"AAgCO,SAAS,gBAAgB,MAAA,EAA+C;AAC7E,EAAA,OAAO,SAAS,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,qBAAqB,iBAAA,EAAmB;AAChF,IAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,aAAA,EAAe,cAAa,GAAI,MAAA;AAG9D,IAAA,YAAA,EAAc,QAAQ,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAQ,KAAM;AACnD,MAAA,MAAA,CAAO,EAAA,CAAG,IAAA,EAAM,CAAC,IAAA,EAAW,QAAA,KAAwB;AAClD,QAAA,MAAM,WAAY,MAAA,CAAe,QAAA;AACjC,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,IAAI,OAAA,IAAW,UAAU,QAAA,CAAS,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,WAAW,CAAA;AACtE,UAAA;AAAA,QACF;AACA,QAAA,MAAM,YAAA,GAAe,oBAAoB,QAAQ,CAAA;AACjD,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,IAAI,OAAA,IAAW,UAAU,QAAA,CAAS,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,WAAW,CAAA;AACtE,UAAA;AAAA,QACF;AACA,QAAA,EAAA,CAAG,EAAA,CAAG,YAAY,CAAA,CAAE,IAAA,CAAK,UAAU,IAAA,EAAM;AAAA,UACvC,WAAY,MAAA,CAAe,SAAA;AAAA,UAC3B,GAAG;AAAA,SACJ,CAAA;AACD,QAAA,IAAI,WAAW,QAAA,EAAU,QAAA,CAAS,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,MACrD,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAGD,IAAA,aAAA,EAAe,OAAA,CAAQ,CAAC,EAAE,IAAA,EAAM,WAAU,KAAM;AAC9C,MAAA,MAAA,CAAO,EAAA,CAAG,IAAA,EAAM,CAAC,IAAA,KAAc;AAC7B,QAAA,MAAM,WAAY,MAAA,CAAe,QAAA;AACjC,QAAA,IAAI,CAAC,QAAA,EAAU;AACf,QAAA,MAAA,CAAO,GAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,SAAA,IAAa,MAAM,IAAI,CAAA;AAAA,MAClD,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAGD,IAAA,YAAA,EAAc,OAAA,CAAQ,CAAC,EAAE,IAAA,EAAM,UAAS,KAAM;AAC5C,MAAA,MAAA,CAAO,EAAA,CAAG,IAAA,EAAM,CAAC,IAAA,KAAoD;AACnE,QAAA,IAAI,CAAC,iBAAA,EAAmB;AACxB,QAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,IAAA,CAAK,SAAS,CAAA;AACvD,QAAA,IAAI,CAAC,cAAA,EAAgB;AACrB,QAAA,MAAM,EAAE,SAAA,EAAW,GAAG,IAAA,EAAK,GAAI,IAAA;AAC/B,QAAA,EAAA,CAAG,GAAG,cAAc,CAAA,CAAE,IAAA,CAAK,QAAA,IAAY,MAAM,IAAI,CAAA;AAAA,MACnD,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAA;AACF;;;;"}
@@ -0,0 +1,21 @@
1
+ class DirectTransport {
2
+ constructor(socket) {
3
+ this.socket = socket;
4
+ }
5
+ emit(event, ...args) {
6
+ this.socket.emit(event, ...args);
7
+ }
8
+ on(event, handler) {
9
+ this.socket.on(event, handler);
10
+ }
11
+ off(event, handler) {
12
+ if (handler) {
13
+ this.socket.off(event, handler);
14
+ } else {
15
+ this.socket.off(event);
16
+ }
17
+ }
18
+ }
19
+
20
+ export { DirectTransport };
21
+ //# sourceMappingURL=DirectTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectTransport.js","sources":["../../../src/transport/DirectTransport.ts"],"sourcesContent":["/**\n * DirectTransport - Wraps a Socket.IO socket as a Transport.\n * Used by bundled (internal) games. Behaviour is identical to using socket directly.\n */\n\nimport type { Socket } from 'socket.io-client';\nimport type { Transport, TransportEventHandler } from './types';\n\nexport class DirectTransport implements Transport {\n constructor(private socket: Socket) {}\n\n emit(event: string, ...args: any[]): void {\n this.socket.emit(event, ...args);\n }\n\n on(event: string, handler: TransportEventHandler): void {\n this.socket.on(event, handler);\n }\n\n off(event: string, handler?: TransportEventHandler): void {\n if (handler) {\n this.socket.off(event, handler);\n } else {\n this.socket.off(event);\n }\n }\n}\n"],"names":[],"mappings":"AAQO,MAAM,eAAA,CAAqC;AAAA,EAChD,YAAoB,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAiB;AAAA,EAErC,IAAA,CAAK,UAAkB,IAAA,EAAmB;AACxC,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA,EACjC;AAAA,EAEA,EAAA,CAAG,OAAe,OAAA,EAAsC;AACtD,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,KAAA,EAAO,OAAO,CAAA;AAAA,EAC/B;AAAA,EAEA,GAAA,CAAI,OAAe,OAAA,EAAuC;AACxD,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,OAAO,CAAA;AAAA,IAChC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAA,CAAO,IAAI,KAAK,CAAA;AAAA,IACvB;AAAA,EACF;AACF;;;;"}
@@ -0,0 +1,70 @@
1
+ import { isSmoreMessage } from './protocol.js';
2
+
3
+ class PostMessageTransport {
4
+ handlers = /* @__PURE__ */ new Map();
5
+ ackCallbacks = /* @__PURE__ */ new Map();
6
+ ackCounter = 0;
7
+ parentOrigin;
8
+ boundMessageHandler;
9
+ constructor(parentOrigin = "*") {
10
+ this.parentOrigin = parentOrigin;
11
+ this.boundMessageHandler = this.handleMessage.bind(this);
12
+ window.addEventListener("message", this.boundMessageHandler);
13
+ }
14
+ emit(event, ...args) {
15
+ let data = args[0];
16
+ let ackId;
17
+ if (args.length >= 2 && typeof args[args.length - 1] === "function") {
18
+ data = args.length === 2 ? args[0] : args[0];
19
+ const callback = args[args.length - 1];
20
+ ackId = `ack_${++this.ackCounter}`;
21
+ this.ackCallbacks.set(ackId, callback);
22
+ }
23
+ window.parent.postMessage(
24
+ { type: "smore:emit", payload: { event, data, ackId } },
25
+ this.parentOrigin
26
+ );
27
+ }
28
+ on(event, handler) {
29
+ let set = this.handlers.get(event);
30
+ if (!set) {
31
+ set = /* @__PURE__ */ new Set();
32
+ this.handlers.set(event, set);
33
+ }
34
+ set.add(handler);
35
+ }
36
+ off(event, handler) {
37
+ if (!handler) {
38
+ this.handlers.delete(event);
39
+ return;
40
+ }
41
+ this.handlers.get(event)?.delete(handler);
42
+ }
43
+ destroy() {
44
+ window.removeEventListener("message", this.boundMessageHandler);
45
+ this.handlers.clear();
46
+ this.ackCallbacks.clear();
47
+ }
48
+ handleMessage(e) {
49
+ if (this.parentOrigin !== "*" && e.origin !== this.parentOrigin) return;
50
+ const msg = e.data;
51
+ if (!isSmoreMessage(msg)) return;
52
+ if (msg.type === "smore:event") {
53
+ const { event, data } = msg.payload;
54
+ const set = this.handlers.get(event);
55
+ if (set) {
56
+ set.forEach((handler) => handler(data));
57
+ }
58
+ } else if (msg.type === "smore:ack") {
59
+ const { ackId, data } = msg.payload;
60
+ const cb = this.ackCallbacks.get(ackId);
61
+ if (cb) {
62
+ this.ackCallbacks.delete(ackId);
63
+ cb(data);
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ export { PostMessageTransport };
70
+ //# sourceMappingURL=PostMessageTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostMessageTransport.js","sources":["../../../src/transport/PostMessageTransport.ts"],"sourcesContent":["/**\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"],"names":[],"mappings":";;AAUO,MAAM,oBAAA,CAA0C;AAAA,EAC7C,QAAA,uBAAe,GAAA,EAAwC;AAAA,EACvD,YAAA,uBAAmB,GAAA,EAAsC;AAAA,EACzD,UAAA,GAAa,CAAA;AAAA,EACb,YAAA;AAAA,EACA,mBAAA;AAAA,EAER,WAAA,CAAY,eAAuB,GAAA,EAAK;AACtC,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,IAAA,CAAK,mBAAA,GAAsB,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA;AACvD,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,mBAAmB,CAAA;AAAA,EAC7D;AAAA,EAEA,IAAA,CAAK,UAAkB,IAAA,EAAmB;AAExC,IAAA,IAAI,IAAA,GAAY,KAAK,CAAC,CAAA;AACtB,IAAA,IAAI,KAAA;AAEJ,IAAA,IAAI,IAAA,CAAK,UAAU,CAAA,IAAK,OAAO,KAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,KAAM,UAAA,EAAY;AACnE,MAAA,IAAA,GAAO,KAAK,MAAA,KAAW,CAAA,GAAI,KAAK,CAAC,CAAA,GAAI,KAAK,CAAC,CAAA;AAC3C,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AACrC,MAAA,KAAA,GAAQ,CAAA,IAAA,EAAO,EAAE,IAAA,CAAK,UAAU,CAAA,CAAA;AAChC,MAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,KAAA,EAAO,QAAQ,CAAA;AAAA,IACvC;AAEA,IAAA,MAAA,CAAO,MAAA,CAAO,WAAA;AAAA,MACZ,EAAE,MAAM,YAAA,EAAc,OAAA,EAAS,EAAE,KAAA,EAAO,IAAA,EAAM,OAAM,EAAE;AAAA,MACtD,IAAA,CAAK;AAAA,KACP;AAAA,EACF;AAAA,EAEA,EAAA,CAAG,OAAe,OAAA,EAAsC;AACtD,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA;AACjC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,uBAAU,GAAA,EAAI;AACd,MAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAAA,IAC9B;AACA,IAAA,GAAA,CAAI,IAAI,OAAO,CAAA;AAAA,EACjB;AAAA,EAEA,GAAA,CAAI,OAAe,OAAA,EAAuC;AACxD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,KAAK,CAAA;AAC1B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,OAAO,CAAA;AAAA,EAC1C;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,IAAA,CAAK,mBAAmB,CAAA;AAC9D,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AACpB,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAAA,EAC1B;AAAA,EAEQ,cAAc,CAAA,EAAuB;AAE3C,IAAA,IAAI,KAAK,YAAA,KAAiB,GAAA,IAAO,CAAA,CAAE,MAAA,KAAW,KAAK,YAAA,EAAc;AAEjE,IAAA,MAAM,MAAM,CAAA,CAAE,IAAA;AACd,IAAA,IAAI,CAAC,cAAA,CAAe,GAAG,CAAA,EAAG;AAE1B,IAAA,IAAI,GAAA,CAAI,SAAS,aAAA,EAAe;AAC9B,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAK,GAAA,CAA0B,OAAA;AACnD,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA;AACnC,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,GAAA,CAAI,OAAA,CAAQ,CAAC,OAAA,KAAY,OAAA,CAAQ,IAAI,CAAC,CAAA;AAAA,MACxC;AAAA,IACF,CAAA,MAAA,IAAW,GAAA,CAAI,IAAA,KAAS,WAAA,EAAa;AACnC,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAK,GAAA,CAAwB,OAAA;AACjD,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,KAAK,CAAA;AACtC,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,IAAA,CAAK,YAAA,CAAa,OAAO,KAAK,CAAA;AAC9B,QAAA,EAAA,CAAG,IAAI,CAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;;;;"}
@@ -0,0 +1,7 @@
1
+ const SMORE_MSG_PREFIX = "smore:";
2
+ function isSmoreMessage(data) {
3
+ return data && typeof data === "object" && typeof data.type === "string" && data.type.startsWith(SMORE_MSG_PREFIX);
4
+ }
5
+
6
+ export { SMORE_MSG_PREFIX, isSmoreMessage };
7
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sources":["../../../src/transport/protocol.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"],"names":[],"mappings":"AAIO,MAAM,gBAAA,GAAmB;AA2DzB,SAAS,eAAe,IAAA,EAAiC;AAC9D,EAAA,OAAO,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,IAAA,CAAK,UAAA,CAAW,gBAAgB,CAAA;AACnH;;;;"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * S'MORE Game SDK - DirectionPad Component
3
+ *
4
+ * 4-direction or 2-direction control pad
5
+ */
6
+ import type { DirectionPadProps } from '../types';
7
+ /**
8
+ * DirectionPad - For directional input
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * // 4 directions
13
+ * <DirectionPad onDirection={(dir) => send('move', { direction: dir })} />
14
+ *
15
+ * // Left/Right only
16
+ * <DirectionPad leftRightOnly onDirection={(dir) => send('move', { direction: dir })} />
17
+ * ```
18
+ */
19
+ export declare function DirectionPad({ onDirection, leftRightOnly, upDownOnly, className, }: DirectionPadProps): import("react/jsx-runtime").JSX.Element;
20
+ export default DirectionPad;
21
+ //# sourceMappingURL=DirectionPad.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectionPad.d.ts","sourceRoot":"","sources":["../../../src/components/DirectionPad.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,aAAqB,EACrB,UAAkB,EAClB,SAAS,GACV,EAAE,iBAAiB,2CAwEnB;AAED,eAAe,YAAY,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * S'MORE Game SDK - HoldButton Component
3
+ *
4
+ * Button that detects hold start/end events
5
+ */
6
+ import type { HoldButtonProps } from '../types';
7
+ /**
8
+ * HoldButton - For hold/release input patterns
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <HoldButton
13
+ * onHoldStart={() => send('charge', { type: 'start' })}
14
+ * onHoldEnd={() => send('charge', { type: 'end' })}
15
+ * >
16
+ * HOLD
17
+ * </HoldButton>
18
+ * ```
19
+ */
20
+ export declare function HoldButton({ onHoldStart, onHoldEnd, children, className, disabled, }: HoldButtonProps): import("react/jsx-runtime").JSX.Element;
21
+ export default HoldButton;
22
+ //# sourceMappingURL=HoldButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoldButton.d.ts","sourceRoot":"","sources":["../../../src/components/HoldButton.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGhD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EACzB,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAgB,GACjB,EAAE,eAAe,2CAiDjB;AAED,eAAe,UAAU,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * IframeGameBridge - Parent-side bridge between iframe and Socket.IO.
3
+ *
4
+ * Renders an iframe loading the external game URL.
5
+ * Bridges postMessage ↔ Socket.IO:
6
+ * - iframe sends `smore:emit` → bridge translates event name and calls `socket.emit()`
7
+ * - socket receives events → bridge translates back and sends `smore:event` to iframe
8
+ *
9
+ * Event translation:
10
+ * - System events (room:*, game:*) pass through unchanged
11
+ * - Game-specific events are prefixed with `ext:{gameId}:` for server genericRelay
12
+ * - Incoming `ext:{gameId}:*` events are stripped back to original name for the iframe
13
+ *
14
+ * Used by GameOverlay (host) and GameView (player) when the game type is 'external'.
15
+ */
16
+ import React from 'react';
17
+ import type { Socket } from 'socket.io-client';
18
+ interface Player {
19
+ sessionId: string;
20
+ name: string;
21
+ connected?: boolean;
22
+ }
23
+ export interface IframeGameBridgeProps {
24
+ gameId: string;
25
+ url: string;
26
+ socket: Socket;
27
+ side: 'host' | 'player';
28
+ roomCode: string;
29
+ players: Player[];
30
+ leaderId: string | null;
31
+ mySessionId?: string;
32
+ isLeader?: boolean;
33
+ onReady?: () => void;
34
+ onGameOver?: (results: any) => void;
35
+ style?: React.CSSProperties;
36
+ className?: string;
37
+ }
38
+ export declare const IframeGameBridge: React.FC<IframeGameBridgeProps>;
39
+ export {};
40
+ //# sourceMappingURL=IframeGameBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IframeGameBridge.d.ts","sourceRoot":"","sources":["../../../src/components/IframeGameBridge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI/C,UAAU,MAAM;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAqJ5D,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * S'MORE Game SDK - SwipeArea Component
3
+ *
4
+ * Detects swipe gestures
5
+ */
6
+ import type { SwipeAreaProps } from '../types';
7
+ /**
8
+ * SwipeArea - For swipe gesture input
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <SwipeArea onSwipe={(dir) => send('swipe', { direction: dir })}>
13
+ * <div>Swipe here!</div>
14
+ * </SwipeArea>
15
+ * ```
16
+ */
17
+ export declare function SwipeArea({ onSwipe, threshold, children, className, }: SwipeAreaProps): import("react/jsx-runtime").JSX.Element;
18
+ export default SwipeArea;
19
+ //# sourceMappingURL=SwipeArea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwipeArea.d.ts","sourceRoot":"","sources":["../../../src/components/SwipeArea.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,SAAc,EACd,QAAQ,EACR,SAAS,GACV,EAAE,cAAc,2CAqDhB;AAED,eAAe,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * S'MORE Game SDK - TapButton Component
3
+ *
4
+ * Optimized touch button with haptic feedback
5
+ */
6
+ import type { TapButtonProps } from '../types';
7
+ /**
8
+ * TapButton - Optimized for mobile touch input
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <TapButton onTap={() => send('tap')}>
13
+ * TAP!
14
+ * </TapButton>
15
+ * ```
16
+ */
17
+ export declare function TapButton({ onTap, children, className, disabled, }: TapButtonProps): import("react/jsx-runtime").JSX.Element;
18
+ export default TapButton;
19
+ //# sourceMappingURL=TapButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TapButton.d.ts","sourceRoot":"","sources":["../../../src/components/TapButton.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,QAAgB,GACjB,EAAE,cAAc,2CAmDhB;AAED,eAAe,SAAS,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * S'MORE Game SDK - Components
3
+ */
4
+ export { TapButton } from './TapButton';
5
+ export { HoldButton } from './HoldButton';
6
+ export { DirectionPad } from './DirectionPad';
7
+ export { SwipeArea } from './SwipeArea';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * RoomProvider - SDK Room Context
3
+ *
4
+ * Foundation context that all other SDK hooks depend on.
5
+ * Provides room state (players, roomCode, leaderId) for both host and player sides.
6
+ *
7
+ * Also provides a Transport abstraction via TransportContext.
8
+ * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.
9
+ * - IframeRoomProvider (external) provides a PostMessageTransport.
10
+ *
11
+ * Usage:
12
+ * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>
13
+ * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} mySessionId={...} isLeader={...} socket={...} isConnected={...}>
14
+ */
15
+ import React from 'react';
16
+ import type { Player } from '@smore/shared';
17
+ import type { Socket } from 'socket.io-client';
18
+ import type { Transport } from '../transport/types';
19
+ declare const TransportContext: React.Context<Transport | null>;
20
+ export declare function useTransport(): Transport;
21
+ export { TransportContext };
22
+ export interface RoomState {
23
+ roomCode: string;
24
+ players: Player[];
25
+ connectedPlayers: Player[];
26
+ leaderId: string | null;
27
+ }
28
+ export interface HostRoomState extends RoomState {
29
+ socket: Socket;
30
+ }
31
+ export interface PlayerRoomState extends RoomState {
32
+ mySessionId: string;
33
+ isLeader: boolean;
34
+ socket: Socket;
35
+ isConnected: boolean;
36
+ }
37
+ export interface RoomContextValue {
38
+ roomCode: string;
39
+ players: Player[];
40
+ connectedPlayers: Player[];
41
+ leaderId: string | null;
42
+ side: 'host' | 'player';
43
+ host: HostRoomState | null;
44
+ player: PlayerRoomState | null;
45
+ }
46
+ export declare const RoomContext: React.Context<RoomContextValue | null>;
47
+ interface HostRoomProviderProps {
48
+ roomCode: string;
49
+ players: Player[];
50
+ leaderId: string | null;
51
+ socket: Socket;
52
+ children: React.ReactNode;
53
+ }
54
+ export declare const HostRoomProvider: React.FC<HostRoomProviderProps>;
55
+ interface PlayerRoomProviderProps {
56
+ roomCode: string;
57
+ players: Player[];
58
+ leaderId: string | null;
59
+ mySessionId: string;
60
+ isLeader: boolean;
61
+ socket: Socket;
62
+ isConnected: boolean;
63
+ children: React.ReactNode;
64
+ }
65
+ export declare const PlayerRoomProvider: React.FC<PlayerRoomProviderProps>;
66
+ export declare function useRoom(): RoomContextValue;
67
+ export declare function useHostRoom(): HostRoomState;
68
+ export declare function usePlayerRoom(): PlayerRoomState;
69
+ //# sourceMappingURL=RoomProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoomProvider.d.ts","sourceRoot":"","sources":["../../../src/context/RoomProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD,QAAA,MAAM,gBAAgB,iCAAwC,CAAC;AAE/D,wBAAgB,YAAY,IAAI,SAAS,CAMxC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAI5B,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC;AAID,eAAO,MAAM,WAAW,wCAA+C,CAAC;AAIxE,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAqC5D,CAAC;AAIF,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAiDhE,CAAC;AAIF,wBAAgB,OAAO,IAAI,gBAAgB,CAM1C;AAED,wBAAgB,WAAW,IAAI,aAAa,CAM3C;AAED,wBAAgB,aAAa,IAAI,eAAe,CAM/C"}
@@ -0,0 +1,3 @@
1
+ export { HostRoomProvider, PlayerRoomProvider, useRoom, useHostRoom, usePlayerRoom, useTransport, TransportContext, } from './RoomProvider';
2
+ export type { RoomState, HostRoomState, PlayerRoomState, RoomContextValue, } from './RoomProvider';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/context/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,aAAa,EACb,YAAY,EACZ,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,SAAS,EACT,aAAa,EACb,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * DevSimulator - Local development tool for testing iframe games without a server.
3
+ *
4
+ * Renders a host iframe and N player iframes side by side.
5
+ * Routes postMessage between iframes directly (no Socket.IO needed).
6
+ *
7
+ * Usage:
8
+ * ```tsx
9
+ * import { DevSimulator } from '@smore/sdk/dev';
10
+ *
11
+ * function App() {
12
+ * return (
13
+ * <DevSimulator
14
+ * hostUrl="http://localhost:3000/screen.html"
15
+ * playerUrl="http://localhost:3000/controller.html"
16
+ * playerCount={2}
17
+ * />
18
+ * );
19
+ * }
20
+ * ```
21
+ */
22
+ import React from 'react';
23
+ interface DevSimulatorProps {
24
+ hostUrl: string;
25
+ playerUrl: string;
26
+ playerCount?: number;
27
+ roomCode?: string;
28
+ }
29
+ export declare const DevSimulator: React.FC<DevSimulatorProps>;
30
+ export {};
31
+ //# sourceMappingURL=DevSimulator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DevSimulator.d.ts","sourceRoot":"","sources":["../../../src/dev/DevSimulator.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAIxE,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAuIpD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { DevSimulator } from './DevSimulator';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dev/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { useGameHost } from './useGameHost';
2
+ export type { UseGameHostConfig, UseGameHostReturn } from './useGameHost';
3
+ export { useGamePlayer } from './useGamePlayer';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * useExternalGames - Fetches external games from the server API.
3
+ *
4
+ * Returns a list of GameMetadata-compatible objects for external (iframe) games.
5
+ * Consumers merge this with their local GAMES array.
6
+ */
7
+ export interface ExternalGameMetadata {
8
+ id: string;
9
+ title: string;
10
+ description: string;
11
+ minPlayers: number;
12
+ maxPlayers: number;
13
+ thumbnail: string;
14
+ categories: string[];
15
+ type: 'external';
16
+ hostUrl: string | null;
17
+ playerUrl: string | null;
18
+ available: boolean;
19
+ rating: number;
20
+ heroRequired: boolean;
21
+ }
22
+ export interface UseExternalGamesConfig {
23
+ serverUrl: string;
24
+ enabled?: boolean;
25
+ }
26
+ export declare function useExternalGames(config: UseExternalGamesConfig): {
27
+ games: ExternalGameMetadata[];
28
+ loading: boolean;
29
+ error: string | null;
30
+ refresh: () => void;
31
+ };
32
+ //# sourceMappingURL=useExternalGames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useExternalGames.d.ts","sourceRoot":"","sources":["../../../src/hooks/useExternalGames.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG;IAChE,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAiDA"}
@@ -0,0 +1,40 @@
1
+ import type { HostRoomState } from '../context/RoomProvider';
2
+ type InputHandler = (playerId: string, data?: any) => void;
3
+ export interface UseGameHostConfig {
4
+ /** Unique game identifier (e.g. 'fibbage', 'wasd') */
5
+ gameId: string;
6
+ /**
7
+ * Map of action names to handler functions.
8
+ * Listens directly on socket for `{gameId}:{key}` events.
9
+ */
10
+ onInput?: Record<string, InputHandler>;
11
+ /**
12
+ * Called when a player requests game state (e.g. after returning from background).
13
+ * Return the current game state object to send back to that player.
14
+ */
15
+ onStateRequest?: (playerId: string) => Record<string, any>;
16
+ /** Called when a player leaves the room. */
17
+ onPlayerLeave?: (playerId: string) => void;
18
+ /** Called when a player disconnects (may reconnect). */
19
+ onPlayerDisconnect?: (playerId: string) => void;
20
+ /** Called when a previously disconnected player reconnects. */
21
+ onPlayerReconnect?: (playerId: string) => void;
22
+ /**
23
+ * Generic socket event listeners (for server broadcasts the host needs to receive).
24
+ * Keys are full event names, values are handler functions.
25
+ */
26
+ listeners?: Record<string, (data: any) => void>;
27
+ }
28
+ export interface UseGameHostReturn {
29
+ /** Current room state from HostRoomProvider context. */
30
+ room: HostRoomState;
31
+ /** Broadcast an event to all players via the host socket. */
32
+ broadcast: (event: string, data: any) => void;
33
+ /** Send state/event to a specific player by sessionId. */
34
+ sendToPlayer: (sessionId: string, event: string, data: any) => void;
35
+ /** Emit game-over with optional results payload. */
36
+ emitGameOver: (results?: any) => void;
37
+ }
38
+ export declare function useGameHost(config: UseGameHostConfig): UseGameHostReturn;
39
+ export {};
40
+ //# sourceMappingURL=useGameHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGameHost.d.ts","sourceRoot":"","sources":["../../../src/hooks/useGameHost.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAM7D,KAAK,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAEvC;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3D,4CAA4C;IAC5C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAE3C,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhD,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAE/C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,IAAI,EAAE,aAAa,CAAC;IAEpB,6DAA6D;IAC7D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAE9C,0DAA0D;IAC1D,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAEpE,oDAAoD;IACpD,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;CACvC;AAMD,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAyJxE"}
@@ -0,0 +1,17 @@
1
+ import type { PlayerRoomState } from '../context/RoomProvider';
2
+ export interface UseGamePlayerConfig {
3
+ gameId: string;
4
+ listeners?: Record<string, (data: any) => void>;
5
+ }
6
+ export interface UseGamePlayerReturn {
7
+ room: PlayerRoomState;
8
+ emit: (event: string, data?: any, callback?: (response: any) => void) => void;
9
+ /** Emit a tap input: sends `{gameId}:{action}` event */
10
+ sendTapInput: (action: string) => void;
11
+ /** Emit a hold input: sends `{gameId}:{action}:{type}` event */
12
+ sendHoldInput: (action: string, type: 'START' | 'END') => void;
13
+ isConnected: boolean;
14
+ gameState: Record<string, any> | null;
15
+ }
16
+ export declare function useGamePlayer(config: UseGamePlayerConfig): UseGamePlayerReturn;
17
+ //# sourceMappingURL=useGamePlayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGamePlayer.d.ts","sourceRoot":"","sources":["../../../src/hooks/useGamePlayer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC;IAC9E,wDAAwD;IACxD,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gEAAgE;IAChE,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC;IAC/D,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,mBAAmB,CA2E9E"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * IframeRoomProvider - Entry point for external (iframe-hosted) games.
3
+ *
4
+ * Usage inside an external game's iframe:
5
+ * ```tsx
6
+ * import { IframeRoomProvider } from '@smore/sdk/iframe';
7
+ * import { useGameHost } from '@smore/sdk/iframe';
8
+ *
9
+ * function App() {
10
+ * return (
11
+ * <IframeRoomProvider>
12
+ * <MyGame />
13
+ * </IframeRoomProvider>
14
+ * );
15
+ * }
16
+ * ```
17
+ *
18
+ * Lifecycle:
19
+ * 1. Mount → sends `smore:ready` to parent
20
+ * 2. Receives `smore:init` from parent with room state
21
+ * 3. Creates PostMessageTransport
22
+ * 4. Renders children with RoomContext + TransportContext
23
+ */
24
+ import React from 'react';
25
+ interface IframeRoomProviderProps {
26
+ children: React.ReactNode;
27
+ parentOrigin?: string;
28
+ }
29
+ export declare const IframeRoomProvider: React.FC<IframeRoomProviderProps>;
30
+ export {};
31
+ //# sourceMappingURL=IframeRoomProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IframeRoomProvider.d.ts","sourceRoot":"","sources":["../../../src/iframe/IframeRoomProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAuC,MAAM,OAAO,CAAC;AAS5D,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAkFhE,CAAC"}