@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,33 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ function styleInject(css, ref) {
6
+ if ( ref === void 0 ) ref = {};
7
+ var insertAt = ref.insertAt;
8
+
9
+ if (!css || typeof document === 'undefined') { return; }
10
+
11
+ var head = document.head || document.getElementsByTagName('head')[0];
12
+ var style = document.createElement('style');
13
+ style.type = 'text/css';
14
+
15
+ if (insertAt === 'top') {
16
+ if (head.firstChild) {
17
+ head.insertBefore(style, head.firstChild);
18
+ } else {
19
+ head.appendChild(style);
20
+ }
21
+ } else {
22
+ head.appendChild(style);
23
+ }
24
+
25
+ if (style.styleSheet) {
26
+ style.styleSheet.cssText = css;
27
+ } else {
28
+ style.appendChild(document.createTextNode(css));
29
+ }
30
+ }
31
+
32
+ exports.default = styleInject;
33
+ //# sourceMappingURL=style-inject.es.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-inject.es.cjs","sources":["../../../../../../../../../../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":";;;;AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,MAAM,GAAG,GAAG,GAAG,EAAE;AAChC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ;;AAE7B,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,CAAC;;AAEzD,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC7C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU;;AAEzB,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC;AAC/C,IAAI,CAAC,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC7B,IAAI;AACJ,EAAE,CAAC,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC3B,EAAE;;AAEF,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG;AAClC,EAAE,CAAC,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AACnD,EAAE;AACF;;;;","x_google_ignoreList":[0]}
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ function createGameRelay(config) {
4
+ return function setupHandlers(io, socket, getRoomHostSocketId, getPlayerSocketId) {
5
+ const { gameId, playerToHost, hostBroadcast, hostToPlayer } = config;
6
+ playerToHost?.forEach(({ from, toHost, withAck }) => {
7
+ socket.on(from, (data, callback) => {
8
+ const roomCode = socket.roomCode;
9
+ if (!roomCode) {
10
+ if (withAck && callback) callback({ success: false, error: "No room" });
11
+ return;
12
+ }
13
+ const hostSocketId = getRoomHostSocketId(roomCode);
14
+ if (!hostSocketId) {
15
+ if (withAck && callback) callback({ success: false, error: "No host" });
16
+ return;
17
+ }
18
+ io.to(hostSocketId).emit(toHost || from, {
19
+ sessionId: socket.sessionId,
20
+ ...data
21
+ });
22
+ if (withAck && callback) callback({ success: true });
23
+ });
24
+ });
25
+ hostBroadcast?.forEach(({ from, toPlayers }) => {
26
+ socket.on(from, (data) => {
27
+ const roomCode = socket.roomCode;
28
+ if (!roomCode) return;
29
+ socket.to(roomCode).emit(toPlayers || from, data);
30
+ });
31
+ });
32
+ hostToPlayer?.forEach(({ from, toPlayer }) => {
33
+ socket.on(from, (data) => {
34
+ if (!getPlayerSocketId) return;
35
+ const targetSocketId = getPlayerSocketId(data.sessionId);
36
+ if (!targetSocketId) return;
37
+ const { sessionId, ...rest } = data;
38
+ io.to(targetSocketId).emit(toPlayer || from, rest);
39
+ });
40
+ });
41
+ };
42
+ }
43
+
44
+ exports.createGameRelay = createGameRelay;
45
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","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,23 @@
1
+ 'use strict';
2
+
3
+ class DirectTransport {
4
+ constructor(socket) {
5
+ this.socket = socket;
6
+ }
7
+ emit(event, ...args) {
8
+ this.socket.emit(event, ...args);
9
+ }
10
+ on(event, handler) {
11
+ this.socket.on(event, handler);
12
+ }
13
+ off(event, handler) {
14
+ if (handler) {
15
+ this.socket.off(event, handler);
16
+ } else {
17
+ this.socket.off(event);
18
+ }
19
+ }
20
+ }
21
+
22
+ exports.DirectTransport = DirectTransport;
23
+ //# sourceMappingURL=DirectTransport.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectTransport.cjs","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,72 @@
1
+ 'use strict';
2
+
3
+ var protocol = require('./protocol.cjs');
4
+
5
+ class PostMessageTransport {
6
+ handlers = /* @__PURE__ */ new Map();
7
+ ackCallbacks = /* @__PURE__ */ new Map();
8
+ ackCounter = 0;
9
+ parentOrigin;
10
+ boundMessageHandler;
11
+ constructor(parentOrigin = "*") {
12
+ this.parentOrigin = parentOrigin;
13
+ this.boundMessageHandler = this.handleMessage.bind(this);
14
+ window.addEventListener("message", this.boundMessageHandler);
15
+ }
16
+ emit(event, ...args) {
17
+ let data = args[0];
18
+ let ackId;
19
+ if (args.length >= 2 && typeof args[args.length - 1] === "function") {
20
+ data = args.length === 2 ? args[0] : args[0];
21
+ const callback = args[args.length - 1];
22
+ ackId = `ack_${++this.ackCounter}`;
23
+ this.ackCallbacks.set(ackId, callback);
24
+ }
25
+ window.parent.postMessage(
26
+ { type: "smore:emit", payload: { event, data, ackId } },
27
+ this.parentOrigin
28
+ );
29
+ }
30
+ on(event, handler) {
31
+ let set = this.handlers.get(event);
32
+ if (!set) {
33
+ set = /* @__PURE__ */ new Set();
34
+ this.handlers.set(event, set);
35
+ }
36
+ set.add(handler);
37
+ }
38
+ off(event, handler) {
39
+ if (!handler) {
40
+ this.handlers.delete(event);
41
+ return;
42
+ }
43
+ this.handlers.get(event)?.delete(handler);
44
+ }
45
+ destroy() {
46
+ window.removeEventListener("message", this.boundMessageHandler);
47
+ this.handlers.clear();
48
+ this.ackCallbacks.clear();
49
+ }
50
+ handleMessage(e) {
51
+ if (this.parentOrigin !== "*" && e.origin !== this.parentOrigin) return;
52
+ const msg = e.data;
53
+ if (!protocol.isSmoreMessage(msg)) return;
54
+ if (msg.type === "smore:event") {
55
+ const { event, data } = msg.payload;
56
+ const set = this.handlers.get(event);
57
+ if (set) {
58
+ set.forEach((handler) => handler(data));
59
+ }
60
+ } else if (msg.type === "smore:ack") {
61
+ const { ackId, data } = msg.payload;
62
+ const cb = this.ackCallbacks.get(ackId);
63
+ if (cb) {
64
+ this.ackCallbacks.delete(ackId);
65
+ cb(data);
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ exports.PostMessageTransport = PostMessageTransport;
72
+ //# sourceMappingURL=PostMessageTransport.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostMessageTransport.cjs","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":["isSmoreMessage"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ const SMORE_MSG_PREFIX = "smore:";
4
+ function isSmoreMessage(data) {
5
+ return data && typeof data === "object" && typeof data.type === "string" && data.type.startsWith(SMORE_MSG_PREFIX);
6
+ }
7
+
8
+ exports.SMORE_MSG_PREFIX = SMORE_MSG_PREFIX;
9
+ exports.isSmoreMessage = isSmoreMessage;
10
+ //# sourceMappingURL=protocol.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.cjs","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,66 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useRef, useCallback } from 'react';
3
+ import styles from './DirectionPad.module.css.js';
4
+
5
+ function DirectionPad({
6
+ onDirection,
7
+ leftRightOnly = false,
8
+ upDownOnly = false,
9
+ className
10
+ }) {
11
+ const pressedRef = useRef(/* @__PURE__ */ new Set());
12
+ const handlePress = useCallback((direction) => {
13
+ if (pressedRef.current.has(direction)) return;
14
+ pressedRef.current.add(direction);
15
+ if (navigator.vibrate) {
16
+ navigator.vibrate(10);
17
+ }
18
+ onDirection(direction);
19
+ }, [onDirection]);
20
+ const handleRelease = useCallback((direction) => {
21
+ pressedRef.current.delete(direction);
22
+ }, []);
23
+ const createButton = (direction, label) => /* @__PURE__ */ jsx(
24
+ "button",
25
+ {
26
+ className: `${styles.dirButton} ${styles[direction]}`,
27
+ onTouchStart: (e) => {
28
+ e.preventDefault();
29
+ handlePress(direction);
30
+ },
31
+ onTouchEnd: (e) => {
32
+ e.preventDefault();
33
+ handleRelease(direction);
34
+ },
35
+ onTouchCancel: () => handleRelease(direction),
36
+ onMouseDown: () => handlePress(direction),
37
+ onMouseUp: () => handleRelease(direction),
38
+ onMouseLeave: () => handleRelease(direction),
39
+ children: label
40
+ },
41
+ direction
42
+ );
43
+ if (leftRightOnly) {
44
+ return /* @__PURE__ */ jsxs("div", { className: `${styles.padContainer} ${styles.horizontal} ${className || ""}`, children: [
45
+ createButton("left", "\u25C0"),
46
+ createButton("right", "\u25B6")
47
+ ] });
48
+ }
49
+ if (upDownOnly) {
50
+ return /* @__PURE__ */ jsxs("div", { className: `${styles.padContainer} ${styles.vertical} ${className || ""}`, children: [
51
+ createButton("up", "\u25B2"),
52
+ createButton("down", "\u25BC")
53
+ ] });
54
+ }
55
+ return /* @__PURE__ */ jsxs("div", { className: `${styles.padContainer} ${styles.full} ${className || ""}`, children: [
56
+ /* @__PURE__ */ jsx("div", { className: styles.row, children: createButton("up", "\u25B2") }),
57
+ /* @__PURE__ */ jsxs("div", { className: styles.row, children: [
58
+ createButton("left", "\u25C0"),
59
+ createButton("right", "\u25B6")
60
+ ] }),
61
+ /* @__PURE__ */ jsx("div", { className: styles.row, children: createButton("down", "\u25BC") })
62
+ ] });
63
+ }
64
+
65
+ export { DirectionPad };
66
+ //# sourceMappingURL=DirectionPad.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectionPad.js","sources":["../../../src/components/DirectionPad.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - DirectionPad Component\n *\n * 4-direction or 2-direction control pad\n */\n\nimport { useCallback, useRef } from 'react';\nimport type { DirectionPadProps } from '../types';\nimport styles from './DirectionPad.module.css';\n\n/**\n * DirectionPad - For directional input\n *\n * @example\n * ```tsx\n * // 4 directions\n * <DirectionPad onDirection={(dir) => send('move', { direction: dir })} />\n *\n * // Left/Right only\n * <DirectionPad leftRightOnly onDirection={(dir) => send('move', { direction: dir })} />\n * ```\n */\nexport function DirectionPad({\n onDirection,\n leftRightOnly = false,\n upDownOnly = false,\n className,\n}: DirectionPadProps) {\n const pressedRef = useRef<Set<string>>(new Set());\n\n const handlePress = useCallback((direction: 'up' | 'down' | 'left' | 'right') => {\n if (pressedRef.current.has(direction)) return;\n pressedRef.current.add(direction);\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(10);\n }\n\n onDirection(direction);\n }, [onDirection]);\n\n const handleRelease = useCallback((direction: string) => {\n pressedRef.current.delete(direction);\n }, []);\n\n const createButton = (direction: 'up' | 'down' | 'left' | 'right', label: string) => (\n <button\n key={direction}\n className={`${styles.dirButton} ${styles[direction]}`}\n onTouchStart={(e) => {\n e.preventDefault();\n handlePress(direction);\n }}\n onTouchEnd={(e) => {\n e.preventDefault();\n handleRelease(direction);\n }}\n onTouchCancel={() => handleRelease(direction)}\n onMouseDown={() => handlePress(direction)}\n onMouseUp={() => handleRelease(direction)}\n onMouseLeave={() => handleRelease(direction)}\n >\n {label}\n </button>\n );\n\n if (leftRightOnly) {\n return (\n <div className={`${styles.padContainer} ${styles.horizontal} ${className || ''}`}>\n {createButton('left', '◀')}\n {createButton('right', '▶')}\n </div>\n );\n }\n\n if (upDownOnly) {\n return (\n <div className={`${styles.padContainer} ${styles.vertical} ${className || ''}`}>\n {createButton('up', '▲')}\n {createButton('down', '▼')}\n </div>\n );\n }\n\n return (\n <div className={`${styles.padContainer} ${styles.full} ${className || ''}`}>\n <div className={styles.row}>\n {createButton('up', '▲')}\n </div>\n <div className={styles.row}>\n {createButton('left', '◀')}\n {createButton('right', '▶')}\n </div>\n <div className={styles.row}>\n {createButton('down', '▼')}\n </div>\n </div>\n );\n}\n\nexport default DirectionPad;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".DirectionPad-module_padContainer__iL-rh{align-items:center;display:flex;flex-direction:column;gap:8px;user-select:none;-webkit-user-select:none}.DirectionPad-module_horizontal__kI4j7{flex-direction:row;gap:16px}.DirectionPad-module_vertical__b8Xec{flex-direction:column;gap:16px}.DirectionPad-module_row__mzuUr{display:flex;gap:8px}.DirectionPad-module_dirButton__QCCHz{-webkit-tap-highlight-color:transparent;align-items:center;background:var(--color-surface,#374151);border:none;border-radius:12px;color:#fff;cursor:pointer;display:flex;font-size:24px;height:70px;justify-content:center;touch-action:manipulation;transition:transform .1s ease,background .1s ease;width:70px}.DirectionPad-module_dirButton__QCCHz:active{background:var(--color-primary,#6366f1);transform:scale(.9)}.DirectionPad-module_horizontal__kI4j7 .DirectionPad-module_dirButton__QCCHz,.DirectionPad-module_vertical__b8Xec .DirectionPad-module_dirButton__QCCHz{font-size:32px;height:100px;width:100px}";
4
+ var styles = {"padContainer":"DirectionPad-module_padContainer__iL-rh","horizontal":"DirectionPad-module_horizontal__kI4j7","vertical":"DirectionPad-module_vertical__b8Xec","row":"DirectionPad-module_row__mzuUr","dirButton":"DirectionPad-module_dirButton__QCCHz"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=DirectionPad.module.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectionPad.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,55 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useRef, useCallback } from 'react';
3
+ import styles from './HoldButton.module.css.js';
4
+
5
+ function HoldButton({
6
+ onHoldStart,
7
+ onHoldEnd,
8
+ children,
9
+ className,
10
+ disabled = false
11
+ }) {
12
+ const isHolding = useRef(false);
13
+ const buttonRef = useRef(null);
14
+ const startHold = useCallback(() => {
15
+ if (disabled || isHolding.current) return;
16
+ isHolding.current = true;
17
+ buttonRef.current?.classList.add(styles.pressed);
18
+ if (navigator.vibrate) {
19
+ navigator.vibrate(10);
20
+ }
21
+ onHoldStart();
22
+ }, [onHoldStart, disabled]);
23
+ const endHold = useCallback(() => {
24
+ if (!isHolding.current) return;
25
+ isHolding.current = false;
26
+ buttonRef.current?.classList.remove(styles.pressed);
27
+ onHoldEnd();
28
+ }, [onHoldEnd]);
29
+ const handleTouchStart = useCallback((e) => {
30
+ e.preventDefault();
31
+ startHold();
32
+ }, [startHold]);
33
+ const handleTouchEnd = useCallback((e) => {
34
+ e.preventDefault();
35
+ endHold();
36
+ }, [endHold]);
37
+ return /* @__PURE__ */ jsx(
38
+ "button",
39
+ {
40
+ ref: buttonRef,
41
+ className: `${styles.holdButton} ${className || ""} ${disabled ? styles.disabled : ""}`,
42
+ onTouchStart: handleTouchStart,
43
+ onTouchEnd: handleTouchEnd,
44
+ onTouchCancel: handleTouchEnd,
45
+ onMouseDown: startHold,
46
+ onMouseUp: endHold,
47
+ onMouseLeave: endHold,
48
+ disabled,
49
+ children
50
+ }
51
+ );
52
+ }
53
+
54
+ export { HoldButton };
55
+ //# sourceMappingURL=HoldButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoldButton.js","sources":["../../../src/components/HoldButton.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - HoldButton Component\n *\n * Button that detects hold start/end events\n */\n\nimport { useRef, useCallback } from 'react';\nimport type React from 'react';\nimport type { HoldButtonProps } from '../types';\nimport styles from './HoldButton.module.css';\n\n/**\n * HoldButton - For hold/release input patterns\n *\n * @example\n * ```tsx\n * <HoldButton\n * onHoldStart={() => send('charge', { type: 'start' })}\n * onHoldEnd={() => send('charge', { type: 'end' })}\n * >\n * HOLD\n * </HoldButton>\n * ```\n */\nexport function HoldButton({\n onHoldStart,\n onHoldEnd,\n children,\n className,\n disabled = false,\n}: HoldButtonProps) {\n const isHolding = useRef(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const startHold = useCallback(() => {\n if (disabled || isHolding.current) return;\n isHolding.current = true;\n buttonRef.current?.classList.add(styles.pressed || '');\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(10);\n }\n\n onHoldStart();\n }, [onHoldStart, disabled]);\n\n const endHold = useCallback(() => {\n if (!isHolding.current) return;\n isHolding.current = false;\n buttonRef.current?.classList.remove(styles.pressed || '');\n onHoldEnd();\n }, [onHoldEnd]);\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n e.preventDefault();\n startHold();\n }, [startHold]);\n\n const handleTouchEnd = useCallback((e: React.TouchEvent) => {\n e.preventDefault();\n endHold();\n }, [endHold]);\n\n return (\n <button\n ref={buttonRef}\n className={`${styles.holdButton} ${className || ''} ${disabled ? styles.disabled : ''}`}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={handleTouchEnd}\n onMouseDown={startHold}\n onMouseUp={endHold}\n onMouseLeave={endHold}\n disabled={disabled}\n >\n {children}\n </button>\n );\n}\n\nexport default HoldButton;\n"],"names":[],"mappings":";;;;AAwBO,SAAS,UAAA,CAAW;AAAA,EACzB,WAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAAoB;AAClB,EAAA,MAAM,SAAA,GAAY,OAAO,KAAK,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAY,OAA0B,IAAI,CAAA;AAEhD,EAAA,MAAM,SAAA,GAAY,YAAY,MAAM;AAClC,IAAA,IAAI,QAAA,IAAY,UAAU,OAAA,EAAS;AACnC,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,OAAa,CAAA;AAGrD,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,WAAA,EAAY;AAAA,EACd,CAAA,EAAG,CAAC,WAAA,EAAa,QAAQ,CAAC,CAAA;AAE1B,EAAA,MAAM,OAAA,GAAU,YAAY,MAAM;AAChC,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACxB,IAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,MAAA,CAAO,MAAA,CAAO,OAAa,CAAA;AACxD,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,CAAC,CAAA,KAAwB;AAC5D,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,CAAC,CAAA,KAAwB;AAC1D,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,SAAA,EAAW,CAAA,EAAG,MAAA,CAAO,UAAU,CAAA,CAAA,EAAI,SAAA,IAAa,EAAE,CAAA,CAAA,EAAI,QAAA,GAAW,MAAA,CAAO,QAAA,GAAW,EAAE,CAAA,CAAA;AAAA,MACrF,YAAA,EAAc,gBAAA;AAAA,MACd,UAAA,EAAY,cAAA;AAAA,MACZ,aAAA,EAAe,cAAA;AAAA,MACf,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,OAAA;AAAA,MACX,YAAA,EAAc,OAAA;AAAA,MACd,QAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;;;;"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".HoldButton-module_holdButton__tu4mi{-webkit-tap-highlight-color:transparent;align-items:center;background:var(--color-secondary,#f59e0b);border:none;border-radius:16px;color:#fff;cursor:pointer;display:flex;font-size:18px;font-weight:700;justify-content:center;min-height:80px;min-width:80px;padding:16px 24px;touch-action:manipulation;transition:transform .1s ease,background .1s ease;user-select:none;-webkit-user-select:none}.HoldButton-module_holdButton__tu4mi:active,.HoldButton-module_pressed__JWIRG{background:var(--color-secondary-dark,#d97706);transform:scale(.95)}.HoldButton-module_disabled__4QwwT{cursor:not-allowed;opacity:.5}.HoldButton-module_disabled__4QwwT.HoldButton-module_pressed__JWIRG,.HoldButton-module_disabled__4QwwT:active{background:var(--color-secondary,#f59e0b);transform:none}";
4
+ var styles = {"holdButton":"HoldButton-module_holdButton__tu4mi","pressed":"HoldButton-module_pressed__JWIRG","disabled":"HoldButton-module_disabled__4QwwT"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=HoldButton.module.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoldButton.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,56 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useRef, useCallback } from 'react';
3
+ import styles from './SwipeArea.module.css.js';
4
+
5
+ function SwipeArea({
6
+ onSwipe,
7
+ threshold = 50,
8
+ children,
9
+ className
10
+ }) {
11
+ const touchStart = useRef(null);
12
+ const handleTouchStart = useCallback((e) => {
13
+ const touch = e.touches[0];
14
+ if (!touch) return;
15
+ touchStart.current = { x: touch.clientX, y: touch.clientY };
16
+ }, []);
17
+ const handleTouchEnd = useCallback((e) => {
18
+ if (!touchStart.current) return;
19
+ const touch = e.changedTouches[0];
20
+ if (!touch) return;
21
+ const deltaX = touch.clientX - touchStart.current.x;
22
+ const deltaY = touch.clientY - touchStart.current.y;
23
+ const absX = Math.abs(deltaX);
24
+ const absY = Math.abs(deltaY);
25
+ if (absX < threshold && absY < threshold) {
26
+ touchStart.current = null;
27
+ return;
28
+ }
29
+ let direction;
30
+ if (absX > absY) {
31
+ direction = deltaX > 0 ? "right" : "left";
32
+ } else {
33
+ direction = deltaY > 0 ? "down" : "up";
34
+ }
35
+ if (navigator.vibrate) {
36
+ navigator.vibrate(15);
37
+ }
38
+ onSwipe(direction);
39
+ touchStart.current = null;
40
+ }, [onSwipe, threshold]);
41
+ return /* @__PURE__ */ jsx(
42
+ "div",
43
+ {
44
+ className: `${styles.swipeArea} ${className || ""}`,
45
+ onTouchStart: handleTouchStart,
46
+ onTouchEnd: handleTouchEnd,
47
+ onTouchCancel: () => {
48
+ touchStart.current = null;
49
+ },
50
+ children
51
+ }
52
+ );
53
+ }
54
+
55
+ export { SwipeArea };
56
+ //# sourceMappingURL=SwipeArea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwipeArea.js","sources":["../../../src/components/SwipeArea.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - SwipeArea Component\n *\n * Detects swipe gestures\n */\n\nimport { useRef, useCallback } from 'react';\nimport type React from 'react';\nimport type { SwipeAreaProps } from '../types';\nimport styles from './SwipeArea.module.css';\n\n/**\n * SwipeArea - For swipe gesture input\n *\n * @example\n * ```tsx\n * <SwipeArea onSwipe={(dir) => send('swipe', { direction: dir })}>\n * <div>Swipe here!</div>\n * </SwipeArea>\n * ```\n */\nexport function SwipeArea({\n onSwipe,\n threshold = 50,\n children,\n className,\n}: SwipeAreaProps) {\n const touchStart = useRef<{ x: number; y: number } | null>(null);\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n const touch = e.touches[0];\n if (!touch) return;\n touchStart.current = { x: touch.clientX, y: touch.clientY };\n }, []);\n\n const handleTouchEnd = useCallback((e: React.TouchEvent) => {\n if (!touchStart.current) return;\n\n const touch = e.changedTouches[0];\n if (!touch) return;\n const deltaX = touch.clientX - touchStart.current.x;\n const deltaY = touch.clientY - touchStart.current.y;\n\n const absX = Math.abs(deltaX);\n const absY = Math.abs(deltaY);\n\n // Check if swipe exceeds threshold\n if (absX < threshold && absY < threshold) {\n touchStart.current = null;\n return;\n }\n\n // Determine direction\n let direction: 'up' | 'down' | 'left' | 'right';\n if (absX > absY) {\n direction = deltaX > 0 ? 'right' : 'left';\n } else {\n direction = deltaY > 0 ? 'down' : 'up';\n }\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(15);\n }\n\n onSwipe(direction);\n touchStart.current = null;\n }, [onSwipe, threshold]);\n\n return (\n <div\n className={`${styles.swipeArea} ${className || ''}`}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={() => { touchStart.current = null; }}\n >\n {children}\n </div>\n );\n}\n\nexport default SwipeArea;\n"],"names":[],"mappings":";;;;AAqBO,SAAS,SAAA,CAAU;AAAA,EACxB,OAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,UAAA,GAAa,OAAwC,IAAI,CAAA;AAE/D,EAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,CAAC,CAAA,KAAwB;AAC5D,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AACzB,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,UAAA,CAAW,UAAU,EAAE,CAAA,EAAG,MAAM,OAAA,EAAS,CAAA,EAAG,MAAM,OAAA,EAAQ;AAAA,EAC5D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,CAAC,CAAA,KAAwB;AAC1D,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AAEzB,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,cAAA,CAAe,CAAC,CAAA;AAChC,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,CAAA;AAClD,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,CAAA;AAElD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC5B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAG5B,IAAA,IAAI,IAAA,GAAO,SAAA,IAAa,IAAA,GAAO,SAAA,EAAW;AACxC,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,SAAA,GAAY,MAAA,GAAS,IAAI,OAAA,GAAU,MAAA;AAAA,IACrC,CAAA,MAAO;AACL,MAAA,SAAA,GAAY,MAAA,GAAS,IAAI,MAAA,GAAS,IAAA;AAAA,IACpC;AAGA,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,OAAA,CAAQ,SAAS,CAAA;AACjB,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,EACvB,CAAA,EAAG,CAAC,OAAA,EAAS,SAAS,CAAC,CAAA;AAEvB,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAW,CAAA,EAAG,MAAA,CAAO,SAAS,CAAA,CAAA,EAAI,aAAa,EAAE,CAAA,CAAA;AAAA,MACjD,YAAA,EAAc,gBAAA;AAAA,MACd,UAAA,EAAY,cAAA;AAAA,MACZ,eAAe,MAAM;AAAE,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MAAM,CAAA;AAAA,MAEjD;AAAA;AAAA,GACH;AAEJ;;;;"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".SwipeArea-module_swipeArea__yob7L{height:100%;touch-action:none;user-select:none;-webkit-user-select:none;width:100%}";
4
+ var styles = {"swipeArea":"SwipeArea-module_swipeArea__yob7L"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=SwipeArea.module.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwipeArea.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,56 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useRef, useCallback } from 'react';
3
+ import styles from './TapButton.module.css.js';
4
+
5
+ function TapButton({
6
+ onTap,
7
+ children,
8
+ className,
9
+ disabled = false
10
+ }) {
11
+ const isPressed = useRef(false);
12
+ const buttonRef = useRef(null);
13
+ const handleTouchStart = useCallback((e) => {
14
+ if (disabled) return;
15
+ e.preventDefault();
16
+ isPressed.current = true;
17
+ buttonRef.current?.classList.add(styles.pressed);
18
+ if (navigator.vibrate) {
19
+ navigator.vibrate(10);
20
+ }
21
+ onTap();
22
+ }, [onTap, disabled]);
23
+ const handleTouchEnd = useCallback((e) => {
24
+ e.preventDefault();
25
+ isPressed.current = false;
26
+ buttonRef.current?.classList.remove(styles.pressed);
27
+ }, []);
28
+ const handleMouseDown = useCallback(() => {
29
+ if (disabled) return;
30
+ isPressed.current = true;
31
+ buttonRef.current?.classList.add(styles.pressed);
32
+ onTap();
33
+ }, [onTap, disabled]);
34
+ const handleMouseUp = useCallback(() => {
35
+ isPressed.current = false;
36
+ buttonRef.current?.classList.remove(styles.pressed);
37
+ }, []);
38
+ return /* @__PURE__ */ jsx(
39
+ "button",
40
+ {
41
+ ref: buttonRef,
42
+ className: `${styles.tapButton} ${className || ""} ${disabled ? styles.disabled : ""}`,
43
+ onTouchStart: handleTouchStart,
44
+ onTouchEnd: handleTouchEnd,
45
+ onTouchCancel: handleTouchEnd,
46
+ onMouseDown: handleMouseDown,
47
+ onMouseUp: handleMouseUp,
48
+ onMouseLeave: handleMouseUp,
49
+ disabled,
50
+ children
51
+ }
52
+ );
53
+ }
54
+
55
+ export { TapButton };
56
+ //# sourceMappingURL=TapButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TapButton.js","sources":["../../../src/components/TapButton.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - TapButton Component\n *\n * Optimized touch button with haptic feedback\n */\n\nimport { useRef, useCallback } from 'react';\nimport type React from 'react';\nimport type { TapButtonProps } from '../types';\nimport styles from './TapButton.module.css';\n\n/**\n * TapButton - Optimized for mobile touch input\n *\n * @example\n * ```tsx\n * <TapButton onTap={() => send('tap')}>\n * TAP!\n * </TapButton>\n * ```\n */\nexport function TapButton({\n onTap,\n children,\n className,\n disabled = false,\n}: TapButtonProps) {\n const isPressed = useRef(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n if (disabled) return;\n e.preventDefault();\n isPressed.current = true;\n buttonRef.current?.classList.add(styles.pressed || '');\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(10);\n }\n\n onTap();\n }, [onTap, disabled]);\n\n const handleTouchEnd = useCallback((e: React.TouchEvent) => {\n e.preventDefault();\n isPressed.current = false;\n buttonRef.current?.classList.remove(styles.pressed || '');\n }, []);\n\n const handleMouseDown = useCallback(() => {\n if (disabled) return;\n isPressed.current = true;\n buttonRef.current?.classList.add(styles.pressed || '');\n onTap();\n }, [onTap, disabled]);\n\n const handleMouseUp = useCallback(() => {\n isPressed.current = false;\n buttonRef.current?.classList.remove(styles.pressed || '');\n }, []);\n\n return (\n <button\n ref={buttonRef}\n className={`${styles.tapButton} ${className || ''} ${disabled ? styles.disabled : ''}`}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={handleTouchEnd}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n disabled={disabled}\n >\n {children}\n </button>\n );\n}\n\nexport default TapButton;\n"],"names":[],"mappings":";;;;AAqBO,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAAmB;AACjB,EAAA,MAAM,SAAA,GAAY,OAAO,KAAK,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAY,OAA0B,IAAI,CAAA;AAEhD,EAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,CAAC,CAAA,KAAwB;AAC5D,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,OAAa,CAAA;AAGrD,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,KAAA,EAAM;AAAA,EACR,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,CAAC,CAAA,KAAwB;AAC1D,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,MAAA,CAAO,MAAA,CAAO,OAAa,CAAA;AAAA,EAC1D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,eAAA,GAAkB,YAAY,MAAM;AACxC,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,GAAA,CAAI,MAAA,CAAO,OAAa,CAAA;AACrD,IAAA,KAAA,EAAM;AAAA,EACR,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,MAAM,aAAA,GAAgB,YAAY,MAAM;AACtC,IAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,MAAA,CAAO,MAAA,CAAO,OAAa,CAAA;AAAA,EAC1D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,SAAA,EAAW,CAAA,EAAG,MAAA,CAAO,SAAS,CAAA,CAAA,EAAI,SAAA,IAAa,EAAE,CAAA,CAAA,EAAI,QAAA,GAAW,MAAA,CAAO,QAAA,GAAW,EAAE,CAAA,CAAA;AAAA,MACpF,YAAA,EAAc,gBAAA;AAAA,MACd,UAAA,EAAY,cAAA;AAAA,MACZ,aAAA,EAAe,cAAA;AAAA,MACf,WAAA,EAAa,eAAA;AAAA,MACb,SAAA,EAAW,aAAA;AAAA,MACX,YAAA,EAAc,aAAA;AAAA,MACd,QAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;;;;"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js';
2
+
3
+ var css_248z = ".TapButton-module_tapButton__dqJr9{-webkit-tap-highlight-color:transparent;align-items:center;background:var(--color-primary,#6366f1);border:none;border-radius:16px;color:#fff;cursor:pointer;display:flex;font-size:18px;font-weight:700;justify-content:center;min-height:80px;min-width:80px;padding:16px 24px;touch-action:manipulation;transition:transform .1s ease,background .1s ease;user-select:none;-webkit-user-select:none}.TapButton-module_pressed__Z2nfR,.TapButton-module_tapButton__dqJr9:active{background:var(--color-primary-dark,#4f46e5);transform:scale(.95)}.TapButton-module_disabled__3bR6q{cursor:not-allowed;opacity:.5}.TapButton-module_disabled__3bR6q.TapButton-module_pressed__Z2nfR,.TapButton-module_disabled__3bR6q:active{background:var(--color-primary,#6366f1);transform:none}";
4
+ var styles = {"tapButton":"TapButton-module_tapButton__dqJr9","pressed":"TapButton-module_pressed__Z2nfR","disabled":"TapButton-module_disabled__3bR6q"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=TapButton.module.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TapButton.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}