@smoregg/sdk 1.2.0 → 2.0.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 (179) hide show
  1. package/dist/cjs/config.cjs.map +1 -1
  2. package/dist/cjs/controller.cjs +215 -145
  3. package/dist/cjs/controller.cjs.map +1 -1
  4. package/dist/cjs/screen.cjs +220 -178
  5. package/dist/cjs/screen.cjs.map +1 -1
  6. package/dist/cjs/testing.cjs +160 -151
  7. package/dist/cjs/testing.cjs.map +1 -1
  8. package/dist/esm/config.js.map +1 -1
  9. package/dist/esm/controller.js +216 -146
  10. package/dist/esm/controller.js.map +1 -1
  11. package/dist/esm/screen.js +221 -179
  12. package/dist/esm/screen.js.map +1 -1
  13. package/dist/esm/testing.js +160 -151
  14. package/dist/esm/testing.js.map +1 -1
  15. package/dist/types/config.d.ts +1 -2
  16. package/dist/types/config.d.ts.map +1 -1
  17. package/dist/types/controller.d.ts +22 -43
  18. package/dist/types/controller.d.ts.map +1 -1
  19. package/dist/types/index.d.ts +14 -14
  20. package/dist/types/index.d.ts.map +1 -1
  21. package/dist/types/screen.d.ts +26 -37
  22. package/dist/types/screen.d.ts.map +1 -1
  23. package/dist/types/testing.d.ts +16 -0
  24. package/dist/types/testing.d.ts.map +1 -1
  25. package/dist/types/types.d.ts +244 -338
  26. package/dist/types/types.d.ts.map +1 -1
  27. package/dist/umd/smore-sdk.umd.js +595 -474
  28. package/dist/umd/smore-sdk.umd.js.map +1 -1
  29. package/dist/umd/smore-sdk.umd.min.js +1 -1
  30. package/dist/umd/smore-sdk.umd.min.js.map +1 -1
  31. package/package.json +1 -1
  32. package/dist/cjs/SmoreHost.cjs +0 -306
  33. package/dist/cjs/SmoreHost.cjs.map +0 -1
  34. package/dist/cjs/SmorePlayer.cjs +0 -229
  35. package/dist/cjs/SmorePlayer.cjs.map +0 -1
  36. package/dist/cjs/components/DirectionPad.cjs +0 -68
  37. package/dist/cjs/components/DirectionPad.cjs.map +0 -1
  38. package/dist/cjs/components/DirectionPad.module.css.cjs +0 -12
  39. package/dist/cjs/components/DirectionPad.module.css.cjs.map +0 -1
  40. package/dist/cjs/components/HoldButton.cjs +0 -57
  41. package/dist/cjs/components/HoldButton.cjs.map +0 -1
  42. package/dist/cjs/components/HoldButton.module.css.cjs +0 -12
  43. package/dist/cjs/components/HoldButton.module.css.cjs.map +0 -1
  44. package/dist/cjs/components/IframeGameBridge.cjs +0 -115
  45. package/dist/cjs/components/IframeGameBridge.cjs.map +0 -1
  46. package/dist/cjs/components/SwipeArea.cjs +0 -58
  47. package/dist/cjs/components/SwipeArea.cjs.map +0 -1
  48. package/dist/cjs/components/SwipeArea.module.css.cjs +0 -12
  49. package/dist/cjs/components/SwipeArea.module.css.cjs.map +0 -1
  50. package/dist/cjs/components/TapButton.cjs +0 -58
  51. package/dist/cjs/components/TapButton.cjs.map +0 -1
  52. package/dist/cjs/components/TapButton.module.css.cjs +0 -12
  53. package/dist/cjs/components/TapButton.module.css.cjs.map +0 -1
  54. package/dist/cjs/context/RoomProvider.cjs +0 -118
  55. package/dist/cjs/context/RoomProvider.cjs.map +0 -1
  56. package/dist/cjs/hooks/useExternalGames.cjs +0 -49
  57. package/dist/cjs/hooks/useExternalGames.cjs.map +0 -1
  58. package/dist/cjs/hooks/useGameHost.cjs +0 -206
  59. package/dist/cjs/hooks/useGameHost.cjs.map +0 -1
  60. package/dist/cjs/hooks/useGamePlayer.cjs +0 -134
  61. package/dist/cjs/hooks/useGamePlayer.cjs.map +0 -1
  62. package/dist/cjs/iframe/index.cjs +0 -260
  63. package/dist/cjs/iframe/index.cjs.map +0 -1
  64. package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs +0 -33
  65. package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs.map +0 -1
  66. package/dist/cjs/server/index.cjs +0 -45
  67. package/dist/cjs/server/index.cjs.map +0 -1
  68. package/dist/cjs/transport/DirectTransport.cjs +0 -23
  69. package/dist/cjs/transport/DirectTransport.cjs.map +0 -1
  70. package/dist/cjs/utils/connectionMonitor.cjs +0 -77
  71. package/dist/cjs/utils/connectionMonitor.cjs.map +0 -1
  72. package/dist/cjs/utils/preloadAssets.cjs +0 -66
  73. package/dist/cjs/utils/preloadAssets.cjs.map +0 -1
  74. package/dist/cjs/utils/serverTime.cjs +0 -43
  75. package/dist/cjs/utils/serverTime.cjs.map +0 -1
  76. package/dist/esm/SmoreHost.js +0 -304
  77. package/dist/esm/SmoreHost.js.map +0 -1
  78. package/dist/esm/SmorePlayer.js +0 -227
  79. package/dist/esm/SmorePlayer.js.map +0 -1
  80. package/dist/esm/components/DirectionPad.js +0 -66
  81. package/dist/esm/components/DirectionPad.js.map +0 -1
  82. package/dist/esm/components/DirectionPad.module.css.js +0 -8
  83. package/dist/esm/components/DirectionPad.module.css.js.map +0 -1
  84. package/dist/esm/components/HoldButton.js +0 -55
  85. package/dist/esm/components/HoldButton.js.map +0 -1
  86. package/dist/esm/components/HoldButton.module.css.js +0 -8
  87. package/dist/esm/components/HoldButton.module.css.js.map +0 -1
  88. package/dist/esm/components/IframeGameBridge.js +0 -113
  89. package/dist/esm/components/IframeGameBridge.js.map +0 -1
  90. package/dist/esm/components/SwipeArea.js +0 -56
  91. package/dist/esm/components/SwipeArea.js.map +0 -1
  92. package/dist/esm/components/SwipeArea.module.css.js +0 -8
  93. package/dist/esm/components/SwipeArea.module.css.js.map +0 -1
  94. package/dist/esm/components/TapButton.js +0 -56
  95. package/dist/esm/components/TapButton.js.map +0 -1
  96. package/dist/esm/components/TapButton.module.css.js +0 -8
  97. package/dist/esm/components/TapButton.module.css.js.map +0 -1
  98. package/dist/esm/context/RoomProvider.js +0 -109
  99. package/dist/esm/context/RoomProvider.js.map +0 -1
  100. package/dist/esm/hooks/useExternalGames.js +0 -47
  101. package/dist/esm/hooks/useExternalGames.js.map +0 -1
  102. package/dist/esm/hooks/useGameHost.js +0 -204
  103. package/dist/esm/hooks/useGameHost.js.map +0 -1
  104. package/dist/esm/hooks/useGamePlayer.js +0 -132
  105. package/dist/esm/hooks/useGamePlayer.js.map +0 -1
  106. package/dist/esm/iframe/index.js +0 -257
  107. package/dist/esm/iframe/index.js.map +0 -1
  108. package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js +0 -29
  109. package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js.map +0 -1
  110. package/dist/esm/server/index.js +0 -43
  111. package/dist/esm/server/index.js.map +0 -1
  112. package/dist/esm/transport/DirectTransport.js +0 -21
  113. package/dist/esm/transport/DirectTransport.js.map +0 -1
  114. package/dist/esm/utils/connectionMonitor.js +0 -75
  115. package/dist/esm/utils/connectionMonitor.js.map +0 -1
  116. package/dist/esm/utils/preloadAssets.js +0 -63
  117. package/dist/esm/utils/preloadAssets.js.map +0 -1
  118. package/dist/esm/utils/serverTime.js +0 -41
  119. package/dist/esm/utils/serverTime.js.map +0 -1
  120. package/dist/types/SmoreHost.d.ts +0 -187
  121. package/dist/types/SmoreHost.d.ts.map +0 -1
  122. package/dist/types/SmorePlayer.d.ts +0 -146
  123. package/dist/types/SmorePlayer.d.ts.map +0 -1
  124. package/dist/types/components/DirectionPad.d.ts +0 -21
  125. package/dist/types/components/DirectionPad.d.ts.map +0 -1
  126. package/dist/types/components/HoldButton.d.ts +0 -22
  127. package/dist/types/components/HoldButton.d.ts.map +0 -1
  128. package/dist/types/components/IframeGameBridge.d.ts +0 -38
  129. package/dist/types/components/IframeGameBridge.d.ts.map +0 -1
  130. package/dist/types/components/SwipeArea.d.ts +0 -19
  131. package/dist/types/components/SwipeArea.d.ts.map +0 -1
  132. package/dist/types/components/TapButton.d.ts +0 -19
  133. package/dist/types/components/TapButton.d.ts.map +0 -1
  134. package/dist/types/components/index.d.ts +0 -6
  135. package/dist/types/components/index.d.ts.map +0 -1
  136. package/dist/types/context/RoomProvider.d.ts +0 -69
  137. package/dist/types/context/RoomProvider.d.ts.map +0 -1
  138. package/dist/types/context/index.d.ts +0 -3
  139. package/dist/types/context/index.d.ts.map +0 -1
  140. package/dist/types/dev/DevSimulator.d.ts +0 -31
  141. package/dist/types/dev/DevSimulator.d.ts.map +0 -1
  142. package/dist/types/dev/index.d.ts +0 -2
  143. package/dist/types/dev/index.d.ts.map +0 -1
  144. package/dist/types/hooks/index.d.ts +0 -7
  145. package/dist/types/hooks/index.d.ts.map +0 -1
  146. package/dist/types/hooks/useExternalGames.d.ts +0 -32
  147. package/dist/types/hooks/useExternalGames.d.ts.map +0 -1
  148. package/dist/types/hooks/useGameHost.d.ts +0 -67
  149. package/dist/types/hooks/useGameHost.d.ts.map +0 -1
  150. package/dist/types/hooks/useGamePlayer.d.ts +0 -55
  151. package/dist/types/hooks/useGamePlayer.d.ts.map +0 -1
  152. package/dist/types/iframe/IframeRoomProvider.d.ts +0 -31
  153. package/dist/types/iframe/IframeRoomProvider.d.ts.map +0 -1
  154. package/dist/types/iframe/index.d.ts +0 -18
  155. package/dist/types/iframe/index.d.ts.map +0 -1
  156. package/dist/types/iframe/vanilla-entry.d.ts +0 -7
  157. package/dist/types/iframe/vanilla-entry.d.ts.map +0 -1
  158. package/dist/types/iframe/vanilla.d.ts +0 -49
  159. package/dist/types/iframe/vanilla.d.ts.map +0 -1
  160. package/dist/types/server/createGameRelay.d.ts +0 -26
  161. package/dist/types/server/createGameRelay.d.ts.map +0 -1
  162. package/dist/types/server/index.d.ts +0 -3
  163. package/dist/types/server/index.d.ts.map +0 -1
  164. package/dist/types/utils/connectionMonitor.d.ts +0 -57
  165. package/dist/types/utils/connectionMonitor.d.ts.map +0 -1
  166. package/dist/types/utils/index.d.ts +0 -7
  167. package/dist/types/utils/index.d.ts.map +0 -1
  168. package/dist/types/utils/preloadAssets.d.ts +0 -29
  169. package/dist/types/utils/preloadAssets.d.ts.map +0 -1
  170. package/dist/types/utils/serverTime.d.ts +0 -28
  171. package/dist/types/utils/serverTime.d.ts.map +0 -1
  172. package/dist/umd/smore-sdk-iframe.umd.js +0 -266
  173. package/dist/umd/smore-sdk-iframe.umd.js.map +0 -1
  174. package/dist/umd/smore-sdk-iframe.umd.min.js +0 -2
  175. package/dist/umd/smore-sdk-iframe.umd.min.js.map +0 -1
  176. package/dist/umd/smore-sdk-vanilla.umd.js +0 -1275
  177. package/dist/umd/smore-sdk-vanilla.umd.js.map +0 -1
  178. package/dist/umd/smore-sdk-vanilla.umd.min.js +0 -2
  179. package/dist/umd/smore-sdk-vanilla.umd.min.js.map +0 -1
@@ -1,66 +0,0 @@
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
@@ -1 +0,0 @@
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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"}
@@ -1,8 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"DirectionPad.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -1,55 +0,0 @@
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
@@ -1 +0,0 @@
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;;;;"}
@@ -1,8 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"HoldButton.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -1,113 +0,0 @@
1
- import { jsx } from 'react/jsx-runtime';
2
- import { useRef, useCallback, useEffect } from 'react';
3
- import { isSmoreMessage } from '../transport/protocol.js';
4
-
5
- const IframeGameBridge = ({
6
- gameId,
7
- url,
8
- socket,
9
- side,
10
- roomCode,
11
- players,
12
- leaderId,
13
- myIndex,
14
- isLeader,
15
- onReady,
16
- onLoaded,
17
- onGameOver,
18
- style,
19
- className
20
- }) => {
21
- const iframeRef = useRef(null);
22
- const readyRef = useRef(false);
23
- const loadedRef = useRef(false);
24
- const postToIframe = useCallback((msg) => {
25
- iframeRef.current?.contentWindow?.postMessage(msg, "*");
26
- }, []);
27
- useEffect(() => {
28
- const handler = (e) => {
29
- if (e.source !== iframeRef.current?.contentWindow) return;
30
- const msg = e.data;
31
- if (!isSmoreMessage(msg)) return;
32
- if (msg.type === "smore:ready" && !readyRef.current) {
33
- readyRef.current = true;
34
- postToIframe({
35
- type: "smore:init",
36
- payload: {
37
- side,
38
- roomCode,
39
- players,
40
- leaderId,
41
- myIndex,
42
- isLeader
43
- }
44
- });
45
- onReady?.();
46
- setTimeout(() => {
47
- if (!loadedRef.current) {
48
- console.warn("[IframeGameBridge] Game did not send smore:loaded, auto-triggering");
49
- loadedRef.current = true;
50
- onLoaded?.();
51
- }
52
- }, 2e3);
53
- }
54
- if (msg.type === "smore:loaded" && !loadedRef.current) {
55
- loadedRef.current = true;
56
- onLoaded?.();
57
- }
58
- if (msg.type === "smore:emit") {
59
- const { event, data, ackId } = msg.payload;
60
- if (event === "room:game-over") {
61
- onGameOver?.(data?.results);
62
- }
63
- if (ackId) {
64
- socket.emit(event, data, (response) => {
65
- postToIframe({ type: "smore:ack", payload: { ackId, data: response } });
66
- });
67
- } else {
68
- socket.emit(event, data);
69
- }
70
- }
71
- };
72
- window.addEventListener("message", handler);
73
- return () => window.removeEventListener("message", handler);
74
- }, [socket, side, roomCode, players, leaderId, myIndex, isLeader, onReady, onLoaded, onGameOver, postToIframe]);
75
- useEffect(() => {
76
- if (!readyRef.current) return;
77
- postToIframe({
78
- type: "smore:update",
79
- payload: { players, leaderId }
80
- });
81
- }, [players, leaderId, postToIframe]);
82
- useEffect(() => {
83
- if (!socket) return;
84
- const handler = (event, ...args) => {
85
- postToIframe({
86
- type: "smore:event",
87
- payload: { event, data: args[0] }
88
- });
89
- };
90
- socket.onAny(handler);
91
- return () => {
92
- socket.offAny(handler);
93
- };
94
- }, [socket, postToIframe]);
95
- return /* @__PURE__ */ jsx(
96
- "iframe",
97
- {
98
- ref: iframeRef,
99
- src: url,
100
- sandbox: "allow-scripts allow-same-origin",
101
- style: {
102
- border: "none",
103
- width: "100%",
104
- height: "100%",
105
- ...style
106
- },
107
- className
108
- }
109
- );
110
- };
111
-
112
- export { IframeGameBridge };
113
- //# sourceMappingURL=IframeGameBridge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"IframeGameBridge.js","sources":["../../../src/components/IframeGameBridge.tsx"],"sourcesContent":["/**\n * IframeGameBridge - Parent-side bridge between iframe and Socket.IO.\n *\n * Renders an iframe loading the external game URL.\n * Bridges postMessage ↔ Socket.IO:\n * - iframe sends `smore:emit` → bridge relays to `socket.emit()` as-is\n * - socket receives events → bridge relays to iframe via `smore:event` as-is\n *\n * No event translation is performed; events are passed through unchanged.\n *\n * Used by GameOverlay (host) and GameView (player) when the game type is 'external'.\n */\n\nimport React, { useEffect, useRef, useCallback } from 'react';\nimport type { Socket } from 'socket.io-client';\nimport { isSmoreMessage } from '../transport/protocol';\nimport type { SmoreEmitMessage } from '../transport/protocol';\n\ninterface Player {\n playerIndex: number;\n name: string;\n connected?: boolean;\n}\n\nexport interface IframeGameBridgeProps {\n gameId: string;\n url: string;\n socket: Socket;\n side: 'host' | 'player';\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n myIndex?: number;\n isLeader?: boolean;\n onReady?: () => void;\n onLoaded?: () => void;\n onGameOver?: (results: any) => void;\n style?: React.CSSProperties;\n className?: string;\n}\n\nexport const IframeGameBridge: React.FC<IframeGameBridgeProps> = ({\n gameId,\n url,\n socket,\n side,\n roomCode,\n players,\n leaderId,\n myIndex,\n isLeader,\n onReady,\n onLoaded,\n onGameOver,\n style,\n className,\n}) => {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const readyRef = useRef(false);\n const loadedRef = useRef(false);\n\n // Send message to iframe\n const postToIframe = useCallback((msg: object) => {\n iframeRef.current?.contentWindow?.postMessage(msg, '*');\n }, []);\n\n // Handle messages from iframe (smore:ready, smore:emit)\n useEffect(() => {\n const handler = (e: MessageEvent) => {\n if (e.source !== iframeRef.current?.contentWindow) return;\n\n const msg = e.data;\n if (!isSmoreMessage(msg)) return;\n\n if (msg.type === 'smore:ready' && !readyRef.current) {\n readyRef.current = true;\n\n postToIframe({\n type: 'smore:init',\n payload: {\n side,\n roomCode,\n players,\n leaderId,\n myIndex,\n isLeader,\n },\n });\n\n onReady?.();\n\n // Fallback: if game doesn't send smore:loaded within 2s, auto-trigger\n setTimeout(() => {\n if (!loadedRef.current) {\n console.warn('[IframeGameBridge] Game did not send smore:loaded, auto-triggering');\n loadedRef.current = true;\n onLoaded?.();\n }\n }, 2000);\n }\n\n if (msg.type === 'smore:loaded' && !loadedRef.current) {\n loadedRef.current = true;\n onLoaded?.();\n }\n\n if (msg.type === 'smore:emit') {\n const { event, data, ackId } = (msg as SmoreEmitMessage).payload;\n\n // Intercept game-over\n if (event === 'room:game-over') {\n onGameOver?.(data?.results);\n }\n\n if (ackId) {\n socket.emit(event, data, (response: any) => {\n postToIframe({ type: 'smore:ack', payload: { ackId, data: response } });\n });\n } else {\n socket.emit(event, data);\n }\n }\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [socket, side, roomCode, players, leaderId, myIndex, isLeader, onReady, onLoaded, onGameOver, postToIframe]);\n\n // Push player/leader updates to iframe after init\n useEffect(() => {\n if (!readyRef.current) return;\n postToIframe({\n type: 'smore:update',\n payload: { players, leaderId },\n });\n }, [players, leaderId, postToIframe]);\n\n // Bridge socket events to iframe\n useEffect(() => {\n if (!socket) return;\n\n const handler = (event: string, ...args: any[]) => {\n postToIframe({\n type: 'smore:event',\n payload: { event, data: args[0] },\n });\n };\n\n socket.onAny(handler);\n return () => {\n socket.offAny(handler);\n };\n }, [socket, postToIframe]);\n\n return (\n <iframe\n ref={iframeRef}\n src={url}\n sandbox=\"allow-scripts allow-same-origin\"\n style={{\n border: 'none',\n width: '100%',\n height: '100%',\n ...style,\n }}\n className={className}\n />\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,56 +0,0 @@
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
@@ -1 +0,0 @@
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;;;;"}
@@ -1,8 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"SwipeArea.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -1,56 +0,0 @@
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
@@ -1 +0,0 @@
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;;;;"}
@@ -1,8 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"TapButton.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -1,109 +0,0 @@
1
- import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useMemo, useContext } from 'react';
3
- import { DirectTransport } from '../transport/DirectTransport.js';
4
-
5
- const TransportContext = createContext(null);
6
- function useTransport() {
7
- const transport = useContext(TransportContext);
8
- if (!transport) {
9
- throw new Error("useTransport must be used within a RoomProvider that supplies a Transport");
10
- }
11
- return transport;
12
- }
13
- const RoomContext = createContext(null);
14
- const HostRoomProvider = ({
15
- roomCode,
16
- players,
17
- leaderId,
18
- socket,
19
- children
20
- }) => {
21
- const connectedPlayers = useMemo(
22
- () => players.filter((p) => p.connected !== false),
23
- [players]
24
- );
25
- const hostState = useMemo(
26
- () => ({ roomCode, players, connectedPlayers, leaderId, socket }),
27
- [roomCode, players, connectedPlayers, leaderId, socket]
28
- );
29
- const value = useMemo(
30
- () => ({
31
- roomCode,
32
- players,
33
- connectedPlayers,
34
- leaderId,
35
- side: "host",
36
- host: hostState,
37
- player: null
38
- }),
39
- [roomCode, players, connectedPlayers, leaderId, hostState]
40
- );
41
- const transport = useMemo(() => new DirectTransport(socket), [socket]);
42
- return /* @__PURE__ */ jsx(TransportContext.Provider, { value: transport, children: /* @__PURE__ */ jsx(RoomContext.Provider, { value, children }) });
43
- };
44
- const PlayerRoomProvider = ({
45
- roomCode,
46
- players,
47
- leaderId,
48
- myIndex,
49
- isLeader,
50
- socket,
51
- isConnected,
52
- children
53
- }) => {
54
- const connectedPlayers = useMemo(
55
- () => players.filter((p) => p.connected !== false),
56
- [players]
57
- );
58
- const playerState = useMemo(
59
- () => ({
60
- roomCode,
61
- players,
62
- connectedPlayers,
63
- leaderId,
64
- myIndex,
65
- isLeader,
66
- socket,
67
- isConnected
68
- }),
69
- [roomCode, players, connectedPlayers, leaderId, myIndex, isLeader, socket, isConnected]
70
- );
71
- const value = useMemo(
72
- () => ({
73
- roomCode,
74
- players,
75
- connectedPlayers,
76
- leaderId,
77
- side: "player",
78
- host: null,
79
- player: playerState
80
- }),
81
- [roomCode, players, connectedPlayers, leaderId, playerState]
82
- );
83
- const transport = useMemo(() => new DirectTransport(socket), [socket]);
84
- return /* @__PURE__ */ jsx(TransportContext.Provider, { value: transport, children: /* @__PURE__ */ jsx(RoomContext.Provider, { value, children }) });
85
- };
86
- function useRoom() {
87
- const context = useContext(RoomContext);
88
- if (!context) {
89
- throw new Error("useRoom must be used within HostRoomProvider or PlayerRoomProvider");
90
- }
91
- return context;
92
- }
93
- function useHostRoom() {
94
- const context = useRoom();
95
- if (context.side !== "host" || !context.host) {
96
- throw new Error("useHostRoom must be used within HostRoomProvider");
97
- }
98
- return context.host;
99
- }
100
- function usePlayerRoom() {
101
- const context = useRoom();
102
- if (context.side !== "player" || !context.player) {
103
- throw new Error("usePlayerRoom must be used within PlayerRoomProvider");
104
- }
105
- return context.player;
106
- }
107
-
108
- export { HostRoomProvider, PlayerRoomProvider, RoomContext, TransportContext, useHostRoom, usePlayerRoom, useRoom, useTransport };
109
- //# sourceMappingURL=RoomProvider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RoomProvider.js","sources":["../../../src/context/RoomProvider.tsx"],"sourcesContent":["/**\n * RoomProvider - SDK Room Context\n *\n * Foundation context that all other SDK hooks depend on.\n * Provides room state (players, roomCode, leaderId) for both host and player sides.\n *\n * Also provides a Transport abstraction via TransportContext.\n * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.\n * - IframeRoomProvider (external) provides a PostMessageTransport.\n *\n * Usage:\n * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>\n * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} myIndex={...} isLeader={...} socket={...} isConnected={...}>\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { Player } from '@smoregg/shared';\nimport type { Socket } from 'socket.io-client';\nimport type { Transport } from '../transport/types';\nimport { DirectTransport } from '../transport/DirectTransport';\n\n// ===== Transport Context =====\n\nconst TransportContext = createContext<Transport | null>(null);\n\nexport function useTransport(): Transport {\n const transport = useContext(TransportContext);\n if (!transport) {\n throw new Error('useTransport must be used within a RoomProvider that supplies a Transport');\n }\n return transport;\n}\n\nexport { TransportContext };\n\n// ===== State Types =====\n\nexport interface RoomState {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n}\n\nexport interface HostRoomState extends RoomState {\n socket: Socket;\n}\n\nexport interface PlayerRoomState extends RoomState {\n myIndex: number;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n}\n\nexport interface RoomContextValue {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n side: 'host' | 'player';\n host: HostRoomState | null;\n player: PlayerRoomState | null;\n}\n\n// ===== Context =====\n\nexport const RoomContext = createContext<RoomContextValue | null>(null);\n\n// ===== Host Provider =====\n\ninterface HostRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n socket: Socket;\n children: React.ReactNode;\n}\n\nexport const HostRoomProvider: React.FC<HostRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n socket,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const hostState: HostRoomState = useMemo(\n () => ({ roomCode, players, connectedPlayers, leaderId, socket }),\n [roomCode, players, connectedPlayers, leaderId, socket]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'host' as const,\n host: hostState,\n player: null,\n }),\n [roomCode, players, connectedPlayers, leaderId, hostState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Player Provider =====\n\ninterface PlayerRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n myIndex: number;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n children: React.ReactNode;\n}\n\nexport const PlayerRoomProvider: React.FC<PlayerRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n myIndex,\n isLeader,\n socket,\n isConnected,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const playerState: PlayerRoomState = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n myIndex,\n isLeader,\n socket,\n isConnected,\n }),\n [roomCode, players, connectedPlayers, leaderId, myIndex, isLeader, socket, isConnected]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'player' as const,\n host: null,\n player: playerState,\n }),\n [roomCode, players, connectedPlayers, leaderId, playerState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Hooks =====\n\nexport function useRoom(): RoomContextValue {\n const context = useContext(RoomContext);\n if (!context) {\n throw new Error('useRoom must be used within HostRoomProvider or PlayerRoomProvider');\n }\n return context;\n}\n\nexport function useHostRoom(): HostRoomState {\n const context = useRoom();\n if (context.side !== 'host' || !context.host) {\n throw new Error('useHostRoom must be used within HostRoomProvider');\n }\n return context.host;\n}\n\nexport function usePlayerRoom(): PlayerRoomState {\n const context = useRoom();\n if (context.side !== 'player' || !context.player) {\n throw new Error('usePlayerRoom must be used within PlayerRoomProvider');\n }\n return context.player;\n}\n"],"names":[],"mappings":"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"}
@@ -1,47 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
-
3
- function useExternalGames(config) {
4
- const { serverUrl, enabled = true } = config;
5
- const [games, setGames] = useState([]);
6
- const [loading, setLoading] = useState(false);
7
- const [error, setError] = useState(null);
8
- const [refreshKey, setRefreshKey] = useState(0);
9
- useEffect(() => {
10
- if (!enabled) return;
11
- let cancelled = false;
12
- setLoading(true);
13
- fetch(`${serverUrl}/api/games`).then((res) => res.json()).then((data) => {
14
- if (cancelled) return;
15
- const external = (data.games || []).map((g) => ({
16
- id: g.id,
17
- title: g.title,
18
- description: g.description || "",
19
- minPlayers: g.minPlayers || 2,
20
- maxPlayers: g.maxPlayers || 8,
21
- thumbnail: g.thumbnail || "/thumbnails/g8.jpeg",
22
- categories: g.categories || ["party"],
23
- type: "external",
24
- hostUrl: g.hostUrl,
25
- playerUrl: g.playerUrl,
26
- available: !!(g.hostUrl && g.playerUrl),
27
- rating: 4,
28
- heroRequired: false
29
- }));
30
- setGames(external);
31
- setError(null);
32
- }).catch((err) => {
33
- if (cancelled) return;
34
- setError(err.message);
35
- }).finally(() => {
36
- if (!cancelled) setLoading(false);
37
- });
38
- return () => {
39
- cancelled = true;
40
- };
41
- }, [serverUrl, enabled, refreshKey]);
42
- const refresh = () => setRefreshKey((k) => k + 1);
43
- return { games, loading, error, refresh };
44
- }
45
-
46
- export { useExternalGames };
47
- //# sourceMappingURL=useExternalGames.js.map