@nice2dev/game-engine 0.1.0 → 1.0.3

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 (294) hide show
  1. package/CHANGELOG.md +193 -1
  2. package/dist/cjs/ai/BehaviorTree.js +1215 -0
  3. package/dist/cjs/ai/BehaviorTree.js.map +1 -0
  4. package/dist/cjs/ai/StateMachine.js +783 -0
  5. package/dist/cjs/ai/StateMachine.js.map +1 -0
  6. package/dist/cjs/audio/AudioBridge.js +454 -0
  7. package/dist/cjs/audio/AudioBridge.js.map +1 -0
  8. package/dist/cjs/devtools/GameplayAnalytics.js +651 -0
  9. package/dist/cjs/devtools/GameplayAnalytics.js.map +1 -0
  10. package/dist/cjs/dialogue/DialogueSystem.js +1023 -0
  11. package/dist/cjs/dialogue/DialogueSystem.js.map +1 -0
  12. package/dist/cjs/editor/NiceGameEditor.js +569 -71
  13. package/dist/cjs/editor/NiceGameEditor.js.map +1 -1
  14. package/dist/cjs/editor/ShaderGraph.js +1616 -0
  15. package/dist/cjs/editor/ShaderGraph.js.map +1 -0
  16. package/dist/cjs/editor/TimelineEditor.js +819 -0
  17. package/dist/cjs/editor/TimelineEditor.js.map +1 -0
  18. package/dist/cjs/engine/SaveSystemV2.js +494 -0
  19. package/dist/cjs/engine/SaveSystemV2.js.map +1 -0
  20. package/dist/cjs/export/GodotExporter.js +1102 -0
  21. package/dist/cjs/export/GodotExporter.js.map +1 -0
  22. package/dist/cjs/export/PlatformExporter.js +236 -0
  23. package/dist/cjs/export/PlatformExporter.js.map +1 -0
  24. package/dist/cjs/export/ThreeJSExporter.js +1116 -0
  25. package/dist/cjs/export/ThreeJSExporter.js.map +1 -0
  26. package/dist/cjs/export/UnityExporter.js +1193 -0
  27. package/dist/cjs/export/UnityExporter.js.map +1 -0
  28. package/dist/cjs/export/WebExporter.js +1036 -0
  29. package/dist/cjs/export/WebExporter.js.map +1 -0
  30. package/dist/cjs/export/index.js +58 -0
  31. package/dist/cjs/export/index.js.map +1 -0
  32. package/dist/cjs/i18n/useTranslation.js +11 -11
  33. package/dist/cjs/import/AsepriteImporter.js +761 -0
  34. package/dist/cjs/import/AsepriteImporter.js.map +1 -0
  35. package/dist/cjs/import/DragonBonesImporter.js +499 -0
  36. package/dist/cjs/import/DragonBonesImporter.js.map +1 -0
  37. package/dist/cjs/import/GameMakerImporter.js +559 -0
  38. package/dist/cjs/import/GameMakerImporter.js.map +1 -0
  39. package/dist/cjs/import/GodotSceneImporter.js +824 -0
  40. package/dist/cjs/import/GodotSceneImporter.js.map +1 -0
  41. package/dist/cjs/import/LDtkImporter.js +481 -0
  42. package/dist/cjs/import/LDtkImporter.js.map +1 -0
  43. package/dist/cjs/import/Live2DImporter.js +553 -0
  44. package/dist/cjs/import/Live2DImporter.js.map +1 -0
  45. package/dist/cjs/import/NdgFormat.js +499 -0
  46. package/dist/cjs/import/NdgFormat.js.map +1 -0
  47. package/dist/cjs/import/OgmoImporter.js +529 -0
  48. package/dist/cjs/import/OgmoImporter.js.map +1 -0
  49. package/dist/cjs/import/RPGMakerImporter.js +520 -0
  50. package/dist/cjs/import/RPGMakerImporter.js.map +1 -0
  51. package/dist/cjs/import/SceneImporter.js +449 -0
  52. package/dist/cjs/import/SceneImporter.js.map +1 -0
  53. package/dist/cjs/import/SpineImporter.js +583 -0
  54. package/dist/cjs/import/SpineImporter.js.map +1 -0
  55. package/dist/cjs/import/SpriterImporter.js +652 -0
  56. package/dist/cjs/import/SpriterImporter.js.map +1 -0
  57. package/dist/cjs/import/TiledMapImporter.js +859 -0
  58. package/dist/cjs/import/TiledMapImporter.js.map +1 -0
  59. package/dist/cjs/import/UnitySceneImporter.js +732 -0
  60. package/dist/cjs/import/UnitySceneImporter.js.map +1 -0
  61. package/dist/cjs/import/index.js +305 -0
  62. package/dist/cjs/import/index.js.map +1 -0
  63. package/dist/cjs/index.js +291 -1
  64. package/dist/cjs/index.js.map +1 -1
  65. package/dist/cjs/input/GamepadNavigation.js +21 -21
  66. package/dist/cjs/input/useGamepads.js +6 -6
  67. package/dist/cjs/integration/IconSprite.js +281 -0
  68. package/dist/cjs/integration/IconSprite.js.map +1 -0
  69. package/dist/cjs/inventory/InventorySystem.js +930 -0
  70. package/dist/cjs/inventory/InventorySystem.js.map +1 -0
  71. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AbortController.js.map +1 -1
  72. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js.map +1 -1
  73. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js.map +1 -1
  74. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js.map +1 -1
  75. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Errors.js.map +1 -1
  76. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js.map +1 -1
  77. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js.map +1 -1
  78. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js.map +1 -1
  79. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpClient.js.map +1 -1
  80. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js.map +1 -1
  81. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnection.js.map +1 -1
  82. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js.map +1 -1
  83. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js.map +1 -1
  84. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ILogger.js.map +1 -1
  85. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ITransport.js.map +1 -1
  86. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js.map +1 -1
  87. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Loggers.js.map +1 -1
  88. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js.map +1 -1
  89. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js.map +1 -1
  90. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js.map +1 -1
  91. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Subject.js.map +1 -1
  92. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js.map +1 -1
  93. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Utils.js.map +1 -1
  94. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js.map +1 -1
  95. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js.map +1 -1
  96. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/pkg-version.js.map +1 -1
  97. package/dist/cjs/quest/QuestSystem.js +924 -0
  98. package/dist/cjs/quest/QuestSystem.js.map +1 -0
  99. package/dist/cjs/rendering/WebGPURenderPipeline.js +658 -0
  100. package/dist/cjs/rendering/WebGPURenderPipeline.js.map +1 -0
  101. package/dist/cjs/scripting/GraphToAST.js +567 -0
  102. package/dist/cjs/scripting/GraphToAST.js.map +1 -0
  103. package/dist/cjs/scripting/LanguageExporter.js +321 -0
  104. package/dist/cjs/scripting/LanguageExporter.js.map +1 -0
  105. package/dist/cjs/scripting/ScriptAST.js +67 -0
  106. package/dist/cjs/scripting/ScriptAST.js.map +1 -0
  107. package/dist/cjs/scripting/VisualScripting2.js +1140 -0
  108. package/dist/cjs/scripting/VisualScripting2.js.map +1 -0
  109. package/dist/cjs/scripting/exporters/CSharpExporter.js +503 -0
  110. package/dist/cjs/scripting/exporters/CSharpExporter.js.map +1 -0
  111. package/dist/cjs/scripting/exporters/GDScriptExporter.js +452 -0
  112. package/dist/cjs/scripting/exporters/GDScriptExporter.js.map +1 -0
  113. package/dist/cjs/scripting/exporters/LuaExporter.js +457 -0
  114. package/dist/cjs/scripting/exporters/LuaExporter.js.map +1 -0
  115. package/dist/cjs/scripting/exporters/PythonExporter.js +565 -0
  116. package/dist/cjs/scripting/exporters/PythonExporter.js.map +1 -0
  117. package/dist/cjs/scripting/exporters/RustExporter.js +525 -0
  118. package/dist/cjs/scripting/exporters/RustExporter.js.map +1 -0
  119. package/dist/cjs/scripting/exporters/TypeScriptExporter.js +570 -0
  120. package/dist/cjs/scripting/exporters/TypeScriptExporter.js.map +1 -0
  121. package/dist/cjs/systems/ParticleSystem2.js +1478 -0
  122. package/dist/cjs/systems/ParticleSystem2.js.map +1 -0
  123. package/dist/cjs/xr/ARVR.js.map +1 -1
  124. package/dist/esm/ai/BehaviorTree.js +1186 -0
  125. package/dist/esm/ai/BehaviorTree.js.map +1 -0
  126. package/dist/esm/ai/StateMachine.js +767 -0
  127. package/dist/esm/ai/StateMachine.js.map +1 -0
  128. package/dist/esm/audio/AudioBridge.js +446 -0
  129. package/dist/esm/audio/AudioBridge.js.map +1 -0
  130. package/dist/esm/devtools/GameplayAnalytics.js +639 -0
  131. package/dist/esm/devtools/GameplayAnalytics.js.map +1 -0
  132. package/dist/esm/dialogue/DialogueSystem.js +1008 -0
  133. package/dist/esm/dialogue/DialogueSystem.js.map +1 -0
  134. package/dist/esm/editor/NiceGameEditor.js +556 -58
  135. package/dist/esm/editor/NiceGameEditor.js.map +1 -1
  136. package/dist/esm/editor/ShaderGraph.js +1606 -0
  137. package/dist/esm/editor/ShaderGraph.js.map +1 -0
  138. package/dist/esm/editor/TimelineEditor.js +800 -0
  139. package/dist/esm/editor/TimelineEditor.js.map +1 -0
  140. package/dist/esm/engine/SaveSystemV2.js +487 -0
  141. package/dist/esm/engine/SaveSystemV2.js.map +1 -0
  142. package/dist/esm/export/GodotExporter.js +1100 -0
  143. package/dist/esm/export/GodotExporter.js.map +1 -0
  144. package/dist/esm/export/PlatformExporter.js +230 -0
  145. package/dist/esm/export/PlatformExporter.js.map +1 -0
  146. package/dist/esm/export/ThreeJSExporter.js +1114 -0
  147. package/dist/esm/export/ThreeJSExporter.js.map +1 -0
  148. package/dist/esm/export/UnityExporter.js +1191 -0
  149. package/dist/esm/export/UnityExporter.js.map +1 -0
  150. package/dist/esm/export/WebExporter.js +1033 -0
  151. package/dist/esm/export/WebExporter.js.map +1 -0
  152. package/dist/esm/export/index.js +44 -0
  153. package/dist/esm/export/index.js.map +1 -0
  154. package/dist/esm/import/AsepriteImporter.js +759 -0
  155. package/dist/esm/import/AsepriteImporter.js.map +1 -0
  156. package/dist/esm/import/DragonBonesImporter.js +496 -0
  157. package/dist/esm/import/DragonBonesImporter.js.map +1 -0
  158. package/dist/esm/import/GameMakerImporter.js +556 -0
  159. package/dist/esm/import/GameMakerImporter.js.map +1 -0
  160. package/dist/esm/import/GodotSceneImporter.js +822 -0
  161. package/dist/esm/import/GodotSceneImporter.js.map +1 -0
  162. package/dist/esm/import/LDtkImporter.js +479 -0
  163. package/dist/esm/import/LDtkImporter.js.map +1 -0
  164. package/dist/esm/import/Live2DImporter.js +550 -0
  165. package/dist/esm/import/Live2DImporter.js.map +1 -0
  166. package/dist/esm/import/NdgFormat.js +490 -0
  167. package/dist/esm/import/NdgFormat.js.map +1 -0
  168. package/dist/esm/import/OgmoImporter.js +526 -0
  169. package/dist/esm/import/OgmoImporter.js.map +1 -0
  170. package/dist/esm/import/RPGMakerImporter.js +517 -0
  171. package/dist/esm/import/RPGMakerImporter.js.map +1 -0
  172. package/dist/esm/import/SceneImporter.js +441 -0
  173. package/dist/esm/import/SceneImporter.js.map +1 -0
  174. package/dist/esm/import/SpineImporter.js +580 -0
  175. package/dist/esm/import/SpineImporter.js.map +1 -0
  176. package/dist/esm/import/SpriterImporter.js +649 -0
  177. package/dist/esm/import/SpriterImporter.js.map +1 -0
  178. package/dist/esm/import/TiledMapImporter.js +857 -0
  179. package/dist/esm/import/TiledMapImporter.js.map +1 -0
  180. package/dist/esm/import/UnitySceneImporter.js +730 -0
  181. package/dist/esm/import/UnitySceneImporter.js.map +1 -0
  182. package/dist/esm/import/index.js +279 -0
  183. package/dist/esm/import/index.js.map +1 -0
  184. package/dist/esm/index.js +47 -3
  185. package/dist/esm/index.js.map +1 -1
  186. package/dist/esm/integration/IconSprite.js +266 -0
  187. package/dist/esm/integration/IconSprite.js.map +1 -0
  188. package/dist/esm/inventory/InventorySystem.js +924 -0
  189. package/dist/esm/inventory/InventorySystem.js.map +1 -0
  190. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AbortController.js.map +1 -1
  191. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js.map +1 -1
  192. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js.map +1 -1
  193. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js.map +1 -1
  194. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Errors.js.map +1 -1
  195. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js.map +1 -1
  196. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js.map +1 -1
  197. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js.map +1 -1
  198. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpClient.js.map +1 -1
  199. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js.map +1 -1
  200. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnection.js.map +1 -1
  201. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js.map +1 -1
  202. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js.map +1 -1
  203. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ILogger.js.map +1 -1
  204. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ITransport.js.map +1 -1
  205. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js.map +1 -1
  206. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Loggers.js.map +1 -1
  207. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js.map +1 -1
  208. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js.map +1 -1
  209. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js.map +1 -1
  210. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Subject.js.map +1 -1
  211. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js.map +1 -1
  212. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Utils.js.map +1 -1
  213. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js.map +1 -1
  214. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js.map +1 -1
  215. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/pkg-version.js.map +1 -1
  216. package/dist/esm/quest/QuestSystem.js +916 -0
  217. package/dist/esm/quest/QuestSystem.js.map +1 -0
  218. package/dist/esm/rendering/WebGPURenderPipeline.js +642 -0
  219. package/dist/esm/rendering/WebGPURenderPipeline.js.map +1 -0
  220. package/dist/esm/scripting/GraphToAST.js +564 -0
  221. package/dist/esm/scripting/GraphToAST.js.map +1 -0
  222. package/dist/esm/scripting/LanguageExporter.js +311 -0
  223. package/dist/esm/scripting/LanguageExporter.js.map +1 -0
  224. package/dist/esm/scripting/ScriptAST.js +52 -0
  225. package/dist/esm/scripting/ScriptAST.js.map +1 -0
  226. package/dist/esm/scripting/VisualScripting2.js +1130 -0
  227. package/dist/esm/scripting/VisualScripting2.js.map +1 -0
  228. package/dist/esm/scripting/exporters/CSharpExporter.js +501 -0
  229. package/dist/esm/scripting/exporters/CSharpExporter.js.map +1 -0
  230. package/dist/esm/scripting/exporters/GDScriptExporter.js +450 -0
  231. package/dist/esm/scripting/exporters/GDScriptExporter.js.map +1 -0
  232. package/dist/esm/scripting/exporters/LuaExporter.js +455 -0
  233. package/dist/esm/scripting/exporters/LuaExporter.js.map +1 -0
  234. package/dist/esm/scripting/exporters/PythonExporter.js +563 -0
  235. package/dist/esm/scripting/exporters/PythonExporter.js.map +1 -0
  236. package/dist/esm/scripting/exporters/RustExporter.js +523 -0
  237. package/dist/esm/scripting/exporters/RustExporter.js.map +1 -0
  238. package/dist/esm/scripting/exporters/TypeScriptExporter.js +568 -0
  239. package/dist/esm/scripting/exporters/TypeScriptExporter.js.map +1 -0
  240. package/dist/esm/systems/ParticleSystem2.js +1471 -0
  241. package/dist/esm/systems/ParticleSystem2.js.map +1 -0
  242. package/dist/esm/xr/ARVR.js.map +1 -1
  243. package/dist/types/__tests__/setup.d.ts +1 -1
  244. package/dist/types/ai/BehaviorTree.d.ts +375 -0
  245. package/dist/types/ai/StateMachine.d.ts +296 -0
  246. package/dist/types/audio/AudioBridge.d.ts +199 -0
  247. package/dist/types/devtools/GameplayAnalytics.d.ts +279 -0
  248. package/dist/types/dialogue/DialogueSystem.d.ts +326 -0
  249. package/dist/types/dialogue/index.d.ts +2 -0
  250. package/dist/types/editor/NiceGameEditor.d.ts +12 -1
  251. package/dist/types/editor/ShaderGraph.d.ts +207 -0
  252. package/dist/types/editor/TimelineEditor.d.ts +393 -0
  253. package/dist/types/engine/SaveSystemV2.d.ts +155 -0
  254. package/dist/types/export/GodotExporter.d.ts +56 -0
  255. package/dist/types/export/PlatformExporter.d.ts +201 -0
  256. package/dist/types/export/ThreeJSExporter.d.ts +40 -0
  257. package/dist/types/export/UnityExporter.d.ts +69 -0
  258. package/dist/types/export/WebExporter.d.ts +58 -0
  259. package/dist/types/export/index.d.ts +19 -0
  260. package/dist/types/import/AsepriteImporter.d.ts +46 -0
  261. package/dist/types/import/DragonBonesImporter.d.ts +331 -0
  262. package/dist/types/import/GameMakerImporter.d.ts +375 -0
  263. package/dist/types/import/GodotSceneImporter.d.ts +34 -0
  264. package/dist/types/import/LDtkImporter.d.ts +177 -0
  265. package/dist/types/import/Live2DImporter.d.ts +237 -0
  266. package/dist/types/import/NdgFormat.d.ts +387 -0
  267. package/dist/types/import/OgmoImporter.d.ts +237 -0
  268. package/dist/types/import/RPGMakerImporter.d.ts +186 -0
  269. package/dist/types/import/SceneImporter.d.ts +276 -0
  270. package/dist/types/import/SpineImporter.d.ts +372 -0
  271. package/dist/types/import/SpriterImporter.d.ts +230 -0
  272. package/dist/types/import/TiledMapImporter.d.ts +57 -0
  273. package/dist/types/import/UnitySceneImporter.d.ts +87 -0
  274. package/dist/types/import/index.d.ts +59 -0
  275. package/dist/types/index.d.ts +46 -18
  276. package/dist/types/integration/IconSprite.d.ts +196 -0
  277. package/dist/types/inventory/InventorySystem.d.ts +336 -0
  278. package/dist/types/performance/WebGPUCompute.d.ts +0 -10
  279. package/dist/types/quest/QuestSystem.d.ts +287 -0
  280. package/dist/types/rendering/WebGPURenderPipeline.d.ts +255 -0
  281. package/dist/types/scripting/GraphToAST.d.ts +55 -0
  282. package/dist/types/scripting/LanguageExporter.d.ts +136 -0
  283. package/dist/types/scripting/ScriptAST.d.ts +312 -0
  284. package/dist/types/scripting/VisualScripting2.d.ts +353 -0
  285. package/dist/types/scripting/exporters/CSharpExporter.d.ts +44 -0
  286. package/dist/types/scripting/exporters/GDScriptExporter.d.ts +46 -0
  287. package/dist/types/scripting/exporters/LuaExporter.d.ts +46 -0
  288. package/dist/types/scripting/exporters/PythonExporter.d.ts +49 -0
  289. package/dist/types/scripting/exporters/RustExporter.d.ts +46 -0
  290. package/dist/types/scripting/exporters/TypeScriptExporter.d.ts +48 -0
  291. package/dist/types/scripting/exporters/index.d.ts +8 -0
  292. package/dist/types/scripting/index.d.ts +11 -0
  293. package/dist/types/systems/ParticleSystem2.d.ts +646 -0
  294. package/package.json +7 -1
@@ -0,0 +1,651 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ /* ────────────────────────────────────────────────────────────────
6
+ Gameplay Analytics — Telemetry, heatmaps & session recording
7
+
8
+ Comprehensive gameplay analytics with:
9
+ - Event-based telemetry pipeline with batching
10
+ - Spatial heatmaps (death, traversal, interaction, combat)
11
+ - Session recording and playback
12
+ - Funnel analysis and retention tracking
13
+ - Performance metrics collection
14
+ ──────────────────────────────────────────────────────────────── */
15
+ const DEFAULT_TELEMETRY_CONFIG = {
16
+ enabled: true,
17
+ batchSize: 50,
18
+ flushIntervalMs: 30000,
19
+ maxBufferSize: 10000,
20
+ categories: [],
21
+ sampleRate: 1,
22
+ };
23
+ const DEFAULT_HEATMAP_CONFIG = {
24
+ type: 'death',
25
+ cellSize: 1,
26
+ bounds: { minX: -50, minY: -50, maxX: 50, maxY: 50 },
27
+ colorStops: [
28
+ { value: 0, color: 'rgba(0, 0, 255, 0)' },
29
+ { value: 0.25, color: 'rgba(0, 0, 255, 0.5)' },
30
+ { value: 0.5, color: 'rgba(0, 255, 0, 0.7)' },
31
+ { value: 0.75, color: 'rgba(255, 255, 0, 0.8)' },
32
+ { value: 1, color: 'rgba(255, 0, 0, 1)' },
33
+ ],
34
+ maxValue: 0,
35
+ blurRadius: 1,
36
+ };
37
+ const DEFAULT_RECORDING_CONFIG = {
38
+ enabled: false,
39
+ fps: 10,
40
+ maxDurationMs: 600000, // 10 minutes
41
+ recordTypes: ['position', 'action', 'state-change'],
42
+ recordPosition: true,
43
+ compress: true,
44
+ };
45
+ /* ══════════════════════════════════════════════════════════════
46
+ TELEMETRY PIPELINE
47
+ ══════════════════════════════════════════════════════════════ */
48
+ class TelemetryPipeline {
49
+ constructor(eventBus, config = {}) {
50
+ this.buffer = [];
51
+ this.flushed = [];
52
+ this.flushTimer = null;
53
+ this.eventCounter = 0;
54
+ this.config = { ...DEFAULT_TELEMETRY_CONFIG, ...config };
55
+ this.eventBus = eventBus;
56
+ this.sessionId = this.generateId();
57
+ if (this.config.enabled)
58
+ this.startFlushTimer();
59
+ }
60
+ generateId() {
61
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
62
+ }
63
+ /** Track a telemetry event */
64
+ track(category, name, data = {}, position) {
65
+ if (!this.config.enabled)
66
+ return;
67
+ if (this.config.categories.length > 0 && !this.config.categories.includes(category))
68
+ return;
69
+ if (this.config.sampleRate < 1 && Math.random() > this.config.sampleRate)
70
+ return;
71
+ const event = {
72
+ id: `evt-${++this.eventCounter}`,
73
+ category,
74
+ name,
75
+ timestamp: Date.now(),
76
+ sessionId: this.sessionId,
77
+ data,
78
+ position,
79
+ };
80
+ this.buffer.push(event);
81
+ if (this.buffer.length >= this.config.batchSize) {
82
+ this.flush();
83
+ }
84
+ // Trim buffer if too large
85
+ if (this.buffer.length > this.config.maxBufferSize) {
86
+ this.buffer = this.buffer.slice(-this.config.maxBufferSize);
87
+ }
88
+ }
89
+ /** Flush buffered events */
90
+ flush() {
91
+ if (this.buffer.length === 0)
92
+ return [];
93
+ const batch = [...this.buffer];
94
+ this.buffer = [];
95
+ this.flushed.push(batch);
96
+ this.eventBus.emit('analytics:flush', { count: batch.length });
97
+ return batch;
98
+ }
99
+ startFlushTimer() {
100
+ this.flushTimer = setInterval(() => this.flush(), this.config.flushIntervalMs);
101
+ }
102
+ /** Get all events (current buffer + flushed) */
103
+ getAllEvents() {
104
+ return [...this.flushed.flat(), ...this.buffer];
105
+ }
106
+ /** Get events by category */
107
+ getByCategory(category) {
108
+ return this.getAllEvents().filter(e => e.category === category);
109
+ }
110
+ /** Get event count by name */
111
+ countByName(name) {
112
+ return this.getAllEvents().filter(e => e.name === name).length;
113
+ }
114
+ getSessionId() {
115
+ return this.sessionId;
116
+ }
117
+ getBufferSize() {
118
+ return this.buffer.length;
119
+ }
120
+ getTotalEvents() {
121
+ return this.flushed.reduce((s, b) => s + b.length, 0) + this.buffer.length;
122
+ }
123
+ clear() {
124
+ this.buffer = [];
125
+ this.flushed = [];
126
+ this.eventCounter = 0;
127
+ }
128
+ destroy() {
129
+ if (this.flushTimer)
130
+ clearInterval(this.flushTimer);
131
+ this.flush();
132
+ }
133
+ }
134
+ /* ══════════════════════════════════════════════════════════════
135
+ HEATMAP GENERATOR
136
+ ══════════════════════════════════════════════════════════════ */
137
+ class HeatmapGenerator {
138
+ constructor(config = {}) {
139
+ this.grid = new Map();
140
+ this.totalEvents = 0;
141
+ this.config = { ...DEFAULT_HEATMAP_CONFIG, ...config };
142
+ }
143
+ cellKey(cx, cy) {
144
+ return `${cx},${cy}`;
145
+ }
146
+ worldToCell(wx, wy) {
147
+ return [
148
+ Math.floor((wx - this.config.bounds.minX) / this.config.cellSize),
149
+ Math.floor((wy - this.config.bounds.minY) / this.config.cellSize),
150
+ ];
151
+ }
152
+ /** Add an event at a world position */
153
+ addEvent(x, y, weight = 1) {
154
+ var _a;
155
+ if (x < this.config.bounds.minX || x > this.config.bounds.maxX ||
156
+ y < this.config.bounds.minY || y > this.config.bounds.maxY)
157
+ return;
158
+ const [cx, cy] = this.worldToCell(x, y);
159
+ const key = this.cellKey(cx, cy);
160
+ this.grid.set(key, ((_a = this.grid.get(key)) !== null && _a !== void 0 ? _a : 0) + weight);
161
+ this.totalEvents++;
162
+ }
163
+ /** Add events from telemetry data */
164
+ addFromTelemetry(events) {
165
+ for (const event of events) {
166
+ if (event.position) {
167
+ this.addEvent(event.position.x, event.position.y);
168
+ }
169
+ }
170
+ }
171
+ /** Get the grid as an array of cells with normalized values */
172
+ getCells() {
173
+ const cells = [];
174
+ let maxVal = this.config.maxValue;
175
+ if (maxVal <= 0) {
176
+ // Auto-detect max value
177
+ maxVal = 0;
178
+ for (const v of this.grid.values()) {
179
+ if (v > maxVal)
180
+ maxVal = v;
181
+ }
182
+ }
183
+ if (maxVal === 0)
184
+ maxVal = 1;
185
+ for (const [key, value] of this.grid) {
186
+ const [cx, cy] = key.split(',').map(Number);
187
+ cells.push({
188
+ x: cx,
189
+ y: cy,
190
+ value: Math.min(value / maxVal, 1),
191
+ events: value,
192
+ });
193
+ }
194
+ return cells;
195
+ }
196
+ /** Apply Gaussian blur to the grid */
197
+ getBlurredCells() {
198
+ var _a;
199
+ const cells = this.getCells();
200
+ if (this.config.blurRadius <= 0)
201
+ return cells;
202
+ const radius = this.config.blurRadius;
203
+ const cellMap = new Map();
204
+ // Build raw map
205
+ for (const cell of cells) {
206
+ cellMap.set(this.cellKey(cell.x, cell.y), cell.events);
207
+ }
208
+ // Apply blur
209
+ const blurred = [];
210
+ const sigma = radius / 2;
211
+ const kernel = [];
212
+ for (let dy = -radius; dy <= radius; dy++) {
213
+ const row = [];
214
+ for (let dx = -radius; dx <= radius; dx++) {
215
+ row.push(Math.exp(-(dx * dx + dy * dy) / (2 * sigma * sigma)));
216
+ }
217
+ kernel.push(row);
218
+ }
219
+ // Normalize kernel
220
+ let kernelSum = 0;
221
+ for (const row of kernel)
222
+ for (const v of row)
223
+ kernelSum += v;
224
+ const visited = new Set();
225
+ for (const cell of cells) {
226
+ for (let dy = -radius; dy <= radius; dy++) {
227
+ for (let dx = -radius; dx <= radius; dx++) {
228
+ const nx = cell.x + dx;
229
+ const ny = cell.y + dy;
230
+ const key = this.cellKey(nx, ny);
231
+ if (visited.has(key))
232
+ continue;
233
+ visited.add(key);
234
+ let sum = 0;
235
+ for (let ky = -radius; ky <= radius; ky++) {
236
+ for (let kx = -radius; kx <= radius; kx++) {
237
+ const srcKey = this.cellKey(nx + kx, ny + ky);
238
+ const srcVal = (_a = cellMap.get(srcKey)) !== null && _a !== void 0 ? _a : 0;
239
+ sum += srcVal * kernel[ky + radius][kx + radius];
240
+ }
241
+ }
242
+ const normalized = sum / kernelSum;
243
+ if (normalized > 0.001) {
244
+ blurred.push({ x: nx, y: ny, value: 0, events: normalized });
245
+ }
246
+ }
247
+ }
248
+ }
249
+ // Normalize values
250
+ let maxVal = this.config.maxValue;
251
+ if (maxVal <= 0) {
252
+ maxVal = Math.max(...blurred.map(c => c.events), 1);
253
+ }
254
+ for (const cell of blurred) {
255
+ cell.value = Math.min(cell.events / maxVal, 1);
256
+ }
257
+ return blurred;
258
+ }
259
+ /** Render heatmap to a canvas */
260
+ renderToCanvas(ctx, width, height) {
261
+ const cells = this.getBlurredCells();
262
+ const { bounds, cellSize, colorStops } = this.config;
263
+ const worldW = bounds.maxX - bounds.minX;
264
+ const worldH = bounds.maxY - bounds.minY;
265
+ const scaleX = width / worldW;
266
+ const scaleY = height / worldH;
267
+ const cellW = cellSize * scaleX;
268
+ const cellH = cellSize * scaleY;
269
+ ctx.clearRect(0, 0, width, height);
270
+ for (const cell of cells) {
271
+ const screenX = cell.x * cellSize * scaleX;
272
+ const screenY = cell.y * cellSize * scaleY;
273
+ // Interpolate color from stops
274
+ const color = this.interpolateColor(cell.value, colorStops);
275
+ ctx.fillStyle = color;
276
+ ctx.fillRect(screenX, screenY, cellW + 1, cellH + 1);
277
+ }
278
+ }
279
+ interpolateColor(value, stops) {
280
+ if (stops.length === 0)
281
+ return 'transparent';
282
+ if (stops.length === 1)
283
+ return stops[0].color;
284
+ for (let i = 0; i < stops.length - 1; i++) {
285
+ if (value >= stops[i].value && value <= stops[i + 1].value) {
286
+ const t = (value - stops[i].value) / (stops[i + 1].value - stops[i].value);
287
+ return this.lerpColor(stops[i].color, stops[i + 1].color, t);
288
+ }
289
+ }
290
+ return stops[stops.length - 1].color;
291
+ }
292
+ lerpColor(a, b, t) {
293
+ const parse = (c) => {
294
+ const m = c.match(/[\d.]+/g);
295
+ return m ? m.map(Number) : [0, 0, 0, 1];
296
+ };
297
+ const ca = parse(a);
298
+ const cb = parse(b);
299
+ const r = Math.round(ca[0] + (cb[0] - ca[0]) * t);
300
+ const g = Math.round(ca[1] + (cb[1] - ca[1]) * t);
301
+ const bl = Math.round(ca[2] + (cb[2] - ca[2]) * t);
302
+ const al = ca[3] + (cb[3] - ca[3]) * t;
303
+ return `rgba(${r}, ${g}, ${bl}, ${al.toFixed(2)})`;
304
+ }
305
+ getTotalEvents() {
306
+ return this.totalEvents;
307
+ }
308
+ getConfig() {
309
+ return this.config;
310
+ }
311
+ clear() {
312
+ this.grid.clear();
313
+ this.totalEvents = 0;
314
+ }
315
+ }
316
+ /* ══════════════════════════════════════════════════════════════
317
+ SESSION RECORDER
318
+ ══════════════════════════════════════════════════════════════ */
319
+ class SessionRecorder {
320
+ constructor(config = {}) {
321
+ this.recording = false;
322
+ this.frames = [];
323
+ this.startedAt = 0;
324
+ this.lastFrameTime = 0;
325
+ this.pendingEvents = [];
326
+ this.recordTimer = null;
327
+ this.config = { ...DEFAULT_RECORDING_CONFIG, ...config };
328
+ this.sessionId = `sess-${Date.now().toString(36)}`;
329
+ }
330
+ /** Start recording */
331
+ start() {
332
+ if (this.recording)
333
+ return;
334
+ this.recording = true;
335
+ this.startedAt = Date.now();
336
+ this.lastFrameTime = this.startedAt;
337
+ this.frames = [];
338
+ const intervalMs = 1000 / this.config.fps;
339
+ this.recordTimer = setInterval(() => this.captureFrame(), intervalMs);
340
+ }
341
+ /** Stop recording and return the session */
342
+ stop(sceneId = 'unknown', buildVersion = '0.0.0') {
343
+ this.recording = false;
344
+ if (this.recordTimer) {
345
+ clearInterval(this.recordTimer);
346
+ this.recordTimer = null;
347
+ }
348
+ // Capture any remaining events
349
+ if (this.pendingEvents.length > 0)
350
+ this.captureFrame();
351
+ const endedAt = Date.now();
352
+ const recording = {
353
+ id: `rec-${Date.now().toString(36)}`,
354
+ sessionId: this.sessionId,
355
+ startedAt: this.startedAt,
356
+ endedAt,
357
+ durationMs: endedAt - this.startedAt,
358
+ frameCount: this.frames.length,
359
+ frames: this.frames,
360
+ metadata: { sceneId, buildVersion, tags: [] },
361
+ sizeBytes: 0,
362
+ };
363
+ // Estimate size
364
+ recording.sizeBytes = JSON.stringify(recording.frames).length;
365
+ return recording;
366
+ }
367
+ /** Add an event to the current frame batch */
368
+ recordEvent(type, data) {
369
+ if (!this.recording)
370
+ return;
371
+ if (this.config.recordTypes.length > 0 && !this.config.recordTypes.includes(type))
372
+ return;
373
+ this.pendingEvents.push({ type, data });
374
+ }
375
+ /** Record player position (convenience) */
376
+ recordPosition(x, y, z) {
377
+ if (!this.config.recordPosition)
378
+ return;
379
+ this.recordEvent('position', { x, y, z });
380
+ }
381
+ captureFrame() {
382
+ const now = Date.now();
383
+ // Check max duration
384
+ if (this.config.maxDurationMs > 0 && now - this.startedAt > this.config.maxDurationMs) {
385
+ this.stop();
386
+ return;
387
+ }
388
+ const frame = {
389
+ timestamp: now,
390
+ delta: now - this.lastFrameTime,
391
+ events: [...this.pendingEvents],
392
+ };
393
+ this.frames.push(frame);
394
+ this.pendingEvents = [];
395
+ this.lastFrameTime = now;
396
+ }
397
+ isRecording() {
398
+ return this.recording;
399
+ }
400
+ getFrameCount() {
401
+ return this.frames.length;
402
+ }
403
+ getDurationMs() {
404
+ return this.recording ? Date.now() - this.startedAt : 0;
405
+ }
406
+ }
407
+ /* ══════════════════════════════════════════════════════════════
408
+ SESSION PLAYER (Playback)
409
+ ══════════════════════════════════════════════════════════════ */
410
+ class SessionPlayer {
411
+ constructor() {
412
+ this.recording = null;
413
+ this.currentFrame = 0;
414
+ this.playing = false;
415
+ this.speed = 1;
416
+ this.playTimer = null;
417
+ this.onFrame = null;
418
+ }
419
+ load(recording) {
420
+ this.recording = recording;
421
+ this.currentFrame = 0;
422
+ this.stop();
423
+ }
424
+ /** Start playback */
425
+ play(onFrame) {
426
+ if (!this.recording || this.playing)
427
+ return;
428
+ this.playing = true;
429
+ this.onFrame = onFrame;
430
+ this.advanceFrame();
431
+ }
432
+ advanceFrame() {
433
+ if (!this.recording || !this.playing || this.currentFrame >= this.recording.frames.length) {
434
+ this.stop();
435
+ return;
436
+ }
437
+ const frame = this.recording.frames[this.currentFrame];
438
+ if (this.onFrame)
439
+ this.onFrame(frame, this.currentFrame);
440
+ this.currentFrame++;
441
+ if (this.currentFrame < this.recording.frames.length) {
442
+ const nextFrame = this.recording.frames[this.currentFrame];
443
+ const delay = (nextFrame.delta || 100) / this.speed;
444
+ this.playTimer = setTimeout(() => this.advanceFrame(), delay);
445
+ }
446
+ else {
447
+ this.stop();
448
+ }
449
+ }
450
+ stop() {
451
+ this.playing = false;
452
+ if (this.playTimer) {
453
+ clearTimeout(this.playTimer);
454
+ this.playTimer = null;
455
+ }
456
+ }
457
+ pause() {
458
+ this.playing = false;
459
+ if (this.playTimer) {
460
+ clearTimeout(this.playTimer);
461
+ this.playTimer = null;
462
+ }
463
+ }
464
+ seek(frameIndex) {
465
+ if (!this.recording)
466
+ return;
467
+ this.currentFrame = Math.max(0, Math.min(frameIndex, this.recording.frameCount - 1));
468
+ }
469
+ setSpeed(speed) {
470
+ this.speed = Math.max(0.1, Math.min(10, speed));
471
+ }
472
+ getProgress() {
473
+ if (!this.recording || this.recording.frameCount === 0)
474
+ return 0;
475
+ return this.currentFrame / this.recording.frameCount;
476
+ }
477
+ isPlaying() {
478
+ return this.playing;
479
+ }
480
+ }
481
+ /* ══════════════════════════════════════════════════════════════
482
+ FUNNEL TRACKER
483
+ ══════════════════════════════════════════════════════════════ */
484
+ class FunnelTracker {
485
+ constructor() {
486
+ this.funnels = new Map();
487
+ this.progress = new Map(); // funnelId → stepId → sessionIds
488
+ }
489
+ define(funnel) {
490
+ this.funnels.set(funnel.id, funnel);
491
+ const stepMap = new Map();
492
+ for (const step of funnel.steps) {
493
+ stepMap.set(step.id, new Set());
494
+ }
495
+ this.progress.set(funnel.id, stepMap);
496
+ }
497
+ /** Record that a session reached a funnel step */
498
+ recordStep(funnelId, stepEventName, sessionId) {
499
+ var _a;
500
+ const funnel = this.funnels.get(funnelId);
501
+ if (!funnel)
502
+ return;
503
+ const step = funnel.steps.find(s => s.eventName === stepEventName);
504
+ if (!step)
505
+ return;
506
+ const stepMap = this.progress.get(funnelId);
507
+ (_a = stepMap === null || stepMap === void 0 ? void 0 : stepMap.get(step.id)) === null || _a === void 0 ? void 0 : _a.add(sessionId);
508
+ }
509
+ /** Get funnel analysis */
510
+ analyze(funnelId) {
511
+ var _a, _b;
512
+ const funnel = this.funnels.get(funnelId);
513
+ const stepMap = this.progress.get(funnelId);
514
+ if (!funnel || !stepMap)
515
+ return [];
516
+ const result = [];
517
+ let prevCount = 0;
518
+ for (const step of funnel.steps) {
519
+ const count = (_b = (_a = stepMap.get(step.id)) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0;
520
+ const dropOff = prevCount > 0 ? 1 - count / prevCount : 0;
521
+ result.push({
522
+ id: step.id,
523
+ name: step.name,
524
+ count,
525
+ dropOffRate: result.length === 0 ? 0 : dropOff,
526
+ });
527
+ prevCount = count;
528
+ }
529
+ return result;
530
+ }
531
+ getFunnels() {
532
+ return Array.from(this.funnels.values());
533
+ }
534
+ }
535
+ /* ══════════════════════════════════════════════════════════════
536
+ GAMEPLAY ANALYTICS (Main class)
537
+ ══════════════════════════════════════════════════════════════ */
538
+ class GameplayAnalytics {
539
+ constructor(eventBus, telemetryConfig, recordingConfig) {
540
+ this.heatmaps = new Map();
541
+ this.eventBus = eventBus;
542
+ this.telemetry = new TelemetryPipeline(eventBus, telemetryConfig);
543
+ this.recorder = new SessionRecorder(recordingConfig);
544
+ this.funnels = new FunnelTracker();
545
+ }
546
+ /** Create or get a heatmap */
547
+ heatmap(id, config) {
548
+ let hm = this.heatmaps.get(id);
549
+ if (!hm) {
550
+ hm = new HeatmapGenerator(config);
551
+ this.heatmaps.set(id, hm);
552
+ }
553
+ return hm;
554
+ }
555
+ /** Track and automatically distribute to relevant heatmaps */
556
+ trackEvent(category, name, data = {}, position) {
557
+ this.telemetry.track(category, name, data, position);
558
+ // Auto-feed heatmaps
559
+ if (position) {
560
+ for (const [_, hm] of this.heatmaps) {
561
+ hm.addEvent(position.x, position.y);
562
+ }
563
+ }
564
+ // Auto-feed session recorder
565
+ this.recorder.recordEvent('action', { category, name, ...data });
566
+ if (position) {
567
+ this.recorder.recordPosition(position.x, position.y, position.z);
568
+ }
569
+ // Auto-feed funnel tracker
570
+ for (const funnel of this.funnels.getFunnels()) {
571
+ this.funnels.recordStep(funnel.id, name, this.telemetry.getSessionId());
572
+ }
573
+ }
574
+ /** Get summary stats */
575
+ getSummary() {
576
+ return {
577
+ totalEvents: this.telemetry.getTotalEvents(),
578
+ sessionId: this.telemetry.getSessionId(),
579
+ heatmapCount: this.heatmaps.size,
580
+ isRecording: this.recorder.isRecording(),
581
+ recordedFrames: this.recorder.getFrameCount(),
582
+ };
583
+ }
584
+ destroy() {
585
+ this.telemetry.destroy();
586
+ if (this.recorder.isRecording())
587
+ this.recorder.stop();
588
+ this.heatmaps.clear();
589
+ }
590
+ }
591
+ /* ══════════════════════════════════════════════════════════════
592
+ REACT HOOK
593
+ ══════════════════════════════════════════════════════════════ */
594
+ function useGameplayAnalytics(eventBus, telemetryConfig, recordingConfig) {
595
+ const analyticsRef = React.useRef(null);
596
+ const analytics = React.useMemo(() => {
597
+ if (!analyticsRef.current) {
598
+ analyticsRef.current = new GameplayAnalytics(eventBus, telemetryConfig, recordingConfig);
599
+ }
600
+ return analyticsRef.current;
601
+ }, [eventBus]);
602
+ React.useEffect(() => {
603
+ return () => {
604
+ analytics.destroy();
605
+ analyticsRef.current = null;
606
+ };
607
+ }, [analytics]);
608
+ const trackEvent = React.useCallback((category, name, data, position) => analytics.trackEvent(category, name, data, position), [analytics]);
609
+ const [summary, setSummary] = React.useState(analytics.getSummary());
610
+ const refreshSummary = React.useCallback(() => {
611
+ setSummary(analytics.getSummary());
612
+ }, [analytics]);
613
+ return {
614
+ analytics,
615
+ trackEvent,
616
+ summary,
617
+ refreshSummary,
618
+ startRecording: () => analytics.recorder.start(),
619
+ stopRecording: (sceneId) => analytics.recorder.stop(sceneId),
620
+ heatmap: (id, config) => analytics.heatmap(id, config),
621
+ };
622
+ }
623
+ const AnalyticsDashboard = ({ analytics, className, style, }) => {
624
+ const [summary, setSummary] = React.useState(analytics.getSummary());
625
+ React.useEffect(() => {
626
+ const timer = setInterval(() => setSummary(analytics.getSummary()), 1000);
627
+ return () => clearInterval(timer);
628
+ }, [analytics]);
629
+ const statStyle = {
630
+ display: 'flex', justifyContent: 'space-between', padding: '4px 0',
631
+ borderBottom: '1px solid rgba(128,128,128,0.2)',
632
+ };
633
+ return React.createElement('div', {
634
+ className: `nice-analytics-dashboard ${className !== null && className !== void 0 ? className : ''}`.trim(),
635
+ style: { padding: 16, fontFamily: 'monospace', fontSize: 13, ...style },
636
+ }, React.createElement('h3', { style: { margin: '0 0 12px 0' } }, 'Gameplay Analytics'), React.createElement('div', { style: statStyle }, React.createElement('span', null, 'Session ID'), React.createElement('code', null, summary.sessionId)), React.createElement('div', { style: statStyle }, React.createElement('span', null, 'Total Events'), React.createElement('span', null, String(summary.totalEvents))), React.createElement('div', { style: statStyle }, React.createElement('span', null, 'Heatmaps'), React.createElement('span', null, String(summary.heatmapCount))), React.createElement('div', { style: statStyle }, React.createElement('span', null, 'Recording'), React.createElement('span', null, summary.isRecording ? `ON (${summary.recordedFrames} frames)` : 'OFF')));
637
+ };
638
+ AnalyticsDashboard.displayName = 'AnalyticsDashboard';
639
+
640
+ exports.AnalyticsDashboard = AnalyticsDashboard;
641
+ exports.DEFAULT_HEATMAP_CONFIG = DEFAULT_HEATMAP_CONFIG;
642
+ exports.DEFAULT_RECORDING_CONFIG = DEFAULT_RECORDING_CONFIG;
643
+ exports.DEFAULT_TELEMETRY_CONFIG = DEFAULT_TELEMETRY_CONFIG;
644
+ exports.FunnelTracker = FunnelTracker;
645
+ exports.GameplayAnalytics = GameplayAnalytics;
646
+ exports.HeatmapGenerator = HeatmapGenerator;
647
+ exports.SessionPlayer = SessionPlayer;
648
+ exports.SessionRecorder = SessionRecorder;
649
+ exports.TelemetryPipeline = TelemetryPipeline;
650
+ exports.useGameplayAnalytics = useGameplayAnalytics;
651
+ //# sourceMappingURL=GameplayAnalytics.js.map