@thunderclap-engine/engine 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (566) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/LICENSE +21 -0
  3. package/README.md +333 -2
  4. package/dist/analytics/analytics.d.ts +80 -0
  5. package/dist/analytics/analytics.js +129 -0
  6. package/dist/analytics/index.d.ts +1 -0
  7. package/dist/analytics/index.js +1 -0
  8. package/dist/anim/aim.d.ts +43 -0
  9. package/dist/anim/aim.js +157 -0
  10. package/dist/anim/clip.d.ts +98 -0
  11. package/dist/anim/clip.js +282 -0
  12. package/dist/anim/compress.d.ts +65 -0
  13. package/dist/anim/compress.js +339 -0
  14. package/dist/anim/foot-ik.d.ts +74 -0
  15. package/dist/anim/foot-ik.js +241 -0
  16. package/dist/anim/graph.d.ts +153 -0
  17. package/dist/anim/graph.js +532 -0
  18. package/dist/anim/ik.d.ts +105 -0
  19. package/dist/anim/ik.js +435 -0
  20. package/dist/anim/index.d.ts +36 -0
  21. package/dist/anim/index.js +21 -0
  22. package/dist/anim/match.d.ts +66 -0
  23. package/dist/anim/match.js +153 -0
  24. package/dist/anim/mixer.d.ts +113 -0
  25. package/dist/anim/mixer.js +314 -0
  26. package/dist/anim/morph.d.ts +41 -0
  27. package/dist/anim/morph.js +94 -0
  28. package/dist/anim/pose.d.ts +74 -0
  29. package/dist/anim/pose.js +254 -0
  30. package/dist/anim/quat.d.ts +44 -0
  31. package/dist/anim/quat.js +187 -0
  32. package/dist/anim/retarget.d.ts +97 -0
  33. package/dist/anim/retarget.js +366 -0
  34. package/dist/anim/root-motion.d.ts +44 -0
  35. package/dist/anim/root-motion.js +224 -0
  36. package/dist/anim/skin-pose.d.ts +39 -0
  37. package/dist/anim/skin-pose.js +53 -0
  38. package/dist/anim/socket.d.ts +47 -0
  39. package/dist/anim/socket.js +84 -0
  40. package/dist/anim/spring-chain.d.ts +73 -0
  41. package/dist/anim/spring-chain.js +294 -0
  42. package/dist/assets/atlas.d.ts +90 -0
  43. package/dist/assets/atlas.js +212 -0
  44. package/dist/assets/baked.d.ts +33 -0
  45. package/dist/assets/baked.js +38 -0
  46. package/dist/assets/bundle.d.ts +88 -0
  47. package/dist/assets/bundle.js +464 -0
  48. package/dist/assets/cache.d.ts +56 -0
  49. package/dist/assets/cache.js +123 -0
  50. package/dist/assets/gltf-load.d.ts +252 -0
  51. package/dist/assets/gltf-load.js +661 -0
  52. package/dist/assets/gltf-skin.d.ts +36 -0
  53. package/dist/assets/gltf-skin.js +109 -0
  54. package/dist/assets/gltf.d.ts +706 -0
  55. package/dist/assets/gltf.js +1376 -0
  56. package/dist/assets/index.d.ts +20 -0
  57. package/dist/assets/index.js +10 -0
  58. package/dist/assets/ktx2.d.ts +71 -0
  59. package/dist/assets/ktx2.js +213 -0
  60. package/dist/assets/manifest.d.ts +79 -0
  61. package/dist/assets/manifest.js +7 -0
  62. package/dist/assets/meshopt.d.ts +23 -0
  63. package/dist/assets/meshopt.js +403 -0
  64. package/dist/audio/audio.d.ts +733 -0
  65. package/dist/audio/audio.js +2013 -0
  66. package/dist/audio/dsp.d.ts +61 -0
  67. package/dist/audio/dsp.js +159 -0
  68. package/dist/audio/duck.d.ts +44 -0
  69. package/dist/audio/duck.js +101 -0
  70. package/dist/audio/envelope.d.ts +53 -0
  71. package/dist/audio/envelope.js +106 -0
  72. package/dist/audio/index.d.ts +13 -0
  73. package/dist/audio/index.js +14 -0
  74. package/dist/audio/music.d.ts +113 -0
  75. package/dist/audio/music.js +548 -0
  76. package/dist/audio/occlusion.d.ts +55 -0
  77. package/dist/audio/occlusion.js +61 -0
  78. package/dist/audio/persist.d.ts +23 -0
  79. package/dist/audio/persist.js +27 -0
  80. package/dist/audio/recipes.d.ts +55 -0
  81. package/dist/audio/recipes.js +227 -0
  82. package/dist/audio/send.d.ts +41 -0
  83. package/dist/audio/send.js +118 -0
  84. package/dist/audio/sprites.d.ts +59 -0
  85. package/dist/audio/sprites.js +43 -0
  86. package/dist/audio/synth.d.ts +103 -0
  87. package/dist/audio/synth.js +197 -0
  88. package/dist/audio/variations.d.ts +25 -0
  89. package/dist/audio/variations.js +55 -0
  90. package/dist/audio/zones.d.ts +100 -0
  91. package/dist/audio/zones.js +167 -0
  92. package/dist/core/detached-surface.d.ts +44 -0
  93. package/dist/core/detached-surface.js +104 -0
  94. package/dist/core/events.d.ts +24 -0
  95. package/dist/core/events.js +43 -0
  96. package/dist/core/game.d.ts +409 -0
  97. package/dist/core/game.js +530 -0
  98. package/dist/core/hash.d.ts +24 -0
  99. package/dist/core/hash.js +49 -0
  100. package/dist/core/index.d.ts +17 -0
  101. package/dist/core/index.js +9 -0
  102. package/dist/core/loop.d.ts +113 -0
  103. package/dist/core/loop.js +185 -0
  104. package/dist/core/math.d.ts +58 -0
  105. package/dist/core/math.js +210 -0
  106. package/dist/core/noise.d.ts +40 -0
  107. package/dist/core/noise.js +247 -0
  108. package/dist/core/pool.d.ts +42 -0
  109. package/dist/core/pool.js +85 -0
  110. package/dist/core/random.d.ts +61 -0
  111. package/dist/core/random.js +199 -0
  112. package/dist/core/scene.d.ts +79 -0
  113. package/dist/core/scene.js +195 -0
  114. package/dist/core/timer.d.ts +66 -0
  115. package/dist/core/timer.js +286 -0
  116. package/dist/fx/billboard-wgsl.d.ts +29 -0
  117. package/dist/fx/billboard-wgsl.js +158 -0
  118. package/dist/fx/billboard.d.ts +249 -0
  119. package/dist/fx/billboard.js +702 -0
  120. package/dist/fx/debug-draw.d.ts +127 -0
  121. package/dist/fx/debug-draw.js +523 -0
  122. package/dist/fx/debug-wgsl.d.ts +7 -0
  123. package/dist/fx/debug-wgsl.js +32 -0
  124. package/dist/fx/decals-wgsl.d.ts +15 -0
  125. package/dist/fx/decals-wgsl.js +173 -0
  126. package/dist/fx/decals.d.ts +216 -0
  127. package/dist/fx/decals.js +607 -0
  128. package/dist/fx/effect.d.ts +129 -0
  129. package/dist/fx/effect.js +349 -0
  130. package/dist/fx/effects/hit-spark.json +48 -0
  131. package/dist/fx/effects/index.d.ts +8 -0
  132. package/dist/fx/effects/index.js +9 -0
  133. package/dist/fx/effects/magic-aura.json +47 -0
  134. package/dist/fx/effects/smoke-puff.json +34 -0
  135. package/dist/fx/emit-surface.d.ts +40 -0
  136. package/dist/fx/emit-surface.js +124 -0
  137. package/dist/fx/flicker.d.ts +30 -0
  138. package/dist/fx/flicker.js +42 -0
  139. package/dist/fx/index.d.ts +31 -0
  140. package/dist/fx/index.js +20 -0
  141. package/dist/fx/particles-wgsl.d.ts +57 -0
  142. package/dist/fx/particles-wgsl.js +828 -0
  143. package/dist/fx/particles.d.ts +566 -0
  144. package/dist/fx/particles.js +1533 -0
  145. package/dist/fx/random.d.ts +15 -0
  146. package/dist/fx/random.js +20 -0
  147. package/dist/fx/sky-wgsl.d.ts +23 -0
  148. package/dist/fx/sky-wgsl.js +127 -0
  149. package/dist/fx/sky.d.ts +96 -0
  150. package/dist/fx/sky.js +175 -0
  151. package/dist/fx/text-atlas.d.ts +143 -0
  152. package/dist/fx/text-atlas.js +327 -0
  153. package/dist/fx/trail-wgsl.d.ts +11 -0
  154. package/dist/fx/trail-wgsl.js +42 -0
  155. package/dist/fx/trail.d.ts +194 -0
  156. package/dist/fx/trail.js +555 -0
  157. package/dist/fx/water-wgsl.d.ts +34 -0
  158. package/dist/fx/water-wgsl.js +197 -0
  159. package/dist/fx/water.d.ts +176 -0
  160. package/dist/fx/water.js +371 -0
  161. package/dist/geom/collide/bvh.d.ts +151 -0
  162. package/dist/geom/collide/bvh.js +493 -0
  163. package/dist/geom/collide/debug.d.ts +14 -0
  164. package/dist/geom/collide/debug.js +74 -0
  165. package/dist/geom/collide/grid.d.ts +26 -0
  166. package/dist/geom/collide/grid.js +91 -0
  167. package/dist/geom/collide/index.d.ts +8 -0
  168. package/dist/geom/collide/index.js +8 -0
  169. package/dist/geom/collide/queries.d.ts +70 -0
  170. package/dist/geom/collide/queries.js +583 -0
  171. package/dist/geom/collide/serialize.d.ts +14 -0
  172. package/dist/geom/collide/serialize.js +145 -0
  173. package/dist/geom/collide/shapes.d.ts +161 -0
  174. package/dist/geom/collide/shapes.js +686 -0
  175. package/dist/geom/collide/slide.d.ts +66 -0
  176. package/dist/geom/collide/slide.js +375 -0
  177. package/dist/geom/collide/tile-slide.d.ts +88 -0
  178. package/dist/geom/collide/tile-slide.js +255 -0
  179. package/dist/geom/geometry.d.ts +95 -0
  180. package/dist/geom/geometry.js +322 -0
  181. package/dist/geom/heightfield.d.ts +72 -0
  182. package/dist/geom/heightfield.js +295 -0
  183. package/dist/geom/hull.d.ts +27 -0
  184. package/dist/geom/hull.js +279 -0
  185. package/dist/geom/index.d.ts +35 -0
  186. package/dist/geom/index.js +23 -0
  187. package/dist/geom/iso.d.ts +74 -0
  188. package/dist/geom/iso.js +89 -0
  189. package/dist/geom/lod.d.ts +29 -0
  190. package/dist/geom/lod.js +27 -0
  191. package/dist/geom/ops.d.ts +47 -0
  192. package/dist/geom/ops.js +285 -0
  193. package/dist/geom/primitives.d.ts +97 -0
  194. package/dist/geom/primitives.js +359 -0
  195. package/dist/geom/shapes.d.ts +43 -0
  196. package/dist/geom/shapes.js +88 -0
  197. package/dist/geom/simplify.d.ts +38 -0
  198. package/dist/geom/simplify.js +519 -0
  199. package/dist/geom/split.d.ts +37 -0
  200. package/dist/geom/split.js +413 -0
  201. package/dist/geom/sweep.d.ts +83 -0
  202. package/dist/geom/sweep.js +534 -0
  203. package/dist/geom/tangents.d.ts +16 -0
  204. package/dist/geom/tangents.js +124 -0
  205. package/dist/geom/triangulate.d.ts +19 -0
  206. package/dist/geom/triangulate.js +147 -0
  207. package/dist/host/default.d.ts +10 -0
  208. package/dist/host/default.js +10 -0
  209. package/dist/host/index.d.ts +4 -0
  210. package/dist/host/index.js +3 -0
  211. package/dist/host/types.d.ts +144 -0
  212. package/dist/host/types.js +1 -0
  213. package/dist/host/web-links.d.ts +38 -0
  214. package/dist/host/web-links.js +110 -0
  215. package/dist/host/web.d.ts +30 -0
  216. package/dist/host/web.js +216 -0
  217. package/dist/host/xr.d.ts +24 -0
  218. package/dist/host/xr.js +59 -0
  219. package/dist/i18n/i18n.d.ts +59 -0
  220. package/dist/i18n/i18n.js +241 -0
  221. package/dist/i18n/index.d.ts +3 -0
  222. package/dist/i18n/index.js +3 -0
  223. package/dist/i18n/message.d.ts +72 -0
  224. package/dist/i18n/message.js +369 -0
  225. package/dist/i18n/negotiate.d.ts +17 -0
  226. package/dist/i18n/negotiate.js +58 -0
  227. package/dist/index.d.ts +7 -0
  228. package/dist/index.js +1 -0
  229. package/dist/input/bindings.d.ts +31 -0
  230. package/dist/input/bindings.js +141 -0
  231. package/dist/input/clock.d.ts +44 -0
  232. package/dist/input/clock.js +49 -0
  233. package/dist/input/follow.d.ts +133 -0
  234. package/dist/input/follow.js +218 -0
  235. package/dist/input/gestures.d.ts +281 -0
  236. package/dist/input/gestures.js +662 -0
  237. package/dist/input/glyphs.d.ts +35 -0
  238. package/dist/input/glyphs.js +216 -0
  239. package/dist/input/gyro.d.ts +85 -0
  240. package/dist/input/gyro.js +140 -0
  241. package/dist/input/index.d.ts +19 -0
  242. package/dist/input/index.js +16 -0
  243. package/dist/input/input.d.ts +543 -0
  244. package/dist/input/input.js +1492 -0
  245. package/dist/input/look.d.ts +327 -0
  246. package/dist/input/look.js +681 -0
  247. package/dist/input/magnify.d.ts +177 -0
  248. package/dist/input/magnify.js +131 -0
  249. package/dist/input/pointer-dispatch.d.ts +138 -0
  250. package/dist/input/pointer-dispatch.js +180 -0
  251. package/dist/input/pointer-router.d.ts +204 -0
  252. package/dist/input/pointer-router.js +533 -0
  253. package/dist/input/pointer-sources.d.ts +164 -0
  254. package/dist/input/pointer-sources.js +306 -0
  255. package/dist/input/rays.d.ts +138 -0
  256. package/dist/input/rays.js +615 -0
  257. package/dist/input/record.d.ts +209 -0
  258. package/dist/input/record.js +601 -0
  259. package/dist/input/touch-zones.d.ts +147 -0
  260. package/dist/input/touch-zones.js +300 -0
  261. package/dist/input/types.d.ts +158 -0
  262. package/dist/input/types.js +1 -0
  263. package/dist/input/xr-source.d.ts +53 -0
  264. package/dist/input/xr-source.js +164 -0
  265. package/dist/nav/astar.d.ts +45 -0
  266. package/dist/nav/astar.js +182 -0
  267. package/dist/nav/corridor.d.ts +40 -0
  268. package/dist/nav/corridor.js +95 -0
  269. package/dist/nav/crowd.d.ts +94 -0
  270. package/dist/nav/crowd.js +624 -0
  271. package/dist/nav/flow.d.ts +61 -0
  272. package/dist/nav/flow.js +193 -0
  273. package/dist/nav/grid.d.ts +108 -0
  274. package/dist/nav/grid.js +210 -0
  275. package/dist/nav/heap.d.ts +22 -0
  276. package/dist/nav/heap.js +92 -0
  277. package/dist/nav/index.d.ts +37 -0
  278. package/dist/nav/index.js +19 -0
  279. package/dist/nav/mesh/areas.d.ts +44 -0
  280. package/dist/nav/mesh/areas.js +98 -0
  281. package/dist/nav/mesh/bake-options.d.ts +33 -0
  282. package/dist/nav/mesh/bake-options.js +76 -0
  283. package/dist/nav/mesh/contour.d.ts +22 -0
  284. package/dist/nav/mesh/contour.js +323 -0
  285. package/dist/nav/mesh/flow3.d.ts +35 -0
  286. package/dist/nav/mesh/flow3.js +229 -0
  287. package/dist/nav/mesh/links.d.ts +38 -0
  288. package/dist/nav/mesh/links.js +72 -0
  289. package/dist/nav/mesh/mesh-path.d.ts +152 -0
  290. package/dist/nav/mesh/mesh-path.js +643 -0
  291. package/dist/nav/mesh/mesh-reach.d.ts +78 -0
  292. package/dist/nav/mesh/mesh-reach.js +450 -0
  293. package/dist/nav/mesh/navmesh.d.ts +117 -0
  294. package/dist/nav/mesh/navmesh.js +647 -0
  295. package/dist/nav/mesh/polymesh.d.ts +24 -0
  296. package/dist/nav/mesh/polymesh.js +384 -0
  297. package/dist/nav/mesh/regions.d.ts +12 -0
  298. package/dist/nav/mesh/regions.js +367 -0
  299. package/dist/nav/mesh/serialize.d.ts +13 -0
  300. package/dist/nav/mesh/serialize.js +197 -0
  301. package/dist/nav/mesh/voxelize.d.ts +111 -0
  302. package/dist/nav/mesh/voxelize.js +552 -0
  303. package/dist/nav/obstacles.d.ts +75 -0
  304. package/dist/nav/obstacles.js +294 -0
  305. package/dist/nav/path.d.ts +59 -0
  306. package/dist/nav/path.js +177 -0
  307. package/dist/nav/query-queue.d.ts +46 -0
  308. package/dist/nav/query-queue.js +308 -0
  309. package/dist/nav/reach.d.ts +53 -0
  310. package/dist/nav/reach.js +148 -0
  311. package/dist/nav/steer.d.ts +36 -0
  312. package/dist/nav/steer.js +78 -0
  313. package/dist/platform/boot.d.ts +28 -0
  314. package/dist/platform/boot.js +43 -0
  315. package/dist/platform/device-mode.d.ts +40 -0
  316. package/dist/platform/device-mode.js +104 -0
  317. package/dist/platform/device.d.ts +31 -0
  318. package/dist/platform/device.js +91 -0
  319. package/dist/platform/environment.d.ts +42 -0
  320. package/dist/platform/environment.js +82 -0
  321. package/dist/platform/gpu.d.ts +40 -0
  322. package/dist/platform/gpu.js +57 -0
  323. package/dist/platform/index.d.ts +18 -0
  324. package/dist/platform/index.js +10 -0
  325. package/dist/platform/letterbox.d.ts +43 -0
  326. package/dist/platform/letterbox.js +57 -0
  327. package/dist/platform/links.d.ts +20 -0
  328. package/dist/platform/links.js +43 -0
  329. package/dist/platform/screens.d.ts +36 -0
  330. package/dist/platform/screens.js +138 -0
  331. package/dist/platform/surface.d.ts +72 -0
  332. package/dist/platform/surface.js +157 -0
  333. package/dist/platform/xr-fake.d.ts +168 -0
  334. package/dist/platform/xr-fake.js +434 -0
  335. package/dist/platform/xr-surface.d.ts +120 -0
  336. package/dist/platform/xr-surface.js +214 -0
  337. package/dist/platform/xr-types.d.ts +262 -0
  338. package/dist/post/ao.d.ts +12 -0
  339. package/dist/post/ao.js +136 -0
  340. package/dist/post/blend.d.ts +27 -0
  341. package/dist/post/blend.js +129 -0
  342. package/dist/post/depth-pass.d.ts +43 -0
  343. package/dist/post/depth-pass.js +118 -0
  344. package/dist/post/dof.d.ts +1 -0
  345. package/dist/post/dof.js +66 -0
  346. package/dist/post/exposure.d.ts +80 -0
  347. package/dist/post/exposure.js +322 -0
  348. package/dist/post/index.d.ts +12 -0
  349. package/dist/post/index.js +11 -0
  350. package/dist/post/lens-dirt.d.ts +13 -0
  351. package/dist/post/lens-dirt.js +91 -0
  352. package/dist/post/lut.d.ts +19 -0
  353. package/dist/post/lut.js +50 -0
  354. package/dist/post/motion-blur.d.ts +9 -0
  355. package/dist/post/motion-blur.js +78 -0
  356. package/dist/post/post-stack.d.ts +302 -0
  357. package/dist/post/post-stack.js +1137 -0
  358. package/dist/post/settings.d.ts +485 -0
  359. package/dist/post/settings.js +416 -0
  360. package/dist/post/shaders.d.ts +25 -0
  361. package/dist/post/shaders.js +410 -0
  362. package/dist/post/ssr.d.ts +16 -0
  363. package/dist/post/ssr.js +155 -0
  364. package/dist/post/taa.d.ts +74 -0
  365. package/dist/post/taa.js +235 -0
  366. package/dist/post/white-balance.d.ts +25 -0
  367. package/dist/post/white-balance.js +98 -0
  368. package/dist/render/bindings.d.ts +98 -0
  369. package/dist/render/bindings.js +281 -0
  370. package/dist/render/blend.d.ts +13 -0
  371. package/dist/render/blend.js +26 -0
  372. package/dist/render/camera-2d.d.ts +72 -0
  373. package/dist/render/camera-2d.js +92 -0
  374. package/dist/render/camera.d.ts +302 -0
  375. package/dist/render/camera.js +671 -0
  376. package/dist/render/color.d.ts +16 -0
  377. package/dist/render/color.js +41 -0
  378. package/dist/render/compressed.d.ts +104 -0
  379. package/dist/render/compressed.js +248 -0
  380. package/dist/render/diagnostics.d.ts +15 -0
  381. package/dist/render/diagnostics.js +43 -0
  382. package/dist/render/dynamic-resolution.d.ts +70 -0
  383. package/dist/render/dynamic-resolution.js +126 -0
  384. package/dist/render/fake-gpu.d.ts +204 -0
  385. package/dist/render/fake-gpu.js +426 -0
  386. package/dist/render/flipbook.d.ts +56 -0
  387. package/dist/render/flipbook.js +87 -0
  388. package/dist/render/frame.d.ts +278 -0
  389. package/dist/render/frame.js +174 -0
  390. package/dist/render/fullscreen.d.ts +54 -0
  391. package/dist/render/fullscreen.js +91 -0
  392. package/dist/render/gpu-timer.d.ts +73 -0
  393. package/dist/render/gpu-timer.js +186 -0
  394. package/dist/render/index.d.ts +53 -0
  395. package/dist/render/index.js +29 -0
  396. package/dist/render/instance-list.d.ts +185 -0
  397. package/dist/render/instance-list.js +547 -0
  398. package/dist/render/lights.d.ts +181 -0
  399. package/dist/render/lights.js +233 -0
  400. package/dist/render/lod.d.ts +54 -0
  401. package/dist/render/lod.js +52 -0
  402. package/dist/render/material.d.ts +165 -0
  403. package/dist/render/material.js +292 -0
  404. package/dist/render/mesh.d.ts +284 -0
  405. package/dist/render/mesh.js +472 -0
  406. package/dist/render/mipmap.d.ts +16 -0
  407. package/dist/render/mipmap.js +121 -0
  408. package/dist/render/parallax.d.ts +50 -0
  409. package/dist/render/parallax.js +47 -0
  410. package/dist/render/pbr-wgsl.d.ts +31 -0
  411. package/dist/render/pbr-wgsl.js +119 -0
  412. package/dist/render/ping-pong.d.ts +42 -0
  413. package/dist/render/ping-pong.js +74 -0
  414. package/dist/render/renderer.d.ts +741 -0
  415. package/dist/render/renderer.js +2486 -0
  416. package/dist/render/scene-pipelines.d.ts +44 -0
  417. package/dist/render/scene-pipelines.js +92 -0
  418. package/dist/render/scene-target.d.ts +170 -0
  419. package/dist/render/scene-target.js +450 -0
  420. package/dist/render/shadow.d.ts +74 -0
  421. package/dist/render/shadow.js +208 -0
  422. package/dist/render/skin.d.ts +112 -0
  423. package/dist/render/skin.js +240 -0
  424. package/dist/render/snapshot.d.ts +36 -0
  425. package/dist/render/snapshot.js +34 -0
  426. package/dist/render/standard.d.ts +162 -0
  427. package/dist/render/standard.js +263 -0
  428. package/dist/render/texture.d.ts +142 -0
  429. package/dist/render/texture.js +228 -0
  430. package/dist/render/tile-layer.d.ts +110 -0
  431. package/dist/render/tile-layer.js +304 -0
  432. package/dist/render/transform.d.ts +115 -0
  433. package/dist/render/transform.js +318 -0
  434. package/dist/render/wgsl.d.ts +131 -0
  435. package/dist/render/wgsl.js +528 -0
  436. package/dist/save/codec.d.ts +49 -0
  437. package/dist/save/codec.js +169 -0
  438. package/dist/save/index.d.ts +8 -0
  439. package/dist/save/index.js +8 -0
  440. package/dist/save/journal.d.ts +24 -0
  441. package/dist/save/journal.js +102 -0
  442. package/dist/save/migrate.d.ts +15 -0
  443. package/dist/save/migrate.js +37 -0
  444. package/dist/save/schema.d.ts +72 -0
  445. package/dist/save/schema.js +154 -0
  446. package/dist/save/settings.d.ts +28 -0
  447. package/dist/save/settings.js +59 -0
  448. package/dist/save/slots.d.ts +56 -0
  449. package/dist/save/slots.js +200 -0
  450. package/dist/save/storage.d.ts +35 -0
  451. package/dist/save/storage.js +62 -0
  452. package/dist/save/store.d.ts +114 -0
  453. package/dist/save/store.js +269 -0
  454. package/dist/testing/fake-host.d.ts +103 -0
  455. package/dist/testing/fake-host.js +163 -0
  456. package/dist/testing/fixed-clock.d.ts +25 -0
  457. package/dist/testing/fixed-clock.js +30 -0
  458. package/dist/testing/index.d.ts +4 -0
  459. package/dist/testing/index.js +5 -0
  460. package/dist/testing/test-game.d.ts +76 -0
  461. package/dist/testing/test-game.js +92 -0
  462. package/dist/tween/ease.d.ts +77 -0
  463. package/dist/tween/ease.js +192 -0
  464. package/dist/tween/index.d.ts +8 -0
  465. package/dist/tween/index.js +7 -0
  466. package/dist/tween/timeline.d.ts +78 -0
  467. package/dist/tween/timeline.js +269 -0
  468. package/dist/tween/tween.d.ts +168 -0
  469. package/dist/tween/tween.js +320 -0
  470. package/dist/ui/anchor.d.ts +206 -0
  471. package/dist/ui/anchor.js +307 -0
  472. package/dist/ui/caption.d.ts +122 -0
  473. package/dist/ui/caption.js +286 -0
  474. package/dist/ui/cursor.d.ts +105 -0
  475. package/dist/ui/cursor.js +261 -0
  476. package/dist/ui/dom.d.ts +30 -0
  477. package/dist/ui/dom.js +92 -0
  478. package/dist/ui/floats.d.ts +86 -0
  479. package/dist/ui/floats.js +260 -0
  480. package/dist/ui/hud.d.ts +198 -0
  481. package/dist/ui/hud.js +431 -0
  482. package/dist/ui/index.d.ts +37 -0
  483. package/dist/ui/index.js +34 -0
  484. package/dist/ui/inventory-card.d.ts +52 -0
  485. package/dist/ui/inventory-card.js +173 -0
  486. package/dist/ui/inventory-context.d.ts +29 -0
  487. package/dist/ui/inventory-context.js +125 -0
  488. package/dist/ui/inventory-drag.d.ts +63 -0
  489. package/dist/ui/inventory-drag.js +394 -0
  490. package/dist/ui/inventory-grid.d.ts +66 -0
  491. package/dist/ui/inventory-grid.js +625 -0
  492. package/dist/ui/inventory-radial.d.ts +39 -0
  493. package/dist/ui/inventory-radial.js +168 -0
  494. package/dist/ui/inventory.d.ts +128 -0
  495. package/dist/ui/inventory.js +154 -0
  496. package/dist/ui/layout.d.ts +356 -0
  497. package/dist/ui/layout.js +856 -0
  498. package/dist/ui/link.d.ts +64 -0
  499. package/dist/ui/link.js +155 -0
  500. package/dist/ui/loading.d.ts +40 -0
  501. package/dist/ui/loading.js +157 -0
  502. package/dist/ui/loupe.d.ts +74 -0
  503. package/dist/ui/loupe.js +164 -0
  504. package/dist/ui/menu-nav.d.ts +33 -0
  505. package/dist/ui/menu-nav.js +28 -0
  506. package/dist/ui/minimap-canvas.d.ts +145 -0
  507. package/dist/ui/minimap-canvas.js +460 -0
  508. package/dist/ui/notify.d.ts +40 -0
  509. package/dist/ui/notify.js +141 -0
  510. package/dist/ui/orb.d.ts +53 -0
  511. package/dist/ui/orb.js +304 -0
  512. package/dist/ui/overlay.d.ts +213 -0
  513. package/dist/ui/overlay.js +394 -0
  514. package/dist/ui/padnav.d.ts +53 -0
  515. package/dist/ui/padnav.js +146 -0
  516. package/dist/ui/perf.d.ts +130 -0
  517. package/dist/ui/perf.js +329 -0
  518. package/dist/ui/rotate-card.d.ts +54 -0
  519. package/dist/ui/rotate-card.js +97 -0
  520. package/dist/ui/stack.d.ts +128 -0
  521. package/dist/ui/stack.js +312 -0
  522. package/dist/ui/styles.d.ts +13 -0
  523. package/dist/ui/styles.js +200 -0
  524. package/dist/ui/text-scale.d.ts +67 -0
  525. package/dist/ui/text-scale.js +102 -0
  526. package/dist/ui/theme.d.ts +70 -0
  527. package/dist/ui/theme.js +98 -0
  528. package/dist/ui/toast.d.ts +23 -0
  529. package/dist/ui/toast.js +46 -0
  530. package/dist/ui/tooltip.d.ts +89 -0
  531. package/dist/ui/tooltip.js +333 -0
  532. package/dist/ui/widgets-2.d.ts +134 -0
  533. package/dist/ui/widgets-2.js +399 -0
  534. package/dist/ui/widgets-3.d.ts +91 -0
  535. package/dist/ui/widgets-3.js +212 -0
  536. package/dist/ui/widgets.d.ts +34 -0
  537. package/dist/ui/widgets.js +50 -0
  538. package/dist/ui/world-panel/index.d.ts +5 -0
  539. package/dist/ui/world-panel/index.js +5 -0
  540. package/dist/ui/world-panel/layout.d.ts +38 -0
  541. package/dist/ui/world-panel/layout.js +68 -0
  542. package/dist/ui/world-panel/paint.d.ts +96 -0
  543. package/dist/ui/world-panel/paint.js +136 -0
  544. package/dist/ui/world-panel/panel.d.ts +235 -0
  545. package/dist/ui/world-panel/panel.js +762 -0
  546. package/dist/ui/world-panel/wgsl.d.ts +10 -0
  547. package/dist/ui/world-panel/wgsl.js +52 -0
  548. package/dist/ui/world-panel/widgets.d.ts +207 -0
  549. package/dist/ui/world-panel/widgets.js +569 -0
  550. package/dist/voxel/chunks.d.ts +77 -0
  551. package/dist/voxel/chunks.js +149 -0
  552. package/dist/voxel/grid.d.ts +84 -0
  553. package/dist/voxel/grid.js +223 -0
  554. package/dist/voxel/index.d.ts +22 -0
  555. package/dist/voxel/index.js +7 -0
  556. package/dist/voxel/mesher-worker.d.ts +14 -0
  557. package/dist/voxel/mesher-worker.js +47 -0
  558. package/dist/voxel/mesher.d.ts +73 -0
  559. package/dist/voxel/mesher.js +306 -0
  560. package/dist/voxel/ray.d.ts +32 -0
  561. package/dist/voxel/ray.js +73 -0
  562. package/dist/voxel/wgsl.d.ts +16 -0
  563. package/dist/voxel/wgsl.js +28 -0
  564. package/dist/voxel/worker-client.d.ts +79 -0
  565. package/dist/voxel/worker-client.js +122 -0
  566. package/package.json +177 -3
@@ -0,0 +1,28 @@
1
+ import { focusableWithin } from './dom.js';
2
+ import { activateLink } from './link.js';
3
+ const DEFAULT_ACTIONS = { up: 'up', down: 'down', confirm: 'confirm' };
4
+ /**
5
+ * One tick of menu navigation over the focusable controls in `root`. Call it from the scene's
6
+ * update while no modal is open. Up and down move focus (wrapping; from outside the menu, down
7
+ * goes to the first control and up to the last). Confirm from a gamepad activates the focused
8
+ * control.
9
+ */
10
+ export function menuNav(input, root, actions = DEFAULT_ACTIONS) {
11
+ const step = input.pressed(actions.down) ? 1 : input.pressed(actions.up) ? -1 : 0;
12
+ const active = root.ownerDocument.activeElement;
13
+ const inside = !!active && active !== root && root.contains(active);
14
+ if (step) {
15
+ const items = focusableWithin(root);
16
+ if (!items.length)
17
+ return null;
18
+ const at = inside ? items.indexOf(active) : -1;
19
+ const next = at < 0 ? (step > 0 ? 0 : items.length - 1) : (at + step + items.length) % items.length;
20
+ items[next]?.focus({ preventScroll: true });
21
+ return 'moved';
22
+ }
23
+ if (inside && input.lastDevice === 'gamepad' && input.pressed(actions.confirm)) {
24
+ activateLink(active, 'gamepad');
25
+ return 'clicked';
26
+ }
27
+ return null;
28
+ }
@@ -0,0 +1,145 @@
1
+ import type { Layout, RegionName, WidgetOptions } from './layout.js';
2
+ /** What the canvas minimap needs from its overlay (`Overlay` fits). */
3
+ export interface CanvasMinimapHost {
4
+ readonly layers: {
5
+ readonly hud: HTMLElement;
6
+ };
7
+ readonly layout: Layout;
8
+ }
9
+ /** The world's ground rectangle the background covers. */
10
+ export interface MinimapWorld {
11
+ minX: number;
12
+ minZ: number;
13
+ maxX: number;
14
+ maxZ: number;
15
+ }
16
+ export type MinimapRotate = 'north' | 'player';
17
+ export type MinimapShape = 'round' | 'square';
18
+ /** `arrow` is the player's arrow shape, turned to the marker's `heading` (ws/ui-7). */
19
+ export type MinimapMarkerShape = 'dot' | 'square' | 'diamond' | 'triangle' | 'ring' | 'arrow';
20
+ /** How a marker kind draws. */
21
+ export interface MinimapKindStyle {
22
+ shape?: MinimapMarkerShape;
23
+ /** CSS colour or `var(--tc-…)`. */
24
+ color?: string;
25
+ /** Diameter, map px (an arrow's length; the player's arrow is 16). Default 8. */
26
+ size?: number;
27
+ }
28
+ /** One marker for `setMarkers`. */
29
+ export interface MinimapMarker {
30
+ id: string;
31
+ x: number;
32
+ z: number;
33
+ kind: string;
34
+ /** Over the kind's colour. */
35
+ color?: string;
36
+ /** A short glyph drawn on the marker (one or two characters), in the theme text colour. */
37
+ icon?: string;
38
+ /**
39
+ * Facing, radians clockwise from north (−z), the convention of `setPlayer`'s yaw (ws/ui-7).
40
+ * An `arrow` kind points this way; other shapes do not turn. Default 0 (north).
41
+ */
42
+ heading?: number;
43
+ }
44
+ /** Where a marker is drawn, as of now (`markerAt`). */
45
+ export interface MinimapMarkerPlace {
46
+ /** Map px from the top-left (`size` units), after the rim clamp. */
47
+ x: number;
48
+ y: number;
49
+ /** True while held on the rim (past the view's edge). */
50
+ outside: boolean;
51
+ /**
52
+ * The marker's heading as drawn on the map, radians clockwise from up: `heading` on a north-up
53
+ * map, `heading − yaw` on a player-up one (`heading` defaults to 0, north). An `arrow` is turned
54
+ * by this.
55
+ * `markerAt` always writes it (optional so an `out` from before ws/ui-7 still type-checks).
56
+ */
57
+ angle?: number;
58
+ }
59
+ export type MinimapBackground = HTMLCanvasElement | ImageBitmap | HTMLImageElement;
60
+ export interface CanvasMinimapOptions {
61
+ /** Width and height, design px. Default 200. */
62
+ size?: number;
63
+ world: MinimapWorld;
64
+ /** Default `'north'`. */
65
+ rotate?: MinimapRotate;
66
+ /** Default `'round'`. */
67
+ shape?: MinimapShape;
68
+ /** Default `'player'`. */
69
+ center?: 'player' | 'world';
70
+ /** Default 1 (the world's longer side spans the map). */
71
+ zoom?: number;
72
+ /**
73
+ * World units from the centre to the rim, over `zoom`: a marker farther than this from the
74
+ * centre is held on the rim. Sets `zoom` to match.
75
+ */
76
+ worldRadius?: number;
77
+ background?: MinimapBackground | null;
78
+ /** Styles per marker kind, over the defaults (`self`, `ally`, `enemy`, `objective`, `info`). */
79
+ kinds?: Readonly<Record<string, MinimapKindStyle>>;
80
+ /** Click or tap on the map, in world units. */
81
+ onPick?: (x: number, z: number) => void;
82
+ /** Layout region. Default `right`. */
83
+ region?: RegionName;
84
+ /**
85
+ * Placement per form factor, as `layout.add` takes it; overrides `region`. A phone's side rail
86
+ * is 56 px, so a full-size map usually wants `{ default: 'right', 'phone-landscape': 'cardLane' }`.
87
+ * The map shrinks (square) to fit a smaller fixed region; in a content bar or rail it holds
88
+ * `size` and the track grows to it (ws/ui-11). `toMap`/picks stay in `size` units.
89
+ */
90
+ place?: WidgetOptions['place'];
91
+ order?: number;
92
+ /** Accessible name. Default `'Map'`. */
93
+ label?: string;
94
+ }
95
+ export interface CanvasMinimap {
96
+ readonly el: HTMLElement;
97
+ readonly canvas: HTMLCanvasElement;
98
+ readonly size: number;
99
+ /** Draws so far. */
100
+ readonly redraws: number;
101
+ /** Markers held. */
102
+ readonly markers: number;
103
+ /** Markers held on the rim (past the view's edge) as of the last draw. */
104
+ readonly rim: number;
105
+ /** View zoom; setting it redraws. */
106
+ zoom: number;
107
+ /** Replace the markers (copied; an unchanged list does not redraw). */
108
+ setMarkers(list: readonly MinimapMarker[]): void;
109
+ /** The player's place and heading (radians, clockwise from north, −z). */
110
+ setPlayer(x: number, z: number, yaw: number): void;
111
+ /** The game's painted layout over the world rectangle, or null for none. */
112
+ setBackground(bg: MinimapBackground | null): void;
113
+ /** World → map px (from the top-left, `size` units). Allocates nothing. */
114
+ toMap(x: number, z: number, out: {
115
+ x: number;
116
+ y: number;
117
+ }): {
118
+ x: number;
119
+ y: number;
120
+ };
121
+ /** Map px → world (`out.x`, `out.y` are world x and z). The inverse of `toMap`. */
122
+ toWorld(u: number, v: number, out: {
123
+ x: number;
124
+ y: number;
125
+ }): {
126
+ x: number;
127
+ y: number;
128
+ };
129
+ /**
130
+ * Where the marker `id` is drawn now (map px from the top-left, rim-clamped) and whether it is
131
+ * on the rim; null for an unknown id. Writes `out` when given (no allocation).
132
+ */
133
+ markerAt(id: string, out?: MinimapMarkerPlace): MinimapMarkerPlace | null;
134
+ /** Draw a pending change now (normally on the next animation frame). */
135
+ flush(): void;
136
+ remove(): void;
137
+ }
138
+ /** The map (see the module comment). */
139
+ export declare function createCanvasMinimap(host: CanvasMinimapHost, opts: CanvasMinimapOptions): CanvasMinimap;
140
+ /**
141
+ * Stylesheet for the canvas minimap (theme tokens).
142
+ */
143
+ export declare const CANVAS_MINIMAP_CSS = "\n.tc-overlay .tc-cminimap { position: relative; width: var(--tc-cminimap-size); height: auto; aspect-ratio: 1;\n max-width: 100%; max-height: 100%; flex: none;\n box-sizing: border-box; border: var(--tc-border-width) solid var(--tc-color-border); box-shadow: var(--tc-shadow);\n border-radius: var(--tc-radius-m); overflow: hidden; background: var(--tc-color-surface); touch-action: none; }\n.tc-overlay .tc-cminimap[data-shape=\"round\"] { border-radius: 50%; }\n.tc-overlay .tc-region[data-content] > .tc-cminimap { max-width: none; max-height: none; }\n.tc-overlay .tc-cminimap-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }\n";
144
+ /** Add `CANVAS_MINIMAP_CSS` to `doc` once (the first map does it). */
145
+ export declare function ensureCanvasMinimapStyles(doc?: Document): void;
@@ -0,0 +1,460 @@
1
+ /**
2
+ * Canvas minimap (ws/ui-5): a map of the ground plane (x, z) of a bounded world, drawn on its own
3
+ * `<canvas>` in a layout region, round or square. The game paints its layout once into a canvas
4
+ * or `ImageBitmap` covering the world rectangle (`setBackground`); the map draws that, the
5
+ * markers (`setMarkers`, a shape per `kind`) and the player's arrow (`setPlayer`).
6
+ *
7
+ * - **Redrawn only on change.** Every setter compares with what it holds and, on a change,
8
+ * schedules one draw on the next animation frame; a still map never touches its canvas.
9
+ * `redraws` counts the draws, `flush()` draws a pending change now.
10
+ * - **Mapping.** The view is centred on the player (or on the world's centre with `center:
11
+ * 'world'`). At `zoom` 1 the world's longer side spans the map; `zoom` 2 shows half that.
12
+ * `rotate: 'north'` keeps north (−z) up; `'player'` turns the map so the player's heading
13
+ * points up. `toMap(x, z, out)` and `toWorld(u, v, out)` are the pair (map px from the
14
+ * top-left corner, in the map's `size` units), exact inverses. `worldRadius` instead of `zoom`
15
+ * puts the edge that many world units from the centre (a marker farther out is on the rim).
16
+ * - **Pick.** With `onPick`, a click or a tap on the map gives `onPick(worldX, worldZ)` through
17
+ * `toWorld`: click-to-move from the map. Off a round map's disc it is ignored.
18
+ * - Markers past the view's edge sit on the rim, dimmed; `markerAt(id)` says where one is drawn
19
+ * and whether it is on the rim, `rim` counts them. A marker may carry an `icon` (a glyph drawn
20
+ * on it). Colours may be CSS colours or `var(--tc-…)` theme tokens (resolved on each draw).
21
+ * - A marker may carry a `heading` (radians, clockwise from north, as `setPlayer`'s yaw); a kind
22
+ * with `shape: 'arrow'` draws it as the player's arrow, turned to that heading on the map
23
+ * (less the player's yaw on a `rotate: 'player'` map). `markerAt(id).angle` is that turn.
24
+ *
25
+ * `ui.minimap(opts)` is this map on the overlay (ws/ui-6 retired ui-4's DOM minimap).
26
+ */
27
+ import { h } from './dom.js';
28
+ import { themePx } from './hud.js';
29
+ const DEFAULT_KINDS = {
30
+ self: { shape: 'dot', color: 'var(--tc-color-text)' },
31
+ ally: { shape: 'dot', color: 'var(--tc-color-success)' },
32
+ enemy: { shape: 'dot', color: 'var(--tc-color-danger)' },
33
+ objective: { shape: 'diamond', color: 'var(--tc-color-accent)', size: 11 },
34
+ info: { shape: 'square', color: 'var(--tc-color-info)' },
35
+ };
36
+ const FALLBACK = { shape: 'dot', color: 'var(--tc-color-info)' };
37
+ /** Map px between a rim-held marker's centre and the edge. */
38
+ const RIM_INSET = 5;
39
+ /** The map (see the module comment). */
40
+ export function createCanvasMinimap(host, opts) {
41
+ const doc = host.layers.hud.ownerDocument;
42
+ const win = doc.defaultView;
43
+ ensureCanvasMinimapStyles(doc);
44
+ const size = Math.max(16, opts.size ?? 200);
45
+ const half = size / 2;
46
+ const world = { ...opts.world };
47
+ const span = Math.max(1e-6, world.maxX - world.minX, world.maxZ - world.minZ);
48
+ const turn = opts.rotate === 'player';
49
+ const round = (opts.shape ?? 'round') === 'round';
50
+ const followWorld = opts.center === 'world';
51
+ const kinds = { ...DEFAULT_KINDS, ...opts.kinds };
52
+ const onPick = opts.onPick;
53
+ const canvas = h('canvas', { class: 'tc-cminimap-canvas', 'aria-hidden': 'true' });
54
+ const el = h('div', {
55
+ class: onPick ? 'tc-cminimap tc-interactive' : 'tc-cminimap',
56
+ role: 'img',
57
+ 'aria-label': opts.label ?? 'Map',
58
+ dataset: { shape: round ? 'round' : 'square', rotate: turn ? 'player' : 'north' },
59
+ style: { '--tc-cminimap-size': themePx(size) },
60
+ }, canvas);
61
+ const rimPx = half - RIM_INSET;
62
+ let zoom = Math.max(1e-3, opts.worldRadius !== undefined
63
+ ? (rimPx * span) / (size * Math.max(1e-6, opts.worldRadius))
64
+ : (opts.zoom ?? 1));
65
+ let k = (size * zoom) / span;
66
+ let px = (world.minX + world.maxX) / 2;
67
+ let pz = (world.minZ + world.maxZ) / 2;
68
+ let yaw = 0;
69
+ let cos = 1;
70
+ let sin = 0;
71
+ let background = opts.background ?? null;
72
+ // Markers, flattened and grown as needed (a steady list reuses them).
73
+ const ids = [];
74
+ const mx = [];
75
+ const mz = [];
76
+ const mkind = [];
77
+ const mcolor = [];
78
+ const micon = [];
79
+ const mheading = [];
80
+ let count = 0;
81
+ let rim = 0;
82
+ let redraws = 0;
83
+ let dirty = false;
84
+ let raf = 0;
85
+ let removed = false;
86
+ const tmp = { x: 0, y: 0 };
87
+ const centre = () => {
88
+ if (followWorld) {
89
+ tmp.x = (world.minX + world.maxX) / 2;
90
+ tmp.y = (world.minZ + world.maxZ) / 2;
91
+ }
92
+ else {
93
+ tmp.x = px;
94
+ tmp.y = pz;
95
+ }
96
+ return tmp;
97
+ };
98
+ /** The view's rotation: −yaw on a turning map. */
99
+ const setTurn = () => {
100
+ const a = turn ? yaw : 0;
101
+ cos = Math.cos(a);
102
+ sin = Math.sin(a);
103
+ };
104
+ const toMap = (x, z, out) => {
105
+ const c = centre();
106
+ const dx = x - c.x;
107
+ const dz = z - c.y;
108
+ // Rotate by −yaw (y down): the heading (sin yaw, −cos yaw) comes out as (0, −1), up.
109
+ out.x = half + (dx * cos + dz * sin) * k;
110
+ out.y = half + (-dx * sin + dz * cos) * k;
111
+ return out;
112
+ };
113
+ const toWorld = (u, v, out) => {
114
+ const du = (u - half) / k;
115
+ const dv = (v - half) / k;
116
+ const c = centre();
117
+ const cx = c.x;
118
+ const cz = c.y;
119
+ out.x = cx + du * cos - dv * sin;
120
+ out.y = cz + du * sin + dv * cos;
121
+ return out;
122
+ };
123
+ /** Marker `i`'s heading on the map, radians clockwise from up. */
124
+ const markerAngle = (i) => {
125
+ const hd = mheading[i] ?? 0;
126
+ return turn ? hd - yaw : hd;
127
+ };
128
+ /** Marker `i` on the map, rim-clamped, into `tmp`; true when held on the rim. */
129
+ const placeMarker = (i) => {
130
+ toMap(mx[i], mz[i], tmp);
131
+ const x = tmp.x - half;
132
+ const y = tmp.y - half;
133
+ const d = round ? Math.hypot(x, y) : Math.max(Math.abs(x), Math.abs(y));
134
+ if (d <= rimPx)
135
+ return false;
136
+ tmp.x = half + (x / d) * rimPx;
137
+ tmp.y = half + (y / d) * rimPx;
138
+ return true;
139
+ };
140
+ // ---- drawing
141
+ const fonts = new Map();
142
+ const iconFont = (markerSize) => {
143
+ const px = Math.round(markerSize * 1.1);
144
+ let f = fonts.get(px);
145
+ if (f === undefined) {
146
+ f = `700 ${px}px sans-serif`;
147
+ fonts.set(px, f);
148
+ }
149
+ return f;
150
+ };
151
+ const tokens = new Map();
152
+ let computed = null;
153
+ const resolve = (color) => {
154
+ const m = /^var\((--[\w-]+)\)$/.exec(color.trim());
155
+ if (!m)
156
+ return color;
157
+ let v = tokens.get(m[1]);
158
+ if (v === undefined) {
159
+ computed ??= win?.getComputedStyle(el) ?? null;
160
+ v = computed?.getPropertyValue(m[1]).trim() || '#fff';
161
+ tokens.set(m[1], v);
162
+ }
163
+ return v;
164
+ };
165
+ const marker = (ctx, x, y, style, color, dim, angle) => {
166
+ const r = (style.size ?? 8) / 2;
167
+ ctx.globalAlpha = dim ? 0.55 : 1;
168
+ ctx.fillStyle = color;
169
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.75)';
170
+ ctx.lineWidth = 1.5;
171
+ if (style.shape === 'arrow') {
172
+ arrow(ctx, x, y, r, angle);
173
+ ctx.globalAlpha = 1;
174
+ return;
175
+ }
176
+ ctx.beginPath();
177
+ switch (style.shape ?? 'dot') {
178
+ case 'square':
179
+ ctx.rect(x - r, y - r, r * 2, r * 2);
180
+ break;
181
+ case 'diamond':
182
+ ctx.moveTo(x, y - r * 1.2);
183
+ ctx.lineTo(x + r * 1.2, y);
184
+ ctx.lineTo(x, y + r * 1.2);
185
+ ctx.lineTo(x - r * 1.2, y);
186
+ ctx.closePath();
187
+ break;
188
+ case 'triangle':
189
+ ctx.moveTo(x, y - r * 1.2);
190
+ ctx.lineTo(x + r * 1.1, y + r * 0.9);
191
+ ctx.lineTo(x - r * 1.1, y + r * 0.9);
192
+ ctx.closePath();
193
+ break;
194
+ case 'ring':
195
+ ctx.arc(x, y, r, 0, Math.PI * 2);
196
+ ctx.strokeStyle = color;
197
+ ctx.lineWidth = 2.5;
198
+ ctx.stroke();
199
+ ctx.globalAlpha = 1;
200
+ return;
201
+ default:
202
+ ctx.arc(x, y, r, 0, Math.PI * 2);
203
+ }
204
+ ctx.fill();
205
+ ctx.stroke();
206
+ ctx.globalAlpha = 1;
207
+ };
208
+ /** The arrow (half-length `r`; the player's is 8) at (x, y), turned by `angle`; fill and stroke as set. */
209
+ const arrow = (ctx, x, y, r, angle) => {
210
+ ctx.save();
211
+ ctx.translate(x, y);
212
+ ctx.rotate(angle);
213
+ ctx.beginPath();
214
+ ctx.moveTo(0, -r);
215
+ ctx.lineTo(r * 0.75, r * 0.75);
216
+ ctx.lineTo(0, r * 0.375);
217
+ ctx.lineTo(-r * 0.75, r * 0.75);
218
+ ctx.closePath();
219
+ ctx.fill();
220
+ ctx.stroke();
221
+ ctx.restore();
222
+ };
223
+ const draw = () => {
224
+ dirty = false;
225
+ redraws++;
226
+ computed = null;
227
+ tokens.clear();
228
+ // Backing store: the canvas's CSS size × devicePixelRatio, else the design size.
229
+ const rect = canvas.getBoundingClientRect?.();
230
+ const dpr = win?.devicePixelRatio ?? 1;
231
+ const bw = Math.max(1, Math.round((rect && rect.width > 0 ? rect.width : size) * dpr));
232
+ if (canvas.width !== bw)
233
+ canvas.width = bw;
234
+ if (canvas.height !== bw)
235
+ canvas.height = bw;
236
+ const ctx = canvas.getContext?.('2d') ?? null;
237
+ if (!ctx) {
238
+ let onRim = 0;
239
+ for (let i = 0; i < count; i++)
240
+ if (placeMarker(i))
241
+ onRim++;
242
+ rim = onRim;
243
+ return;
244
+ }
245
+ const s = bw / size;
246
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
247
+ ctx.clearRect(0, 0, bw, bw);
248
+ ctx.setTransform(s, 0, 0, s, 0, 0);
249
+ ctx.save();
250
+ ctx.beginPath();
251
+ if (round)
252
+ ctx.arc(half, half, half, 0, Math.PI * 2);
253
+ else
254
+ ctx.rect(0, 0, size, size);
255
+ ctx.clip();
256
+ ctx.fillStyle = resolve('var(--tc-color-surface)');
257
+ ctx.fillRect(0, 0, size, size);
258
+ if (background) {
259
+ // World → map as a canvas transform, then the picture over the world rectangle.
260
+ const c = centre();
261
+ ctx.save();
262
+ ctx.translate(half, half);
263
+ ctx.rotate(-(turn ? yaw : 0));
264
+ ctx.scale(k, k);
265
+ ctx.translate(-c.x, -c.y);
266
+ ctx.drawImage(background, world.minX, world.minZ, world.maxX - world.minX, world.maxZ - world.minZ);
267
+ ctx.restore();
268
+ }
269
+ ctx.restore();
270
+ // Markers, held on the rim past the edge.
271
+ let onRim = 0;
272
+ for (let i = 0; i < count; i++) {
273
+ const dim = placeMarker(i);
274
+ if (dim)
275
+ onRim++;
276
+ const style = kinds[mkind[i]] ?? FALLBACK;
277
+ const color = resolve(mcolor[i] ?? style.color ?? '#fff');
278
+ marker(ctx, tmp.x, tmp.y, style, color, dim, markerAngle(i));
279
+ const icon = micon[i];
280
+ if (icon) {
281
+ ctx.globalAlpha = dim ? 0.55 : 1;
282
+ ctx.fillStyle = resolve('var(--tc-color-text)');
283
+ ctx.font = iconFont(style.size ?? 8);
284
+ ctx.textAlign = 'center';
285
+ ctx.textBaseline = 'middle';
286
+ ctx.fillText(icon, tmp.x, tmp.y);
287
+ ctx.globalAlpha = 1;
288
+ }
289
+ }
290
+ rim = onRim;
291
+ // The player's arrow.
292
+ toMap(px, pz, tmp);
293
+ ctx.fillStyle = resolve('var(--tc-color-accent)');
294
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.8)';
295
+ ctx.lineWidth = 1.5;
296
+ arrow(ctx, tmp.x, tmp.y, 8, turn ? 0 : yaw);
297
+ };
298
+ const schedule = () => {
299
+ if (removed)
300
+ return;
301
+ dirty = true;
302
+ if (raf)
303
+ return;
304
+ const run = () => {
305
+ raf = 0;
306
+ if (dirty && !removed)
307
+ draw();
308
+ };
309
+ if (win?.requestAnimationFrame)
310
+ raf = win.requestAnimationFrame(run);
311
+ else {
312
+ raf = 1;
313
+ queueMicrotask(run);
314
+ }
315
+ };
316
+ // ---- pick
317
+ const pickAt = (clientX, clientY) => {
318
+ const r = canvas.getBoundingClientRect();
319
+ if (!(r.width > 0 && r.height > 0))
320
+ return;
321
+ const u = ((clientX - r.left) / r.width) * size;
322
+ const v = ((clientY - r.top) / r.height) * size;
323
+ if (round && Math.hypot(u - half, v - half) > half)
324
+ return;
325
+ toWorld(u, v, tmp);
326
+ onPick?.(tmp.x, tmp.y);
327
+ };
328
+ const onDown = (e) => {
329
+ if (e.button !== 0 || !e.isPrimary)
330
+ return;
331
+ e.preventDefault();
332
+ e.stopPropagation();
333
+ pickAt(e.clientX, e.clientY);
334
+ };
335
+ if (onPick)
336
+ el.addEventListener('pointerdown', onDown);
337
+ setTurn();
338
+ const handle = host.layout.add(el, {
339
+ place: opts.place ?? { default: opts.region ?? 'right' },
340
+ order: opts.order,
341
+ });
342
+ schedule();
343
+ return {
344
+ el,
345
+ canvas,
346
+ size,
347
+ get redraws() {
348
+ return redraws;
349
+ },
350
+ get markers() {
351
+ return count;
352
+ },
353
+ get rim() {
354
+ return rim;
355
+ },
356
+ get zoom() {
357
+ return zoom;
358
+ },
359
+ set zoom(z) {
360
+ const next = Math.max(1e-3, z);
361
+ if (next === zoom)
362
+ return;
363
+ zoom = next;
364
+ k = (size * zoom) / span;
365
+ schedule();
366
+ },
367
+ setMarkers(list) {
368
+ let changed = list.length !== count;
369
+ for (let i = 0; i < list.length; i++) {
370
+ const m = list[i];
371
+ if (!changed &&
372
+ ids[i] === m.id &&
373
+ mx[i] === m.x &&
374
+ mz[i] === m.z &&
375
+ mkind[i] === m.kind &&
376
+ mcolor[i] === m.color &&
377
+ micon[i] === m.icon &&
378
+ mheading[i] === m.heading) {
379
+ continue;
380
+ }
381
+ changed = true;
382
+ ids[i] = m.id;
383
+ mx[i] = m.x;
384
+ mz[i] = m.z;
385
+ mkind[i] = m.kind;
386
+ mcolor[i] = m.color;
387
+ micon[i] = m.icon;
388
+ mheading[i] = m.heading;
389
+ }
390
+ count = list.length;
391
+ if (changed)
392
+ schedule();
393
+ },
394
+ setPlayer(x, z, y) {
395
+ if (x === px && z === pz && y === yaw)
396
+ return;
397
+ px = x;
398
+ pz = z;
399
+ yaw = y;
400
+ setTurn();
401
+ schedule();
402
+ },
403
+ setBackground(bg) {
404
+ if (bg === background)
405
+ return;
406
+ background = bg;
407
+ schedule();
408
+ },
409
+ toMap,
410
+ toWorld,
411
+ markerAt(id, out) {
412
+ for (let i = 0; i < count; i++) {
413
+ if (ids[i] !== id)
414
+ continue;
415
+ const outside = placeMarker(i);
416
+ const o = out ?? { x: 0, y: 0, outside: false, angle: 0 };
417
+ o.x = tmp.x;
418
+ o.y = tmp.y;
419
+ o.outside = outside;
420
+ o.angle = markerAngle(i);
421
+ return o;
422
+ }
423
+ return null;
424
+ },
425
+ flush() {
426
+ if (dirty && !removed)
427
+ draw();
428
+ },
429
+ remove() {
430
+ removed = true;
431
+ if (raf && win?.cancelAnimationFrame && raf !== 1)
432
+ win.cancelAnimationFrame(raf);
433
+ el.removeEventListener('pointerdown', onDown);
434
+ handle.remove();
435
+ el.remove();
436
+ },
437
+ };
438
+ }
439
+ /**
440
+ * Stylesheet for the canvas minimap (theme tokens).
441
+ */
442
+ export const CANVAS_MINIMAP_CSS = `
443
+ .tc-overlay .tc-cminimap { position: relative; width: var(--tc-cminimap-size); height: auto; aspect-ratio: 1;
444
+ max-width: 100%; max-height: 100%; flex: none;
445
+ box-sizing: border-box; border: var(--tc-border-width) solid var(--tc-color-border); box-shadow: var(--tc-shadow);
446
+ border-radius: var(--tc-radius-m); overflow: hidden; background: var(--tc-color-surface); touch-action: none; }
447
+ .tc-overlay .tc-cminimap[data-shape="round"] { border-radius: 50%; }
448
+ .tc-overlay .tc-region[data-content] > .tc-cminimap { max-width: none; max-height: none; }
449
+ .tc-overlay .tc-cminimap-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
450
+ `;
451
+ const STYLE_ID = 'tc-ui-cminimap';
452
+ /** Add `CANVAS_MINIMAP_CSS` to `doc` once (the first map does it). */
453
+ export function ensureCanvasMinimapStyles(doc = document) {
454
+ if (doc.getElementById(STYLE_ID))
455
+ return;
456
+ const style = doc.createElement('style');
457
+ style.id = STYLE_ID;
458
+ style.textContent = CANVAS_MINIMAP_CSS;
459
+ doc.head.appendChild(style);
460
+ }
@@ -0,0 +1,40 @@
1
+ export type NotifyTone = 'info' | 'success' | 'warn' | 'danger';
2
+ export interface NotifyAction {
3
+ label: string;
4
+ /** Runs, then the notification is dismissed unless `keep` is set. */
5
+ onClick: () => void;
6
+ keep?: boolean;
7
+ }
8
+ export interface NotifyOptions {
9
+ title: string;
10
+ body?: string | Node;
11
+ /** A glyph or node at the left. */
12
+ icon?: string | Node;
13
+ tone?: NotifyTone;
14
+ actions?: readonly NotifyAction[];
15
+ /** ms before it disappears; paused while hovered or focused. `0` = until dismissed. Default 6000. */
16
+ timeout?: number;
17
+ }
18
+ export interface Notification {
19
+ readonly element: HTMLElement;
20
+ readonly open: boolean;
21
+ dismiss(): void;
22
+ }
23
+ export interface Notifier {
24
+ /** The stack (`role=status`, `aria-live=polite`); the root for `menuNav`. */
25
+ readonly element: HTMLElement;
26
+ readonly count: number;
27
+ notify(opts: NotifyOptions): Notification;
28
+ dismissAll(): void;
29
+ /** Focus the first action (or close button) of the newest notification, for pad users. */
30
+ focus(): boolean;
31
+ dispose(): void;
32
+ }
33
+ /** A notifier stacked top-right in `container` (the overlay's `toasts` layer). */
34
+ export declare function createNotifier(container: HTMLElement, max?: number): Notifier;
35
+ /**
36
+ * Stylesheet for notifications (design px, theme tokens).
37
+ */
38
+ export declare const NOTIFY_CSS: string;
39
+ /** Add `NOTIFY_CSS` to `doc` once (the first notification does it). */
40
+ export declare function ensureNotifyStyles(doc?: Document): void;