@cavegiant/cave-world-r3f 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -0
  4. package/dist/core/connector-label/readiness.d.ts +11 -0
  5. package/dist/core/connector-label/readiness.d.ts.map +1 -0
  6. package/dist/core/connector-label/readiness.js +31 -0
  7. package/dist/core/connector-label/readiness.js.map +1 -0
  8. package/dist/core/connector-label/types.d.ts +64 -0
  9. package/dist/core/connector-label/types.d.ts.map +1 -0
  10. package/dist/core/connector-label/types.js +47 -0
  11. package/dist/core/connector-label/types.js.map +1 -0
  12. package/dist/core/context/cave-world-context.d.ts +96 -0
  13. package/dist/core/context/cave-world-context.d.ts.map +1 -0
  14. package/dist/core/context/cave-world-context.js +100 -0
  15. package/dist/core/context/cave-world-context.js.map +1 -0
  16. package/dist/core/errors.d.ts +34 -0
  17. package/dist/core/errors.d.ts.map +1 -0
  18. package/dist/core/errors.js +17 -0
  19. package/dist/core/errors.js.map +1 -0
  20. package/dist/core/events/event-bus.d.ts +122 -0
  21. package/dist/core/events/event-bus.d.ts.map +1 -0
  22. package/dist/core/events/event-bus.js +62 -0
  23. package/dist/core/events/event-bus.js.map +1 -0
  24. package/dist/core/hooks/use-cave-event.d.ts +13 -0
  25. package/dist/core/hooks/use-cave-event.d.ts.map +1 -0
  26. package/dist/core/hooks/use-cave-event.js +12 -0
  27. package/dist/core/hooks/use-cave-event.js.map +1 -0
  28. package/dist/core/i18n/messages.d.ts +82 -0
  29. package/dist/core/i18n/messages.d.ts.map +1 -0
  30. package/dist/core/i18n/messages.js +131 -0
  31. package/dist/core/i18n/messages.js.map +1 -0
  32. package/dist/core/index.d.ts +11 -0
  33. package/dist/core/index.d.ts.map +1 -0
  34. package/dist/core/index.js +47 -0
  35. package/dist/core/index.js.map +1 -0
  36. package/dist/core/logging/logger.d.ts +29 -0
  37. package/dist/core/logging/logger.d.ts.map +1 -0
  38. package/dist/core/logging/logger.js +47 -0
  39. package/dist/core/logging/logger.js.map +1 -0
  40. package/dist/core/registry/component-registry.d.ts +41 -0
  41. package/dist/core/registry/component-registry.d.ts.map +1 -0
  42. package/dist/core/registry/component-registry.js +34 -0
  43. package/dist/core/registry/component-registry.js.map +1 -0
  44. package/dist/core/registry/object-registry.d.ts +38 -0
  45. package/dist/core/registry/object-registry.d.ts.map +1 -0
  46. package/dist/core/registry/object-registry.js +32 -0
  47. package/dist/core/registry/object-registry.js.map +1 -0
  48. package/dist/explore/cave-explore.d.ts +85 -0
  49. package/dist/explore/cave-explore.d.ts.map +1 -0
  50. package/dist/explore/cave-explore.js +204 -0
  51. package/dist/explore/cave-explore.js.map +1 -0
  52. package/dist/explore/cave-orbit-viewer.d.ts +76 -0
  53. package/dist/explore/cave-orbit-viewer.d.ts.map +1 -0
  54. package/dist/explore/cave-orbit-viewer.js +123 -0
  55. package/dist/explore/cave-orbit-viewer.js.map +1 -0
  56. package/dist/explore/characters/character-configs.d.ts +38 -0
  57. package/dist/explore/characters/character-configs.d.ts.map +1 -0
  58. package/dist/explore/characters/character-configs.js +45 -0
  59. package/dist/explore/characters/character-configs.js.map +1 -0
  60. package/dist/explore/characters/character-controls.d.ts +44 -0
  61. package/dist/explore/characters/character-controls.d.ts.map +1 -0
  62. package/dist/explore/characters/character-pose.d.ts +19 -0
  63. package/dist/explore/characters/character-pose.d.ts.map +1 -0
  64. package/dist/explore/characters/character-pose.js +13 -0
  65. package/dist/explore/characters/character-pose.js.map +1 -0
  66. package/dist/explore/characters/local-character-model.d.ts +53 -0
  67. package/dist/explore/characters/local-character-model.d.ts.map +1 -0
  68. package/dist/explore/characters/local-character-model.js +36 -0
  69. package/dist/explore/characters/local-character-model.js.map +1 -0
  70. package/dist/explore/characters/mixamo-style-bone-map.d.ts +9 -0
  71. package/dist/explore/characters/mixamo-style-bone-map.d.ts.map +1 -0
  72. package/dist/explore/characters/mixamo-style-bone-map.js +28 -0
  73. package/dist/explore/characters/mixamo-style-bone-map.js.map +1 -0
  74. package/dist/explore/characters/remote-character-controller.d.ts +38 -0
  75. package/dist/explore/characters/remote-character-controller.d.ts.map +1 -0
  76. package/dist/explore/characters/remote-character-controller.js +135 -0
  77. package/dist/explore/characters/remote-character-controller.js.map +1 -0
  78. package/dist/explore/characters/remote-character.d.ts +19 -0
  79. package/dist/explore/characters/remote-character.d.ts.map +1 -0
  80. package/dist/explore/characters/remote-character.js +63 -0
  81. package/dist/explore/characters/remote-character.js.map +1 -0
  82. package/dist/explore/connected-spaces-renderer.d.ts +16 -0
  83. package/dist/explore/connected-spaces-renderer.d.ts.map +1 -0
  84. package/dist/explore/connected-spaces-renderer.js +103 -0
  85. package/dist/explore/connected-spaces-renderer.js.map +1 -0
  86. package/dist/explore/hooks/use-action-shortcuts.d.ts +16 -0
  87. package/dist/explore/hooks/use-action-shortcuts.d.ts.map +1 -0
  88. package/dist/explore/hooks/use-action-shortcuts.js +23 -0
  89. package/dist/explore/hooks/use-action-shortcuts.js.map +1 -0
  90. package/dist/explore/hooks/use-active-space-notify.d.ts +11 -0
  91. package/dist/explore/hooks/use-active-space-notify.d.ts.map +1 -0
  92. package/dist/explore/hooks/use-active-space-notify.js +17 -0
  93. package/dist/explore/hooks/use-active-space-notify.js.map +1 -0
  94. package/dist/explore/hooks/use-character-sync.d.ts +46 -0
  95. package/dist/explore/hooks/use-character-sync.d.ts.map +1 -0
  96. package/dist/explore/hooks/use-character-sync.js +72 -0
  97. package/dist/explore/hooks/use-character-sync.js.map +1 -0
  98. package/dist/explore/hooks/use-connector-preloader.d.ts +20 -0
  99. package/dist/explore/hooks/use-connector-preloader.d.ts.map +1 -0
  100. package/dist/explore/hooks/use-connector-preloader.js +78 -0
  101. package/dist/explore/hooks/use-connector-preloader.js.map +1 -0
  102. package/dist/explore/hooks/use-connector-transitions.d.ts +31 -0
  103. package/dist/explore/hooks/use-connector-transitions.d.ts.map +1 -0
  104. package/dist/explore/hooks/use-connector-transitions.js +63 -0
  105. package/dist/explore/hooks/use-connector-transitions.js.map +1 -0
  106. package/dist/explore/hooks/use-explore-actions.d.ts +17 -0
  107. package/dist/explore/hooks/use-explore-actions.d.ts.map +1 -0
  108. package/dist/explore/hooks/use-explore-actions.js +134 -0
  109. package/dist/explore/hooks/use-explore-actions.js.map +1 -0
  110. package/dist/explore/hooks/use-load-error-notify.d.ts +11 -0
  111. package/dist/explore/hooks/use-load-error-notify.d.ts.map +1 -0
  112. package/dist/explore/hooks/use-load-error-notify.js +18 -0
  113. package/dist/explore/hooks/use-load-error-notify.js.map +1 -0
  114. package/dist/explore/hooks/use-primary-space-loader.d.ts +24 -0
  115. package/dist/explore/hooks/use-primary-space-loader.d.ts.map +1 -0
  116. package/dist/explore/hooks/use-primary-space-loader.js +29 -0
  117. package/dist/explore/hooks/use-primary-space-loader.js.map +1 -0
  118. package/dist/explore/index.d.ts +37 -0
  119. package/dist/explore/index.d.ts.map +1 -0
  120. package/dist/explore/index.js +107 -0
  121. package/dist/explore/index.js.map +1 -0
  122. package/dist/explore/loaders/cave-loader.d.ts +58 -0
  123. package/dist/explore/loaders/cave-loader.d.ts.map +1 -0
  124. package/dist/explore/loaders/cave-loader.js +79 -0
  125. package/dist/explore/loaders/cave-loader.js.map +1 -0
  126. package/dist/explore/math/space-transforms.d.ts +49 -0
  127. package/dist/explore/math/space-transforms.d.ts.map +1 -0
  128. package/dist/explore/math/space-transforms.js +54 -0
  129. package/dist/explore/math/space-transforms.js.map +1 -0
  130. package/dist/explore/overlays/action-bubble.d.ts +8 -0
  131. package/dist/explore/overlays/action-bubble.d.ts.map +1 -0
  132. package/dist/explore/overlays/action-bubble.js +18 -0
  133. package/dist/explore/overlays/action-bubble.js.map +1 -0
  134. package/dist/explore/overlays/action-panel.d.ts +12 -0
  135. package/dist/explore/overlays/action-panel.d.ts.map +1 -0
  136. package/dist/explore/overlays/action-panel.js +69 -0
  137. package/dist/explore/overlays/action-panel.js.map +1 -0
  138. package/dist/explore/overlays/connector-label-beacon.d.ts +11 -0
  139. package/dist/explore/overlays/connector-label-beacon.d.ts.map +1 -0
  140. package/dist/explore/overlays/connector-label-beacon.js +38 -0
  141. package/dist/explore/overlays/connector-label-beacon.js.map +1 -0
  142. package/dist/explore/overlays/connector-label-tag-shell.d.ts +16 -0
  143. package/dist/explore/overlays/connector-label-tag-shell.d.ts.map +1 -0
  144. package/dist/explore/overlays/connector-label-tag-shell.js +18 -0
  145. package/dist/explore/overlays/connector-label-tag-shell.js.map +1 -0
  146. package/dist/explore/overlays/detail-window.d.ts +9 -0
  147. package/dist/explore/overlays/detail-window.d.ts.map +1 -0
  148. package/dist/explore/overlays/detail-window.js +92 -0
  149. package/dist/explore/overlays/detail-window.js.map +1 -0
  150. package/dist/explore/overlays/explore-helper.d.ts +44 -0
  151. package/dist/explore/overlays/explore-helper.d.ts.map +1 -0
  152. package/dist/explore/overlays/explore-helper.js +57 -0
  153. package/dist/explore/overlays/explore-helper.js.map +1 -0
  154. package/dist/explore/overlays/icons.d.ts +16 -0
  155. package/dist/explore/overlays/icons.d.ts.map +1 -0
  156. package/dist/explore/overlays/icons.js +34 -0
  157. package/dist/explore/overlays/icons.js.map +1 -0
  158. package/dist/explore/overlays/space-load-error-overlay.d.ts +27 -0
  159. package/dist/explore/overlays/space-load-error-overlay.d.ts.map +1 -0
  160. package/dist/explore/overlays/space-load-error-overlay.js +24 -0
  161. package/dist/explore/overlays/space-load-error-overlay.js.map +1 -0
  162. package/dist/explore/services/websocket.service.d.ts +180 -0
  163. package/dist/explore/services/websocket.service.d.ts.map +1 -0
  164. package/dist/explore/services/websocket.service.js +187 -0
  165. package/dist/explore/services/websocket.service.js.map +1 -0
  166. package/dist/explore/simple-character.d.ts +46 -0
  167. package/dist/explore/simple-character.d.ts.map +1 -0
  168. package/dist/explore/simple-character.js +119 -0
  169. package/dist/explore/simple-character.js.map +1 -0
  170. package/dist/explore/stores/action-prompt.store.d.ts +27 -0
  171. package/dist/explore/stores/action-prompt.store.d.ts.map +1 -0
  172. package/dist/explore/stores/action-prompt.store.js +14 -0
  173. package/dist/explore/stores/action-prompt.store.js.map +1 -0
  174. package/dist/explore/stores/cave-explore.store.d.ts +77 -0
  175. package/dist/explore/stores/cave-explore.store.d.ts.map +1 -0
  176. package/dist/explore/stores/cave-explore.store.js +66 -0
  177. package/dist/explore/stores/cave-explore.store.js.map +1 -0
  178. package/dist/explore/stores/explore-context.d.ts +35 -0
  179. package/dist/explore/stores/explore-context.d.ts.map +1 -0
  180. package/dist/explore/stores/explore-context.js +43 -0
  181. package/dist/explore/stores/explore-context.js.map +1 -0
  182. package/dist/explore/styles/cave-world-css.d.ts +10 -0
  183. package/dist/explore/styles/cave-world-css.d.ts.map +1 -0
  184. package/dist/explore/styles/cave-world-css.js +935 -0
  185. package/dist/explore/styles/cave-world-css.js.map +1 -0
  186. package/dist/explore/styles/inject.d.ts +32 -0
  187. package/dist/explore/styles/inject.d.ts.map +1 -0
  188. package/dist/explore/styles/inject.js +40 -0
  189. package/dist/explore/styles/inject.js.map +1 -0
  190. package/dist/explore/utils/schedule-idle.d.ts +12 -0
  191. package/dist/explore/utils/schedule-idle.d.ts.map +1 -0
  192. package/dist/explore/utils/schedule-idle.js +16 -0
  193. package/dist/explore/utils/schedule-idle.js.map +1 -0
  194. package/dist/explore/viewer-shared.d.ts +56 -0
  195. package/dist/explore/viewer-shared.d.ts.map +1 -0
  196. package/dist/index.d.ts +16 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/index.js +78 -0
  199. package/dist/index.js.map +1 -0
  200. package/dist/space/cave-base-layer.d.ts +42 -0
  201. package/dist/space/cave-base-layer.d.ts.map +1 -0
  202. package/dist/space/cave-base-layer.js +221 -0
  203. package/dist/space/cave-base-layer.js.map +1 -0
  204. package/dist/space/cave-custom-layer.d.ts +12 -0
  205. package/dist/space/cave-custom-layer.d.ts.map +1 -0
  206. package/dist/space/cave-custom-layer.js +17 -0
  207. package/dist/space/cave-custom-layer.js.map +1 -0
  208. package/dist/space/cave-env.d.ts +6 -0
  209. package/dist/space/cave-env.d.ts.map +1 -0
  210. package/dist/space/cave-env.js +23 -0
  211. package/dist/space/cave-env.js.map +1 -0
  212. package/dist/space/cave-space.d.ts +46 -0
  213. package/dist/space/cave-space.d.ts.map +1 -0
  214. package/dist/space/cave-space.js +37 -0
  215. package/dist/space/cave-space.js.map +1 -0
  216. package/dist/space/connector-label-host.d.ts +21 -0
  217. package/dist/space/connector-label-host.d.ts.map +1 -0
  218. package/dist/space/connector-label-host.js +65 -0
  219. package/dist/space/connector-label-host.js.map +1 -0
  220. package/dist/space/index.d.ts +18 -0
  221. package/dist/space/index.d.ts.map +1 -0
  222. package/dist/space/index.js +47 -0
  223. package/dist/space/index.js.map +1 -0
  224. package/dist/space/objects/builtin-registrar.d.ts +17 -0
  225. package/dist/space/objects/builtin-registrar.d.ts.map +1 -0
  226. package/dist/space/objects/builtin-registrar.js +19 -0
  227. package/dist/space/objects/builtin-registrar.js.map +1 -0
  228. package/dist/space/objects/custom-object.d.ts +9 -0
  229. package/dist/space/objects/custom-object.d.ts.map +1 -0
  230. package/dist/space/objects/custom-object.js +56 -0
  231. package/dist/space/objects/custom-object.js.map +1 -0
  232. package/dist/space/objects/image-object.d.ts +7 -0
  233. package/dist/space/objects/image-object.d.ts.map +1 -0
  234. package/dist/space/objects/image-object.js +14 -0
  235. package/dist/space/objects/image-object.js.map +1 -0
  236. package/dist/space/objects/model-object/fbx-object.d.ts +8 -0
  237. package/dist/space/objects/model-object/fbx-object.d.ts.map +1 -0
  238. package/dist/space/objects/model-object/fbx-object.js +26 -0
  239. package/dist/space/objects/model-object/fbx-object.js.map +1 -0
  240. package/dist/space/objects/model-object/gltf-object.d.ts +9 -0
  241. package/dist/space/objects/model-object/gltf-object.d.ts.map +1 -0
  242. package/dist/space/objects/model-object/gltf-object.js +66 -0
  243. package/dist/space/objects/model-object/gltf-object.js.map +1 -0
  244. package/dist/space/objects/model-object/index.d.ts +9 -0
  245. package/dist/space/objects/model-object/index.d.ts.map +1 -0
  246. package/dist/space/objects/model-object/index.js +12 -0
  247. package/dist/space/objects/model-object/index.js.map +1 -0
  248. package/dist/space/objects/model-object/splat-object.d.ts +9 -0
  249. package/dist/space/objects/model-object/splat-object.d.ts.map +1 -0
  250. package/dist/space/objects/model-object/splat-object.js +19 -0
  251. package/dist/space/objects/model-object/splat-object.js.map +1 -0
  252. package/dist/space/objects/object-components/windows/index.d.ts +5 -0
  253. package/dist/space/objects/object-components/windows/index.d.ts.map +1 -0
  254. package/dist/space/objects/object-components/windows/index.js +20 -0
  255. package/dist/space/objects/object-components/windows/index.js.map +1 -0
  256. package/dist/space/objects/placeholder-object.d.ts +7 -0
  257. package/dist/space/objects/placeholder-object.d.ts.map +1 -0
  258. package/dist/space/objects/placeholder-object.js +12 -0
  259. package/dist/space/objects/placeholder-object.js.map +1 -0
  260. package/dist/space/objects/poi-object.d.ts +7 -0
  261. package/dist/space/objects/poi-object.d.ts.map +1 -0
  262. package/dist/space/objects/poi-object.js +38 -0
  263. package/dist/space/objects/poi-object.js.map +1 -0
  264. package/dist/space/objects/portal-object.d.ts +7 -0
  265. package/dist/space/objects/portal-object.d.ts.map +1 -0
  266. package/dist/space/objects/portal-object.js +84 -0
  267. package/dist/space/objects/portal-object.js.map +1 -0
  268. package/dist/space/objects/video-object.d.ts +7 -0
  269. package/dist/space/objects/video-object.d.ts.map +1 -0
  270. package/dist/space/objects/video-object.js +32 -0
  271. package/dist/space/objects/video-object.js.map +1 -0
  272. package/dist/space/polygon-boundary.d.ts +10 -0
  273. package/dist/space/polygon-boundary.d.ts.map +1 -0
  274. package/dist/space/polygon-boundary.js +205 -0
  275. package/dist/space/polygon-boundary.js.map +1 -0
  276. package/dist/space/splats/spark/robust-splat-mesh.d.ts +59 -0
  277. package/dist/space/splats/spark/robust-splat-mesh.d.ts.map +1 -0
  278. package/dist/space/splats/spark/robust-splat-mesh.js +105 -0
  279. package/dist/space/splats/spark/robust-splat-mesh.js.map +1 -0
  280. package/dist/space/splats/spark/splat-mesh.d.ts +5 -0
  281. package/dist/space/splats/spark/splat-mesh.d.ts.map +1 -0
  282. package/dist/space/splats/spark/splat-mesh.js +7 -0
  283. package/dist/space/splats/spark/splat-mesh.js.map +1 -0
  284. package/dist/space/splats/spark/splat-spread-reveal.d.ts +14 -0
  285. package/dist/space/splats/spark/splat-spread-reveal.d.ts.map +1 -0
  286. package/dist/space/splats/spark/splat-spread-reveal.js +45 -0
  287. package/dist/space/splats/spark/splat-spread-reveal.js.map +1 -0
  288. package/dist/space/utils/cave-world-player.d.ts +3 -0
  289. package/dist/space/utils/cave-world-player.d.ts.map +1 -0
  290. package/dist/space/utils/cave-world-player.js +5 -0
  291. package/dist/space/utils/cave-world-player.js.map +1 -0
  292. package/dist/space/utils/configure-canvas.d.ts +20 -0
  293. package/dist/space/utils/configure-canvas.d.ts.map +1 -0
  294. package/dist/space/utils/configure-canvas.js +12 -0
  295. package/dist/space/utils/configure-canvas.js.map +1 -0
  296. package/dist/space/utils/polygon-boundary-geometry.d.ts +8 -0
  297. package/dist/space/utils/polygon-boundary-geometry.d.ts.map +1 -0
  298. package/dist/space/utils/polygon-boundary-geometry.js +20 -0
  299. package/dist/space/utils/polygon-boundary-geometry.js.map +1 -0
  300. package/dist/space/utils/polygon-boundary-segments.d.ts +50 -0
  301. package/dist/space/utils/polygon-boundary-segments.d.ts.map +1 -0
  302. package/dist/space/utils/polygon-boundary-segments.js +64 -0
  303. package/dist/space/utils/polygon-boundary-segments.js.map +1 -0
  304. package/dist/space/utils/rotation-compat.d.ts +4 -0
  305. package/dist/space/utils/rotation-compat.d.ts.map +1 -0
  306. package/dist/space/utils/rotation-compat.js +9 -0
  307. package/dist/space/utils/rotation-compat.js.map +1 -0
  308. package/dist/space/utils/select-splat-level.d.ts +52 -0
  309. package/dist/space/utils/select-splat-level.d.ts.map +1 -0
  310. package/dist/space/utils/select-splat-level.js +43 -0
  311. package/dist/space/utils/select-splat-level.js.map +1 -0
  312. package/dist/space/utils/spark-performance.d.ts +10 -0
  313. package/dist/space/utils/spark-performance.d.ts.map +1 -0
  314. package/dist/space/utils/spark-performance.js +10 -0
  315. package/dist/space/utils/spark-performance.js.map +1 -0
  316. package/dist/space/utils/splat-collider-helper.d.ts +5 -0
  317. package/dist/space/utils/splat-collider-helper.d.ts.map +1 -0
  318. package/dist/space/utils/splat-collider-helper.js +162 -0
  319. package/dist/space/utils/splat-collider-helper.js.map +1 -0
  320. package/dist/space/utils/touch-primary-device.d.ts +16 -0
  321. package/dist/space/utils/touch-primary-device.d.ts.map +1 -0
  322. package/dist/space/utils/touch-primary-device.js +52 -0
  323. package/dist/space/utils/touch-primary-device.js.map +1 -0
  324. package/dist/space/utils/use-visibility-frameloop.d.ts +20 -0
  325. package/dist/space/utils/use-visibility-frameloop.d.ts.map +1 -0
  326. package/dist/space/utils/use-visibility-frameloop.js +18 -0
  327. package/dist/space/utils/use-visibility-frameloop.js.map +1 -0
  328. package/dist/styles.css +930 -0
  329. package/dist/types/index.d.ts +2 -0
  330. package/dist/types/index.d.ts.map +1 -0
  331. package/dist/types/index.js +2 -0
  332. package/dist/types/index.js.map +1 -0
  333. package/dist/types/space-types.d.ts +404 -0
  334. package/dist/types/space-types.d.ts.map +1 -0
  335. package/doc/API.md +617 -0
  336. package/doc/ARCHITECTURE.md +264 -0
  337. package/doc/multiplayer-protocol.md +757 -0
  338. package/doc/scene-json-structure.md +567 -0
  339. package/package.json +131 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cave-world-css.js","sources":["../../../explore/styles/cave-world-css.ts"],"sourcesContent":["/**\n * Single source of truth for the default overlay stylesheet.\n *\n * Kept as a TypeScript string rather than a .css import so the SDK stays\n * bundler-agnostic (no ?raw / css-loader requirement), and so the runtime\n * injector and the published dist/styles.css can never drift apart — the Vite\n * build writes that file from this constant.\n */\nexport const CAVE_WORLD_CSS = `/**\n * @cavegiant/cave-world-r3f default UI theme.\n *\n * Every rule is namespaced under '.cw-*' so it cannot collide with host styles,\n * and every visual value is a '--cw-*' custom property so hosts can re-theme the\n * built-in overlays without replacing them.\n *\n * The defaults are declared on ':root' rather than on '.cw-root' on purpose: a\n * declaration on the element itself would shadow anything a host sets on an\n * ancestor, which would make theming silently do nothing.\n *\n * Load it either by importing '@cavegiant/cave-world-r3f/styles.css' or by letting\n * the SDK inject it at runtime (default; see 'injectStyles' on the viewers).\n */\n\n:root {\n --cw-font-sans:\n ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,\n 'PingFang SC', 'Microsoft YaHei', sans-serif;\n --cw-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n\n /* Palette — warm gold primary, mint secondary, over cool dark glass. */\n --cw-color-text: #f5efe6;\n --cw-color-text-bright: #fffaf0;\n --cw-color-text-muted: rgb(245 239 230 / 45%);\n --cw-color-accent: #d4b87a;\n --cw-color-accent-soft: #e8d4a8;\n --cw-color-accent-warm: #d2a380;\n --cw-color-accent-mint: #78c8b0;\n --cw-color-key-text: #f5e6c0;\n --cw-color-shortcut: #ffd700;\n\n --cw-color-surface: rgb(22 24 34 / 82%);\n --cw-color-surface-solid: rgb(31 28 23 / 95%);\n --cw-color-scrim: rgb(0 0 0 / 50%);\n --cw-color-border: rgb(212 184 122 / 22%);\n --cw-color-border-strong: rgb(212 184 122 / 45%);\n --cw-color-border-hover: rgb(120 200 176 / 42%);\n --cw-color-label-surface: rgb(141 134 102 / 75%);\n --cw-color-label-border: rgb(210 163 128 / 80%);\n --cw-color-bubble-surface: rgb(0 0 0 / 70%);\n --cw-color-bubble-border: rgb(255 255 255 / 50%);\n\n /* Panel HUD decoration. */\n --cw-panel-fill: linear-gradient(\n 168deg,\n rgb(32 34 44 / 30%) 0%,\n rgb(22 24 34 / 34%) 50%,\n rgb(14 16 24 / 38%) 100%\n );\n --cw-panel-rim: conic-gradient(\n from 135deg at 50% 50%,\n rgb(212 184 122 / 52%) 0deg,\n rgb(120 200 180 / 26%) 90deg,\n rgb(212 184 122 / 46%) 200deg,\n rgb(120 200 180 / 16%) 300deg,\n rgb(212 184 122 / 52%) 360deg\n );\n /* Chamfered HUD silhouette. */\n --cw-panel-clip: polygon(\n 12px 0,\n calc(100% - 12px) 0,\n 100% 12px,\n 100% calc(100% - 12px),\n calc(100% - 12px) 100%,\n 12px 100%,\n 0 calc(100% - 12px),\n 0 12px\n );\n --cw-panel-grain: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/%3E%3C/svg%3E\");\n\n --cw-radius-sm: 4px;\n --cw-radius-md: 8px;\n --cw-radius-lg: 16px;\n --cw-radius-pill: 999px;\n\n --cw-blur: 12px;\n --cw-blur-sm: 4px;\n --cw-shadow-panel:\n 0 8px 28px rgb(0 0 0 / 18%), 0 0 1px rgb(212 184 122 / 30%),\n inset 0 1px 0 rgb(255 248 230 / 14%), inset 0 -1px 0 rgb(0 0 0 / 12%);\n --cw-shadow-dialog: 0 12px 36px rgb(0 0 0 / 45%);\n --cw-shadow-tag: 0 2px 12px rgb(0 0 0 / 25%);\n --cw-text-shadow: 0 1px 6px rgb(0 0 0 / 80%);\n\n --cw-z-bubble: 4;\n --cw-z-panel: 5;\n --cw-z-detail: 6;\n --cw-z-helper: 7;\n --cw-z-error: 2147483000;\n}\n\n/* ── Primitives ──────────────────────────────────────────────────────────── */\n\n/*\n * '.cw-overlay-root' must stay layout-neutral: it is also applied to drei\n * 'Html' wrappers, which drei positions with inline styles. A width/height here\n * would stretch that wrapper to the canvas size and throw its\n * 'translate(-50%, -50%)' anchoring half a viewport off.\n */\n.cw-root,\n.cw-overlay-root {\n font-family: var(--cw-font-sans);\n color: var(--cw-color-text);\n}\n\n.cw-root {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.cw-surface {\n background: var(--cw-color-surface);\n border: 1px solid var(--cw-color-border);\n border-radius: var(--cw-radius-md);\n box-shadow: var(--cw-shadow-panel);\n backdrop-filter: blur(var(--cw-blur));\n -webkit-backdrop-filter: blur(var(--cw-blur));\n}\n\n.cw-key {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 1.75rem;\n height: 1.75rem;\n padding: 0 0.375rem;\n font-family: var(--cw-font-mono);\n font-size: 0.6875rem;\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n color: var(--cw-color-key-text);\n background: rgb(28 26 22 / 32%);\n border: 1px solid rgb(212 184 122 / 32%);\n border-radius: var(--cw-radius-sm);\n box-shadow:\n 0 1px 0 rgb(0 0 0 / 30%),\n inset 0 1px 0 rgb(255 248 230 / 12%);\n backdrop-filter: blur(var(--cw-blur-sm));\n -webkit-backdrop-filter: blur(var(--cw-blur-sm));\n}\n\n.cw-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n min-height: 2.5rem;\n padding: 0 1rem;\n font: inherit;\n font-size: 0.8125rem;\n font-weight: 500;\n color: rgb(255 255 255 / 80%);\n cursor: pointer;\n background: none;\n border: 1px solid rgb(255 255 255 / 25%);\n border-radius: var(--cw-radius-pill);\n transition:\n background-color 150ms ease,\n border-color 150ms ease,\n transform 100ms ease;\n}\n\n.cw-button:hover:not(:disabled) {\n border-color: rgb(255 255 255 / 45%);\n}\n\n.cw-button:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.cw-button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.cw-button--primary {\n font-weight: 500;\n color: #2a1c10;\n background: var(--cw-color-accent-warm);\n border-color: transparent;\n}\n\n.cw-button--primary:hover:not(:disabled) {\n background: color-mix(in srgb, var(--cw-color-accent-warm) 88%, white);\n border-color: transparent;\n}\n\n.cw-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n color: rgb(255 255 255 / 70%);\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: var(--cw-radius-sm);\n}\n\n.cw-icon-button:hover {\n color: var(--cw-color-text-bright);\n background: rgb(255 255 255 / 8%);\n}\n\n.cw-spinner {\n display: inline-block;\n flex-shrink: 0;\n width: 0.875rem;\n height: 0.875rem;\n border: 2px solid rgb(255 255 255 / 25%);\n border-top-color: rgb(255 255 255 / 90%);\n border-radius: 50%;\n animation: cw-spin 0.8s linear infinite;\n}\n\n@keyframes cw-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@keyframes cw-fade-in {\n from {\n opacity: 0;\n }\n}\n\n@keyframes cw-rise-in {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .cw-spinner {\n animation-duration: 2s;\n }\n\n .cw-panel,\n .cw-panel__row {\n animation: none;\n }\n}\n\n/* ── Action bubble (3D anchored single hint) ──────────────────────────────── */\n\n.cw-bubble-layer {\n display: flex;\n gap: 6px;\n white-space: nowrap;\n pointer-events: none;\n}\n\n.cw-bubble {\n padding: 2px 5px;\n font-size: 12px;\n color: #fff;\n background: var(--cw-color-bubble-surface);\n border: 1px solid var(--cw-color-bubble-border);\n border-radius: 5px;\n box-shadow: 0 4px 10px rgb(0 0 0 / 50%);\n}\n\n.cw-bubble__key {\n margin-right: 0.3em;\n font-weight: 600;\n color: var(--cw-color-shortcut);\n}\n\n/* ── Action panel (screen-space destination picker) ───────────────────────── */\n\n.cw-panel-layer {\n position: absolute;\n inset: 0;\n z-index: var(--cw-z-panel);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n pointer-events: none;\n}\n\n@media (min-width: 640px) {\n .cw-panel-layer {\n padding: 2rem;\n }\n}\n\n.cw-panel {\n position: relative;\n width: 100%;\n max-width: 17rem;\n pointer-events: auto;\n animation: cw-fade-in 200ms ease-out backwards;\n}\n\n/* Iridescent rim, revealed by the 1px inset of the chamfered frame above it. */\n.cw-panel__rim {\n position: absolute;\n inset: -1px;\n background: var(--cw-panel-rim);\n clip-path: var(--cw-panel-clip);\n opacity: 0.7;\n}\n\n.cw-panel__frame {\n position: relative;\n overflow: hidden;\n clip-path: var(--cw-panel-clip);\n backdrop-filter: blur(var(--cw-blur));\n -webkit-backdrop-filter: blur(var(--cw-blur));\n}\n\n.cw-panel__body {\n position: relative;\n padding: 1rem 1rem 0.875rem;\n background: var(--cw-panel-fill);\n border: 1px solid var(--cw-color-border);\n box-shadow: var(--cw-shadow-panel);\n}\n\n.cw-panel__grain {\n position: absolute;\n inset: 0;\n background-image: var(--cw-panel-grain);\n background-size: 160px 160px;\n opacity: 0.03;\n mix-blend-mode: overlay;\n pointer-events: none;\n}\n\n.cw-panel__hairline {\n position: absolute;\n inset-inline: 0;\n top: 0;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n rgb(120 200 180 / 28%) 18%,\n rgb(245 220 160 / 70%) 50%,\n rgb(120 200 180 / 28%) 82%,\n transparent 100%\n );\n pointer-events: none;\n}\n\n/* Crosshair registration marks in each corner. */\n.cw-panel__mark {\n position: absolute;\n width: 10px;\n height: 10px;\n pointer-events: none;\n}\n\n.cw-panel__mark::before,\n.cw-panel__mark::after {\n position: absolute;\n background: rgb(212 184 122 / 70%);\n content: '';\n}\n\n.cw-panel__mark::before {\n inset-inline: 0;\n top: 50%;\n height: 1px;\n transform: translateY(-50%);\n}\n\n.cw-panel__mark::after {\n inset-block: 0;\n left: 50%;\n width: 1px;\n transform: translateX(-50%);\n}\n\n.cw-panel__mark--tl {\n top: 8px;\n left: 8px;\n}\n\n.cw-panel__mark--tr {\n top: 8px;\n right: 8px;\n}\n\n.cw-panel__mark--bl {\n bottom: 8px;\n left: 8px;\n}\n\n.cw-panel__mark--br {\n right: 8px;\n bottom: 8px;\n}\n\n.cw-panel__header {\n position: relative;\n margin-bottom: 0.75rem;\n padding-left: 0.125rem;\n}\n\n.cw-panel__eyebrow-row {\n display: flex;\n gap: 0.375rem;\n align-items: center;\n margin-bottom: 0.25rem;\n}\n\n.cw-panel__dot {\n width: 4px;\n height: 4px;\n background: var(--cw-color-accent-mint);\n border-radius: 50%;\n box-shadow: 0 0 5px rgb(120 200 176 / 50%);\n}\n\n.cw-panel__eyebrow {\n margin: 0;\n font-size: 0.5625rem;\n font-weight: 600;\n letter-spacing: 0.28em;\n text-transform: uppercase;\n color: var(--cw-color-accent-soft);\n text-shadow: 0 1px 4px rgb(0 0 0 / 80%);\n}\n\n.cw-panel__title {\n margin: 0;\n font-size: 1.0625rem;\n font-weight: 600;\n line-height: 1.2;\n letter-spacing: -0.01em;\n color: var(--cw-color-text);\n text-shadow: 0 1px 8px rgb(0 0 0 / 85%);\n}\n\n.cw-panel__divider {\n margin-top: 0.625rem;\n height: 1px;\n background: linear-gradient(\n 90deg,\n rgb(212 184 122 / 45%) 0%,\n rgb(120 200 180 / 22%) 45%,\n transparent 100%\n );\n}\n\n.cw-panel__list {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.cw-panel__row {\n animation: cw-rise-in 200ms ease-out backwards;\n}\n\n.cw-panel__item {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.625rem;\n width: 100%;\n padding: 0.5rem 0.625rem;\n overflow: hidden;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: rgb(255 255 255 / 2%);\n border: 1px solid rgb(212 184 122 / 16%);\n border-radius: var(--cw-radius-sm);\n box-shadow: inset 0 1px 0 rgb(255 248 230 / 6%);\n transition:\n background-color 200ms ease,\n border-color 200ms ease;\n}\n\n.cw-panel__item:hover:not(:disabled),\n.cw-panel__item:focus-visible:not(:disabled) {\n background: rgb(120 200 176 / 10%);\n border-color: var(--cw-color-border-hover);\n outline: none;\n}\n\n.cw-panel__item:disabled {\n cursor: not-allowed;\n background: rgb(255 255 255 / 1%);\n border-color: rgb(212 184 122 / 10%);\n opacity: 0.55;\n}\n\n/* Accent bar that wipes in on hover. */\n.cw-panel__item-bar {\n position: absolute;\n inset-block: 0.25rem;\n left: 0;\n width: 2px;\n background: linear-gradient(180deg, var(--cw-color-accent-mint) 0%, var(--cw-color-accent) 100%);\n opacity: 0;\n transition: opacity 200ms ease;\n pointer-events: none;\n}\n\n.cw-panel__item:hover:not(:disabled) .cw-panel__item-bar,\n.cw-panel__item:focus-visible:not(:disabled) .cw-panel__item-bar {\n opacity: 1;\n}\n\n.cw-panel__item:hover:not(:disabled) .cw-key,\n.cw-panel__item:focus-visible:not(:disabled) .cw-key {\n border-color: rgb(120 200 176 / 50%);\n}\n\n.cw-panel__item-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n color: rgb(212 184 122 / 65%);\n background: rgb(255 255 255 / 3%);\n border: 1px solid rgb(212 184 122 / 22%);\n border-radius: var(--cw-radius-sm);\n transition:\n color 200ms ease,\n border-color 200ms ease;\n}\n\n.cw-panel__item:hover:not(:disabled) .cw-panel__item-icon {\n color: var(--cw-color-accent-mint);\n border-color: rgb(120 200 176 / 45%);\n}\n\n.cw-panel__item-text {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.cw-panel__item-label {\n display: block;\n overflow: hidden;\n font-size: 0.8125rem;\n font-weight: 600;\n line-height: 1.35;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-shadow: var(--cw-text-shadow);\n transition: color 200ms ease;\n}\n\n.cw-panel__item:hover:not(:disabled) .cw-panel__item-label {\n color: var(--cw-color-text-bright);\n}\n\n.cw-panel__item-hint {\n display: block;\n margin-top: 0.125rem;\n font-size: 0.5625rem;\n font-weight: 500;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: rgb(212 184 122 / 55%);\n text-shadow: 0 1px 4px rgb(0 0 0 / 70%);\n transition: color 200ms ease;\n}\n\n.cw-panel__item:hover:not(:disabled) .cw-panel__item-hint {\n color: rgb(120 200 176 / 80%);\n}\n\n.cw-panel__item-chevron {\n display: inline-flex;\n flex-shrink: 0;\n color: rgb(212 184 122 / 45%);\n filter: drop-shadow(0 1px 3px rgb(0 0 0 / 60%));\n transition:\n color 200ms ease,\n transform 200ms ease;\n}\n\n.cw-panel__item:hover:not(:disabled) .cw-panel__item-chevron {\n color: var(--cw-color-accent-mint);\n transform: translateX(2px);\n}\n\n.cw-panel__footer {\n position: relative;\n display: flex;\n gap: 0.5rem;\n align-items: center;\n margin-top: 0.625rem;\n}\n\n.cw-panel__footer-rule {\n flex: 1 1 auto;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgb(212 184 122 / 30%));\n}\n\n.cw-panel__footer-rule--end {\n background: linear-gradient(90deg, rgb(120 200 180 / 25%), transparent);\n}\n\n.cw-panel__footer-text {\n margin: 0;\n font-size: 0.5625rem;\n font-weight: 500;\n letter-spacing: 0.16em;\n text-transform: uppercase;\n color: var(--cw-color-text-muted);\n text-shadow: 0 1px 4px rgb(0 0 0 / 75%);\n}\n\n/* ── Detail window ───────────────────────────────────────────────────────── */\n\n.cw-detail {\n position: absolute;\n inset: 0 30% 0 0;\n z-index: var(--cw-z-detail);\n display: flex;\n flex-direction: column;\n background: var(--cw-color-scrim);\n}\n\n.cw-detail__header {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n justify-content: space-between;\n padding: 1.25rem 1.25rem 0;\n font-size: 1rem;\n color: #fff;\n}\n\n.cw-detail__body {\n flex: 1 1 auto;\n padding: 0.75rem 1.25rem;\n overflow: hidden;\n}\n\n.cw-detail__grid {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: 0.5rem;\n width: 100%;\n height: 100%;\n padding: 0.75rem;\n background: var(--cw-color-scrim);\n border-radius: var(--cw-radius-md);\n}\n\n.cw-detail__cell {\n position: relative;\n overflow: hidden;\n color: #fff;\n border: 1px dashed rgb(255 255 255 / 85%);\n border-radius: var(--cw-radius-sm);\n}\n\n.cw-detail__cell img,\n.cw-detail__cell video,\n.cw-detail__cell iframe {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n object-fit: cover;\n}\n\n.cw-detail__text {\n padding: 0.25rem 0.75rem;\n white-space: pre-wrap;\n}\n\n.cw-detail__counter {\n align-self: center;\n margin-bottom: 0.75rem;\n padding: 0.375rem 1.5rem;\n font-size: 0.75rem;\n color: #fff;\n background: var(--cw-color-scrim);\n border-radius: var(--cw-radius-pill);\n}\n\n.cw-detail__thumbs {\n display: flex;\n gap: 0.75rem;\n margin: 0 1.25rem;\n padding-bottom: 0.5rem;\n overflow-x: auto;\n}\n\n.cw-detail__thumb {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n gap: 0.5rem;\n flex: 0 0 auto;\n width: 13.5rem;\n height: 7.625rem;\n padding: 0.75rem;\n cursor: pointer;\n background: rgb(0 0 0 / 30%);\n border: 1px solid transparent;\n border-radius: var(--cw-radius-md);\n}\n\n.cw-detail__thumb:hover,\n.cw-detail__thumb[aria-current='true'] {\n background: var(--cw-color-scrim);\n border-color: rgb(255 255 255 / 85%);\n}\n\n.cw-detail__thumb-cell {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.75rem;\n color: rgb(255 255 255 / 50%);\n border: 1px dashed rgb(255 255 255 / 85%);\n border-radius: var(--cw-radius-sm);\n}\n\n/* ── Explore helper (onboarding hints) ───────────────────────────────────── */\n\n.cw-helper {\n position: absolute;\n inset: 0;\n z-index: var(--cw-z-helper);\n background: rgb(0 0 0 / 22%);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n}\n\n.cw-helper__card {\n position: absolute;\n right: 0;\n bottom: 9rem;\n left: 0;\n display: flex;\n justify-content: center;\n}\n\n.cw-helper__inner {\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n max-width: 80%;\n padding: 1.25rem;\n}\n\n.cw-helper__hints {\n display: flex;\n flex-wrap: wrap;\n gap: 1.5rem;\n justify-content: center;\n}\n\n.cw-helper__hint {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n align-items: center;\n}\n\n.cw-helper__hint-desc {\n font-size: 0.75rem;\n color: rgb(245 239 230 / 62%);\n}\n\n.cw-helper__actions {\n display: flex;\n justify-content: flex-end;\n}\n\n/* ── Load-error overlay ──────────────────────────────────────────────────── */\n\n.cw-error-layer {\n position: fixed;\n inset: 0;\n z-index: var(--cw-z-error);\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgb(0 0 0 / 70%);\n backdrop-filter: blur(var(--cw-blur-sm));\n -webkit-backdrop-filter: blur(var(--cw-blur-sm));\n}\n\n.cw-error {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n align-items: center;\n max-width: 20rem;\n margin: 0 1.5rem;\n padding: 1.75rem 1.5rem;\n text-align: center;\n background: var(--cw-color-surface-solid);\n border-radius: var(--cw-radius-lg);\n box-shadow: var(--cw-shadow-dialog);\n}\n\n.cw-error__badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 3rem;\n height: 3rem;\n font-size: 1.5rem;\n color: var(--cw-color-accent-warm);\n border: 2px solid var(--cw-color-accent-warm);\n border-radius: 50%;\n}\n\n.cw-error__title {\n margin: 0;\n font-size: 1rem;\n font-weight: 500;\n color: #fff;\n}\n\n.cw-error__message {\n margin: 0.25rem 0 0;\n font-size: 0.75rem;\n line-height: 1.25rem;\n color: rgb(255 255 255 / 60%);\n}\n\n.cw-error__actions {\n display: flex;\n flex-direction: column;\n gap: 0.625rem;\n width: 100%;\n}\n\n.cw-error__actions .cw-button {\n width: 100%;\n}\n\n/* ── Connector label (3D wayfinding tag) ─────────────────────────────────── */\n\n.cw-label {\n transition: opacity 150ms ease-out;\n pointer-events: none;\n}\n\n.cw-label__hit {\n pointer-events: auto;\n touch-action: manipulation;\n}\n\n.cw-label__tag {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.75rem;\n font-size: 0.75rem;\n color: #fff;\n white-space: nowrap;\n background: var(--cw-color-label-surface);\n border: 1px solid var(--cw-color-label-border);\n border-radius: var(--cw-radius-pill);\n box-shadow: var(--cw-shadow-tag);\n backdrop-filter: blur(var(--cw-blur-sm));\n -webkit-backdrop-filter: blur(var(--cw-blur-sm));\n}\n\n.cw-label__tag--compact {\n justify-content: center;\n width: 2rem;\n height: 2rem;\n padding: 0;\n border-radius: 50%;\n}\n\n.cw-label__tag--interactive {\n cursor: pointer;\n}\n\n.cw-label__tag--pending {\n cursor: not-allowed;\n opacity: 0.55;\n filter: saturate(0.5);\n}\n\n.cw-label__text {\n max-width: 10rem;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ── Utilities ───────────────────────────────────────────────────────────── */\n\n/*\n * Integrity probe. 'verifyCaveWorldStyles()' measures an offscreen element with\n * this class to tell whether this stylesheet is actually in effect: a host reset\n * that outranks single-class selectors (see the troubleshooting note in the\n * README) silently strips padding and borders from every overlay. Keep the two\n * values in sync with 'inject.ts'.\n */\n.cw-style-probe {\n position: absolute;\n top: -9999px;\n left: -9999px;\n padding-top: 7px;\n border-top: 3px solid transparent;\n}\n\n.cw-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n}\n`\n"],"names":["CAVE_WORLD_CSS"],"mappings":"AAQO,MAAMA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Inject the SDK stylesheet into `<head>` exactly once per document.
3
+ *
4
+ * Idempotent by element id, so mounting several viewers (or remounting one)
5
+ * never duplicates the rules. Safe to call during SSR — it no-ops without a
6
+ * `document`.
7
+ */
8
+ export declare function ensureCaveWorldStyles(): void;
9
+ /**
10
+ * Warn once per page if the default overlay styles are not actually in effect.
11
+ *
12
+ * Two host setups produce a silently half-styled UI, and neither raises an
13
+ * error on its own: the stylesheet never being loaded (`injectStyles={false}`
14
+ * without the matching `styles.css` import), or host CSS outranking it. The
15
+ * latter is the nastier one — a reset flattened to beat single-class selectors
16
+ * (e.g. Tailwind Preflight run through `@csstools/postcss-cascade-layers`, which
17
+ * rewrites `*` to `*:not(#\\#):not(#\\#)`) wins over every `.cw-*` rule and
18
+ * strips the overlays' padding, borders and button styling.
19
+ *
20
+ * Measures one offscreen element in idle time, so it costs a single style
21
+ * recalculation outside the mount path.
22
+ */
23
+ export declare function verifyCaveWorldStyles(): void;
24
+ /**
25
+ * Ensure the default overlay styles are present and effective.
26
+ *
27
+ * @param enabled pass `false` when importing
28
+ * `@cavegiant/cave-world-r3f/styles.css` yourself (or shipping a full replacement),
29
+ * so the SDK does not inject a second copy.
30
+ */
31
+ export declare function useCaveWorldStyles(enabled?: boolean): void;
32
+ //# sourceMappingURL=inject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inject.d.ts","sourceRoot":"","sources":["../../../explore/styles/inject.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAS5C;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CA0B5C;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,UAAO,GAAG,IAAI,CAKvD"}
@@ -0,0 +1,40 @@
1
+ import { useEffect as l } from "react";
2
+ import { createLogger as d } from "../../core/logging/logger.js";
3
+ import { scheduleIdle as i } from "../utils/schedule-idle.js";
4
+ import { CAVE_WORLD_CSS as a } from "./cave-world-css.js";
5
+ const t = "cave-world-styles", c = "7px", u = "3px", n = d("styles");
6
+ function f() {
7
+ if (typeof document > "u" || document.getElementById(t)) return;
8
+ const e = document.createElement("style");
9
+ e.id = t, e.textContent = a, document.head.prepend(e);
10
+ }
11
+ let s = !1;
12
+ function p() {
13
+ if (s || typeof document > "u" || !document.body) return;
14
+ s = !0;
15
+ const e = document.createElement("div");
16
+ e.className = "cw-style-probe", document.body.append(e);
17
+ const { paddingTop: o, borderTopWidth: r } = getComputedStyle(e);
18
+ if (e.remove(), !(o === c && r === u)) {
19
+ if (!document.getElementById(t)) {
20
+ n.warn(
21
+ "Default overlay styles are missing. Either drop `injectStyles={false}` or import '@cavegiant/cave-world-r3f/styles.css'."
22
+ );
23
+ return;
24
+ }
25
+ n.warn(
26
+ `Default overlay styles are loaded but overridden by host CSS (.cw-style-probe resolved to padding-top ${o}, border-top-width ${r}).`,
27
+ "A reset that outranks single-class selectors — typically Tailwind Preflight with its cascade layers flattened into `:not(#\\#)` specificity hacks — will strip padding, borders and button styling from the overlays.",
28
+ "Remove the flattening, or import the stylesheet through your own CSS pipeline and pass `injectStyles={false}`."
29
+ );
30
+ }
31
+ }
32
+ function v(e = !0) {
33
+ l(() => (e && f(), i(p)), [e]);
34
+ }
35
+ export {
36
+ f as ensureCaveWorldStyles,
37
+ v as useCaveWorldStyles,
38
+ p as verifyCaveWorldStyles
39
+ };
40
+ //# sourceMappingURL=inject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inject.js","sources":["../../../explore/styles/inject.ts"],"sourcesContent":["import { useEffect } from 'react'\nimport { createLogger } from '../../core'\nimport { scheduleIdle } from '../utils/schedule-idle'\nimport { CAVE_WORLD_CSS } from './cave-world-css'\n\nconst STYLE_ELEMENT_ID = 'cave-world-styles'\n\n/** Expected computed values of `.cw-style-probe`; see the rule in the CSS. */\nconst PROBE_PADDING_TOP = '7px'\nconst PROBE_BORDER_TOP_WIDTH = '3px'\n\nconst logger = createLogger('styles')\n\n/**\n * Inject the SDK stylesheet into `<head>` exactly once per document.\n *\n * Idempotent by element id, so mounting several viewers (or remounting one)\n * never duplicates the rules. Safe to call during SSR — it no-ops without a\n * `document`.\n */\nexport function ensureCaveWorldStyles(): void {\n if (typeof document === 'undefined') return\n if (document.getElementById(STYLE_ELEMENT_ID)) return\n\n const style = document.createElement('style')\n style.id = STYLE_ELEMENT_ID\n style.textContent = CAVE_WORLD_CSS\n // Prepend so host stylesheets loaded later win on equal specificity.\n document.head.prepend(style)\n}\n\nlet verified = false\n\n/**\n * Warn once per page if the default overlay styles are not actually in effect.\n *\n * Two host setups produce a silently half-styled UI, and neither raises an\n * error on its own: the stylesheet never being loaded (`injectStyles={false}`\n * without the matching `styles.css` import), or host CSS outranking it. The\n * latter is the nastier one — a reset flattened to beat single-class selectors\n * (e.g. Tailwind Preflight run through `@csstools/postcss-cascade-layers`, which\n * rewrites `*` to `*:not(#\\\\#):not(#\\\\#)`) wins over every `.cw-*` rule and\n * strips the overlays' padding, borders and button styling.\n *\n * Measures one offscreen element in idle time, so it costs a single style\n * recalculation outside the mount path.\n */\nexport function verifyCaveWorldStyles(): void {\n if (verified) return\n if (typeof document === 'undefined' || !document.body) return\n verified = true\n\n const probe = document.createElement('div')\n probe.className = 'cw-style-probe'\n document.body.append(probe)\n const { paddingTop, borderTopWidth } = getComputedStyle(probe)\n probe.remove()\n\n if (paddingTop === PROBE_PADDING_TOP && borderTopWidth === PROBE_BORDER_TOP_WIDTH) return\n\n if (!document.getElementById(STYLE_ELEMENT_ID)) {\n logger.warn(\n 'Default overlay styles are missing. Either drop `injectStyles={false}` or import' +\n \" '@cavegiant/cave-world-r3f/styles.css'.\"\n )\n return\n }\n\n logger.warn(\n `Default overlay styles are loaded but overridden by host CSS (.cw-style-probe resolved to padding-top ${paddingTop}, border-top-width ${borderTopWidth}).`,\n 'A reset that outranks single-class selectors — typically Tailwind Preflight with its cascade layers flattened into `:not(#\\\\#)` specificity hacks — will strip padding, borders and button styling from the overlays.',\n 'Remove the flattening, or import the stylesheet through your own CSS pipeline and pass `injectStyles={false}`.'\n )\n}\n\n/**\n * Ensure the default overlay styles are present and effective.\n *\n * @param enabled pass `false` when importing\n * `@cavegiant/cave-world-r3f/styles.css` yourself (or shipping a full replacement),\n * so the SDK does not inject a second copy.\n */\nexport function useCaveWorldStyles(enabled = true): void {\n useEffect(() => {\n if (enabled) ensureCaveWorldStyles()\n return scheduleIdle(verifyCaveWorldStyles)\n }, [enabled])\n}\n"],"names":["STYLE_ELEMENT_ID","PROBE_PADDING_TOP","PROBE_BORDER_TOP_WIDTH","logger","createLogger","ensureCaveWorldStyles","style","CAVE_WORLD_CSS","verified","verifyCaveWorldStyles","probe","paddingTop","borderTopWidth","useCaveWorldStyles","enabled","useEffect","scheduleIdle"],"mappings":";;;;AAKA,MAAMA,IAAmB,qBAGnBC,IAAoB,OACpBC,IAAyB,OAEzBC,IAASC,EAAa,QAAQ;AAS7B,SAASC,IAA8B;AAE5C,MADI,OAAO,WAAa,OACpB,SAAS,eAAeL,CAAgB,EAAG;AAE/C,QAAMM,IAAQ,SAAS,cAAc,OAAO;AAC5C,EAAAA,EAAM,KAAKN,GACXM,EAAM,cAAcC,GAEpB,SAAS,KAAK,QAAQD,CAAK;AAC7B;AAEA,IAAIE,IAAW;AAgBR,SAASC,IAA8B;AAE5C,MADID,KACA,OAAO,WAAa,OAAe,CAAC,SAAS,KAAM;AACvD,EAAAA,IAAW;AAEX,QAAME,IAAQ,SAAS,cAAc,KAAK;AAC1C,EAAAA,EAAM,YAAY,kBAClB,SAAS,KAAK,OAAOA,CAAK;AAC1B,QAAM,EAAE,YAAAC,GAAY,gBAAAC,MAAmB,iBAAiBF,CAAK;AAG7D,MAFAA,EAAM,OAAA,GAEF,EAAAC,MAAeV,KAAqBW,MAAmBV,IAE3D;AAAA,QAAI,CAAC,SAAS,eAAeF,CAAgB,GAAG;AAC9C,MAAAG,EAAO;AAAA,QACL;AAAA,MAAA;AAGF;AAAA,IACF;AAEA,IAAAA,EAAO;AAAA,MACL,yGAAyGQ,CAAU,sBAAsBC,CAAc;AAAA,MACvJ;AAAA,MACA;AAAA,IAAA;AAAA;AAEJ;AASO,SAASC,EAAmBC,IAAU,IAAY;AACvD,EAAAC,EAAU,OACJD,KAAST,EAAA,GACNW,EAAaP,CAAqB,IACxC,CAACK,CAAO,CAAC;AACd;"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Run low-priority work in browser idle time, falling back to a macrotask
3
+ * where `requestIdleCallback` is unavailable (Safari < 17).
4
+ *
5
+ * Used to push the heavy parts of a neighbor-scene preload (subtree mount,
6
+ * splat decode/upload, OBJ collider parse) off the critical frame so they don't
7
+ * burst against player input the moment the primary scene becomes ready.
8
+ *
9
+ * @returns a cancel function; safe to call after the task has already run.
10
+ */
11
+ export declare function scheduleIdle(task: () => void, timeoutMs?: number): () => void;
12
+ //# sourceMappingURL=schedule-idle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-idle.d.ts","sourceRoot":"","sources":["../../../explore/utils/schedule-idle.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,SAAS,SAAO,GAAG,MAAM,IAAI,CAc3E"}
@@ -0,0 +1,16 @@
1
+ function d(e, l = 1e3) {
2
+ if (typeof window > "u")
3
+ return e(), () => {
4
+ };
5
+ const n = window;
6
+ if (typeof n.requestIdleCallback == "function") {
7
+ const t = n.requestIdleCallback(e, { timeout: l });
8
+ return () => n.cancelIdleCallback?.(t);
9
+ }
10
+ const o = window.setTimeout(e, 1);
11
+ return () => window.clearTimeout(o);
12
+ }
13
+ export {
14
+ d as scheduleIdle
15
+ };
16
+ //# sourceMappingURL=schedule-idle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-idle.js","sources":["../../../explore/utils/schedule-idle.ts"],"sourcesContent":["interface IdleCapableWindow {\n requestIdleCallback?: (callback: () => void, options?: { timeout?: number }) => number\n cancelIdleCallback?: (handle: number) => void\n}\n\n/**\n * Run low-priority work in browser idle time, falling back to a macrotask\n * where `requestIdleCallback` is unavailable (Safari < 17).\n *\n * Used to push the heavy parts of a neighbor-scene preload (subtree mount,\n * splat decode/upload, OBJ collider parse) off the critical frame so they don't\n * burst against player input the moment the primary scene becomes ready.\n *\n * @returns a cancel function; safe to call after the task has already run.\n */\nexport function scheduleIdle(task: () => void, timeoutMs = 1000): () => void {\n if (typeof window === 'undefined') {\n task()\n return () => {}\n }\n\n const idleWindow = window as unknown as IdleCapableWindow\n if (typeof idleWindow.requestIdleCallback === 'function') {\n const handle = idleWindow.requestIdleCallback(task, { timeout: timeoutMs })\n return () => idleWindow.cancelIdleCallback?.(handle)\n }\n\n const handle = window.setTimeout(task, 1)\n return () => window.clearTimeout(handle)\n}\n"],"names":["scheduleIdle","task","timeoutMs","idleWindow","handle"],"mappings":"AAeO,SAASA,EAAaC,GAAkBC,IAAY,KAAkB;AAC3E,MAAI,OAAO,SAAW;AACpB,WAAAD,EAAA,GACO,MAAM;AAAA,IAAC;AAGhB,QAAME,IAAa;AACnB,MAAI,OAAOA,EAAW,uBAAwB,YAAY;AACxD,UAAMC,IAASD,EAAW,oBAAoBF,GAAM,EAAE,SAASC,GAAW;AAC1E,WAAO,MAAMC,EAAW,qBAAqBC,CAAM;AAAA,EACrD;AAEA,QAAMA,IAAS,OAAO,WAAWH,GAAM,CAAC;AACxC,SAAO,MAAM,OAAO,aAAaG,CAAM;AACzC;"}
@@ -0,0 +1,56 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { CaveEventBus, ComponentRegistry, ObjectRegistry, PartialCaveWorldMessages, SpaceLoadError } from '../core/index.js';
3
+ import type { CaveSpace } from '../types/index.js';
4
+ import type { CaveSpaceLoader } from './loaders/cave-loader.js';
5
+ import type { LoadErrorRenderer } from './overlays/space-load-error-overlay.js';
6
+ /**
7
+ * Props shared by every viewer (`CaveExplore`, `CaveOrbitViewer`).
8
+ *
9
+ * Kept in one place so the two entry points can't drift on loading, theming,
10
+ * extension, or error-handling behavior.
11
+ */
12
+ export interface CaveViewerBaseProps {
13
+ /** Scene id handed to `caveSpaceLoader`. */
14
+ spaceId?: string;
15
+ /** Custom scene-JSON loader. Defaults to the CaveGiant content API. */
16
+ caveSpaceLoader?: CaveSpaceLoader;
17
+ /** Fired when the primary scene's base layer is ready. */
18
+ onSpaceInitialized?: () => void;
19
+ /** Reuse a bus to observe SDK events from outside the React tree. */
20
+ eventBus?: CaveEventBus;
21
+ /** Pre-populated object renderers; yours override built-ins. */
22
+ objectRegistry?: ObjectRegistry;
23
+ /** Pre-populated behavior components; yours override built-ins. */
24
+ componentRegistry?: ComponentRegistry;
25
+ /** Partial copy overrides for the built-in overlays. */
26
+ messages?: PartialCaveWorldMessages;
27
+ /**
28
+ * Inject the default stylesheet at runtime. Set `false` if you import
29
+ * `@cavegiant/cave-world-r3f/styles.css` yourself or fully replace the overlays.
30
+ * @default true
31
+ */
32
+ injectStyles?: boolean;
33
+ /**
34
+ * Play the one-shot spread reveal when the primary scene's splat first loads.
35
+ * Preloaded neighbors and scene transitions never replay it.
36
+ * @default REVEAL_ON_ENTER_DEFAULT_ENABLED
37
+ */
38
+ revealOnEnter?: boolean;
39
+ /** Replace the built-in detail window. */
40
+ renderDetailWindow?: () => ReactNode;
41
+ /**
42
+ * Called once when a load terminally fails (config JSON or splat, after
43
+ * automatic retries). Use it to tear down host loading UI, which would
44
+ * otherwise keep covering the screen.
45
+ */
46
+ onLoadError?: (error: SpaceLoadError) => void;
47
+ /** Back-button handler for the load-error prompt; omitting it hides the button. */
48
+ onLoadErrorExit?: () => void;
49
+ /** Replace the built-in load-error prompt. */
50
+ renderLoadError?: LoadErrorRenderer;
51
+ /** Extra R3F content rendered inside the scene graph. */
52
+ children?: ReactNode;
53
+ }
54
+ /** Callback shape for active-scene tracking across cross-scene travel. */
55
+ export type ActiveSpaceChangeHandler = (spaceId: string, space?: CaveSpace) => void;
56
+ //# sourceMappingURL=viewer-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewer-shared.d.ts","sourceRoot":"","sources":["../../explore/viewer-shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,wBAAwB,EACxB,cAAc,EACf,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uEAAuE;IACvE,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAE/B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,gEAAgE;IAChE,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,wBAAwB,CAAA;IAEnC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,SAAS,CAAA;IAEpC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;IAC5B,8CAA8C;IAC9C,eAAe,CAAC,EAAE,iBAAiB,CAAA;IAEnC,yDAAyD;IACzD,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,0EAA0E;AAC1E,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `@cavegiant/cave-world-r3f` — web-based 3D virtual tour SDK.
3
+ *
4
+ * This root entry re-exports the APIs most integrations need. For narrower
5
+ * imports use the sub-paths:
6
+ *
7
+ * - `@cavegiant/cave-world-r3f/types` — scene JSON types only, zero runtime
8
+ * - `@cavegiant/cave-world-r3f/core` — event bus, registries, provider, hooks
9
+ * - `@cavegiant/cave-world-r3f/space` — scene rendering components (R3F)
10
+ * - `@cavegiant/cave-world-r3f/explore` — viewers, overlays, character, multiplayer
11
+ */
12
+ export type { AssetSourceFromType, AudioProps, BaseCollider, BaseLayer, BaseSceneRef, Block, BoundaryDef, BoxBoundaryDef, BoxCollider, CaveSpace, ColliderComponent, Color, ConnectorDef, ConnectorInfo, ConnectorLabelDef, ConnectorTarget, Content, CustomComponentMap, CustomLayer, CustomObject, CustomObjectType, DigitalHuman2DProps, GalleryInfoPointDetail, ImageProps, InfoPointDetail, InfoPointProps, LightProps, LightingSettings, Matrix16, ModelCollider, ModelProps, PanoramaVideoProps, PhysicsSettings, PolygonBoundaryDef, PortalProps, Quaternion, SpaceMetadata, SpawnPoint, SplatLevel, TextProps, Transform, Vector3, VideoProps, WindowComponent } from './types/index.js';
13
+ export { CaveEventBus, CaveWorldError, CaveWorldProvider, ComponentRegistry, DEFAULT_MESSAGES, FALLBACK_LABEL_TEXT, ObjectRegistry, createLogger, formatMessage, isCaveWorldError, messagesEn, messagesZhCN, resolveMessages, setCaveWorldLogLevel, setCaveWorldLogSink, useCaveEvent, useCaveEventBus, useCaveWorld, useCaveWorldMessages, useCaveWorldStore, useCaveWorldStoreApi, useComponentRegistry, useObjectRegistry, type CaveEventHandler, type CaveEventMap, type CaveEventName, type CaveWorldErrorCode, type CaveWorldLogLevel, type CaveWorldMessages, type CaveWorldProviderProps, type CaveWorldServices, type CaveWorldState, type ComponentRegistryEntry, type ConnectorLabelMode, type ConnectorLabelRenderer, type ConnectorLabelRendererProps, type ObjectComponent, type ObjectComponentProps, type ObjectRenderer, type ObjectRendererProps, type PartialCaveWorldMessages, type ResolvedConnectorLabel, type SpaceLoadError } from './core/index.js';
14
+ export { CaveSpace as CaveSpaceRenderer, getSparkCanvasDpr, isMobileDevice, isTouchPrimaryDevice, selectSplatLevel, useTouchPrimaryDevice, useVisibilityFrameloop, CAVE_WORLD_LOCAL_PLAYER_FLAG, type CaveSpaceProps } from './space/index.js';
15
+ export { ActionBubble, ActionPanel, CaveExplore, CaveOrbitViewer, ConnectorLabelBeacon, ConnectorLabelTagShell, DefaultCaveSpaceLoader, DetailWindow, MIXAMO_STYLE_BONE_MAP, SpaceLoadErrorOverlay, assertCaveSpace, createHttpCaveSpaceLoader, createLocalCharacterModelConfig, ensureCaveWorldStyles, useCaveExplore, useCaveExploreStore, type ActionDef, type CaveExploreHandle, type CaveExploreProps, type CaveOrbitViewerProps, type CaveSpaceLoader, type CharacterControlsConfig, type CharacterMovementOptions, type ExploreHelperConfig, type ExploreHelperRenderer, type HttpCaveSpaceLoaderOptions, type LoadErrorRenderProps, type LoadErrorRenderer, type LocalCharacterModelConfig, type LocalCharacterModelProp, type MultiplayerProp, type OrbitCameraConfig, type OrbitControlsConfig, type PortalNavigateHandler, type VRMHumanBoneName } from './explore/index.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,KAAK,EACL,WAAW,EACX,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,KAAK,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,OAAO,EACP,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,eAAe,EACf,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,OAAO,EACP,UAAU,EACV,eAAe,EAChB,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACpB,MAAM,QAAQ,CAAA;AAGf,OAAO,EACL,SAAS,IAAI,iBAAiB,EAC9B,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,4BAA4B,EAC5B,KAAK,cAAc,EACpB,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,YAAY,EACZ,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,yBAAyB,EACzB,+BAA+B,EAC/B,qBAAqB,EACrB,cAAc,EACd,mBAAmB,EACnB,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ import { CaveEventBus as o } from "./core/events/event-bus.js";
2
+ import { ObjectRegistry as t } from "./core/registry/object-registry.js";
3
+ import { ComponentRegistry as p } from "./core/registry/component-registry.js";
4
+ import { CaveWorldProvider as f, useCaveEventBus as m, useCaveWorld as v, useCaveWorldMessages as C, useCaveWorldStore as x, useCaveWorldStoreApi as u, useComponentRegistry as i, useObjectRegistry as d } from "./core/context/cave-world-context.js";
5
+ import { useCaveEvent as n } from "./core/hooks/use-cave-event.js";
6
+ import { createLogger as E, setCaveWorldLogLevel as S, setCaveWorldLogSink as g } from "./core/logging/logger.js";
7
+ import { CaveWorldError as W, isCaveWorldError as _ } from "./core/errors.js";
8
+ import { DEFAULT_MESSAGES as y, formatMessage as M, en as D, zhCN as O, resolveMessages as B } from "./core/i18n/messages.js";
9
+ import { FALLBACK_LABEL_TEXT as T } from "./core/connector-label/types.js";
10
+ import { default as P } from "./space/cave-space.js";
11
+ import { useVisibilityFrameloop as N } from "./space/utils/use-visibility-frameloop.js";
12
+ import { getSparkCanvasDpr as j } from "./space/utils/spark-performance.js";
13
+ import { isMobileDevice as w, selectSplatLevel as G } from "./space/utils/select-splat-level.js";
14
+ import { isTouchPrimaryDevice as Y, useTouchPrimaryDevice as z } from "./space/utils/touch-primary-device.js";
15
+ import { CAVE_WORLD_LOCAL_PLAYER_FLAG as I } from "./space/utils/cave-world-player.js";
16
+ import { default as U } from "./explore/cave-explore.js";
17
+ import { default as q } from "./explore/cave-orbit-viewer.js";
18
+ import { DefaultCaveSpaceLoader as Q, assertCaveSpace as $, createHttpCaveSpaceLoader as ee } from "./explore/loaders/cave-loader.js";
19
+ import { default as oe } from "./explore/overlays/detail-window.js";
20
+ import { default as te } from "./explore/overlays/action-panel.js";
21
+ import { default as pe } from "./explore/overlays/action-bubble.js";
22
+ import { default as fe } from "./explore/overlays/space-load-error-overlay.js";
23
+ import { default as ve } from "./explore/overlays/connector-label-beacon.js";
24
+ import { default as xe } from "./explore/overlays/connector-label-tag-shell.js";
25
+ import { ensureCaveWorldStyles as ie } from "./explore/styles/inject.js";
26
+ import { useCaveExplore as ce, useCaveExploreStore as ne } from "./explore/stores/explore-context.js";
27
+ import { createLocalCharacterModelConfig as Ee } from "./explore/characters/local-character-model.js";
28
+ import { MIXAMO_STYLE_BONE_MAP as ge } from "./explore/characters/mixamo-style-bone-map.js";
29
+ export {
30
+ pe as ActionBubble,
31
+ te as ActionPanel,
32
+ I as CAVE_WORLD_LOCAL_PLAYER_FLAG,
33
+ o as CaveEventBus,
34
+ U as CaveExplore,
35
+ q as CaveOrbitViewer,
36
+ P as CaveSpaceRenderer,
37
+ W as CaveWorldError,
38
+ f as CaveWorldProvider,
39
+ p as ComponentRegistry,
40
+ ve as ConnectorLabelBeacon,
41
+ xe as ConnectorLabelTagShell,
42
+ y as DEFAULT_MESSAGES,
43
+ Q as DefaultCaveSpaceLoader,
44
+ oe as DetailWindow,
45
+ T as FALLBACK_LABEL_TEXT,
46
+ ge as MIXAMO_STYLE_BONE_MAP,
47
+ t as ObjectRegistry,
48
+ fe as SpaceLoadErrorOverlay,
49
+ $ as assertCaveSpace,
50
+ ee as createHttpCaveSpaceLoader,
51
+ Ee as createLocalCharacterModelConfig,
52
+ E as createLogger,
53
+ ie as ensureCaveWorldStyles,
54
+ M as formatMessage,
55
+ j as getSparkCanvasDpr,
56
+ _ as isCaveWorldError,
57
+ w as isMobileDevice,
58
+ Y as isTouchPrimaryDevice,
59
+ D as messagesEn,
60
+ O as messagesZhCN,
61
+ B as resolveMessages,
62
+ G as selectSplatLevel,
63
+ S as setCaveWorldLogLevel,
64
+ g as setCaveWorldLogSink,
65
+ n as useCaveEvent,
66
+ m as useCaveEventBus,
67
+ ce as useCaveExplore,
68
+ ne as useCaveExploreStore,
69
+ v as useCaveWorld,
70
+ C as useCaveWorldMessages,
71
+ x as useCaveWorldStore,
72
+ u as useCaveWorldStoreApi,
73
+ i as useComponentRegistry,
74
+ d as useObjectRegistry,
75
+ z as useTouchPrimaryDevice,
76
+ N as useVisibilityFrameloop
77
+ };
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,42 @@
1
+ import { type ReactNode, type RefObject } from 'react';
2
+ import { type ThreeEvent } from '@react-three/fiber';
3
+ import { type Group, type Object3DEventMap } from 'three';
4
+ import type { CaveSpace } from '../types/index.js';
5
+ export interface CaveBaseLayerProps {
6
+ space?: CaveSpace;
7
+ /** Space id, threaded down for splat load-error context. */
8
+ spaceId?: string;
9
+ onProcess?: (percent: number) => void;
10
+ onInitialized?: () => void;
11
+ onClick?: (event: ThreeEvent<MouseEvent>) => void;
12
+ onDoubleClick?: (event: ThreeEvent<MouseEvent>) => void;
13
+ physics?: boolean;
14
+ /**
15
+ * When `false` this base layer is preloaded-but-not-current: connector
16
+ * sensors don't mount (no spurious `connector:enter` from an adjacent scene
17
+ * occupying the same world coordinates) and physics defaults off.
18
+ */
19
+ active?: boolean;
20
+ /** Connected space configs, for resolving portal label metadata. */
21
+ connectedSpaces?: Record<string, CaveSpace>;
22
+ /** Space ids whose base layer finished loading — gates portal travel UI. */
23
+ readySpaceIds?: Record<string, true>;
24
+ /** Connector the player is inside; its label hides. */
25
+ activeConnectorId?: string;
26
+ /** Mount connector label hosts. @default true */
27
+ connectorLabels?: boolean;
28
+ /**
29
+ * Play the spread reveal once when this base layer's splat first loads.
30
+ * Only the primary (entry) scene should set this; neighbors reached through
31
+ * a transition leave it `false` so travel feels instant.
32
+ */
33
+ revealOnEnter?: boolean;
34
+ children?: ReactNode;
35
+ ref?: RefObject<Group<Object3DEventMap>>;
36
+ }
37
+ /**
38
+ * The scene's ground truth: the 3DGS/splat or model capture, its colliders,
39
+ * boundaries, and connector trigger volumes.
40
+ */
41
+ export default function CaveBaseLayer(props: CaveBaseLayerProps): import("react").JSX.Element | null;
42
+ //# sourceMappingURL=cave-base-layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cave-base-layer.d.ts","sourceRoot":"","sources":["../../space/cave-base-layer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAG/D,OAAO,EAAqB,KAAK,KAAK,EAAE,KAAK,gBAAgB,EAAE,MAAM,OAAO,CAAA;AAG5E,OAAO,KAAK,EAAE,SAAS,EAA+B,MAAM,UAAU,CAAA;AA2GtE,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;IACvD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC3C,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACpC,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iDAAiD;IACjD,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,GAAG,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAA;CACzC;AAED;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,kBAAkB,sCA6O9D"}
@@ -0,0 +1,221 @@
1
+ import { jsxs as C, jsx as t } from "react/jsx-runtime";
2
+ import { useState as N, useMemo as x, useEffect as S, startTransition as j, useRef as m, useCallback as i, Suspense as w } from "react";
3
+ import { useLoader as F } from "@react-three/fiber";
4
+ import { BvhPhysicsBody as b, BvhPhysicsSensor as H } from "@react-three/viverse";
5
+ import { MeshBasicMaterial as J } from "three";
6
+ import { OBJLoader as V } from "three/examples/jsm/loaders/OBJLoader.js";
7
+ import { useCaveEventBus as W, useCaveWorldStore as K } from "../core/context/cave-world-context.js";
8
+ import X from "./connector-label-host.js";
9
+ import { PolygonBoundaryColliders as Y, PolygonBoundaryFence as Z } from "./polygon-boundary.js";
10
+ import ee from "./splats/spark/robust-splat-mesh.js";
11
+ import { toQuaternionRotation as A } from "./utils/rotation-compat.js";
12
+ import { selectSplatLevel as te } from "./utils/select-splat-level.js";
13
+ import { createSplatCollider as re } from "./utils/splat-collider-helper.js";
14
+ const G = [1, 0, 0, 0], oe = 1e5, ne = /* @__PURE__ */ new J({ visible: !1 });
15
+ function se({
16
+ connector: o,
17
+ onIntersection: r
18
+ }) {
19
+ const s = i(
20
+ (n) => r(o, n),
21
+ [o, r]
22
+ );
23
+ return /* @__PURE__ */ t(H, { onIntersectedChanged: s, children: /* @__PURE__ */ C(
24
+ "mesh",
25
+ {
26
+ position: o.transform.position,
27
+ rotation: o.transform.rotation,
28
+ scale: o.transform.scale,
29
+ children: [
30
+ /* @__PURE__ */ t("boxGeometry", {}),
31
+ /* @__PURE__ */ t("meshStandardMaterial", { visible: !1 })
32
+ ]
33
+ }
34
+ ) });
35
+ }
36
+ function le({
37
+ collider: o,
38
+ onLoaded: r
39
+ }) {
40
+ const s = F(V, o.url), n = x(() => {
41
+ const l = s.clone(!0);
42
+ return l.traverse((a) => {
43
+ a.isMesh && (a.material = ne);
44
+ }), l.rotation.set(-Math.PI / 2, 0, 0), l;
45
+ }, [s]);
46
+ return S(() => {
47
+ r();
48
+ }, [r]), /* @__PURE__ */ t("primitive", { object: n });
49
+ }
50
+ function ae(o, r) {
51
+ const s = m(!1), n = m(0), l = m(!1), [a, L] = N(!1), p = r ? o : 0, c = i(() => {
52
+ l.current || s.current && n.current >= p && (l.current = !0, L(!0));
53
+ }, [p]), v = i(() => {
54
+ s.current = !0, c();
55
+ }, [c]), I = i(() => {
56
+ n.current += 1, c();
57
+ }, [c]);
58
+ return { ready: a, markSceneReady: v, markColliderReady: I };
59
+ }
60
+ function Ie(o) {
61
+ const {
62
+ space: r,
63
+ spaceId: s,
64
+ active: n = !0,
65
+ revealOnEnter: l = !1,
66
+ onInitialized: a,
67
+ ref: L,
68
+ connectedSpaces: p = {},
69
+ readySpaceIds: c = {},
70
+ activeConnectorId: v,
71
+ connectorLabels: I = !0
72
+ } = o, u = o.physics ?? n, [d, O] = N(null), f = W(), E = K((e) => e.setSpaceLoadError), _ = x(
73
+ () => r?.baseLayer?.colliders?.filter((e) => e.type === "model").length ?? 0,
74
+ [r?.baseLayer?.colliders]
75
+ ), { ready: M, markSceneReady: R, markColliderReady: D } = ae(_, u);
76
+ S(() => {
77
+ M && j(() => {
78
+ f.emit("space:initialized", {}), a?.();
79
+ });
80
+ }, [M, f, a]), S(() => {
81
+ if (d)
82
+ return () => {
83
+ d.geometry.dispose();
84
+ };
85
+ }, [d]);
86
+ const k = m(() => {
87
+ }), B = m(!1);
88
+ S(() => {
89
+ k.current = (e) => {
90
+ j(() => {
91
+ !B.current && !r?.baseLayer?.colliders?.length && (B.current = !0, O(re(e, oe))), R();
92
+ });
93
+ };
94
+ }, [r?.baseLayer?.colliders, R]);
95
+ const U = i((e) => {
96
+ k.current(e);
97
+ }, []), h = x(
98
+ () => te(r?.baseLayer?.scene),
99
+ [r?.baseLayer?.scene]
100
+ )?.url, z = i(
101
+ (e) => {
102
+ E({ stage: "splat", url: h, spaceId: s, error: e });
103
+ },
104
+ [E, h, s]
105
+ ), Q = i(
106
+ (e, y) => {
107
+ f.emit(y ? "connector:enter" : "connector:leave", { connector: e });
108
+ },
109
+ [f]
110
+ );
111
+ if (!r?.baseLayer) return null;
112
+ const { transform: g, scene: $, colliders: P, boundaries: q, connectors: T } = r.baseLayer;
113
+ return /* @__PURE__ */ C(
114
+ "group",
115
+ {
116
+ name: "base-layer",
117
+ position: g.position,
118
+ quaternion: g.rotation,
119
+ scale: g.scale,
120
+ ref: L,
121
+ children: [
122
+ $?.type === "splat" && h ? /* @__PURE__ */ t(
123
+ ee,
124
+ {
125
+ url: h,
126
+ visible: n,
127
+ quaternion: G,
128
+ spaceId: s,
129
+ revealOnEnter: l,
130
+ onLoad: U,
131
+ onError: n ? z : void 0,
132
+ onClick: o.onClick,
133
+ onDoubleClick: o.onDoubleClick
134
+ }
135
+ ) : null,
136
+ P?.map((e) => {
137
+ if (e.type !== "model" || !e.url) return null;
138
+ const y = /* @__PURE__ */ t(le, { collider: e, onLoaded: D });
139
+ return (
140
+ // Each collider gets its own boundary. `useLoader` suspends, and
141
+ // without a boundary here the suspension unwinds to the viewer's,
142
+ // discarding this whole subtree — including the splat mesh, which
143
+ // spark re-downloads from scratch on every remount. Colliders also
144
+ // load in parallel this way instead of one per retry.
145
+ //
146
+ // The boundary must stay *outside* `BvhPhysicsBody`: it snapshots its
147
+ // children into the BVH world in a mount effect, so a child that
148
+ // arrives later is never registered as a collider.
149
+ /* @__PURE__ */ t(w, { fallback: null, children: u ? /* @__PURE__ */ t(b, { children: y }) : (
150
+ // Hidden preloads still load collider assets (to satisfy the init
151
+ // gate) but skip BVH registration.
152
+ /* @__PURE__ */ t("group", { visible: !1, children: y })
153
+ ) }, e.id)
154
+ );
155
+ }),
156
+ u ? /* @__PURE__ */ t(b, { children: P?.map(
157
+ (e) => e.type === "box" ? /* @__PURE__ */ C(
158
+ "mesh",
159
+ {
160
+ position: e.box.position,
161
+ quaternion: A(e.box.rotation),
162
+ scale: e.box.scale,
163
+ children: [
164
+ /* @__PURE__ */ t("boxGeometry", {}),
165
+ /* @__PURE__ */ t("meshStandardMaterial", { visible: !1 })
166
+ ]
167
+ },
168
+ e.id
169
+ ) : null
170
+ ) }) : null,
171
+ u ? /* @__PURE__ */ t(b, { children: q?.map((e) => e.type === "box" && e.collisionEnabled !== !1 ? /* @__PURE__ */ C(
172
+ "mesh",
173
+ {
174
+ position: e.box.position,
175
+ quaternion: A(e.box.rotation),
176
+ scale: e.box.scale,
177
+ children: [
178
+ /* @__PURE__ */ t("boxGeometry", {}),
179
+ /* @__PURE__ */ t("meshStandardMaterial", { visible: !1 })
180
+ ]
181
+ },
182
+ e.id
183
+ ) : e.type === "polygon" ? /* @__PURE__ */ t(Y, { boundary: e }, e.id) : null) }) : null,
184
+ n ? q?.map(
185
+ (e) => e.type === "polygon" ? /* @__PURE__ */ t(
186
+ Z,
187
+ {
188
+ boundary: e,
189
+ active: n
190
+ },
191
+ `polygon-vis-${e.id}`
192
+ ) : null
193
+ ) : null,
194
+ n ? T?.map((e) => /* @__PURE__ */ t(
195
+ se,
196
+ {
197
+ connector: e,
198
+ onIntersection: Q
199
+ },
200
+ e.id
201
+ )) : null,
202
+ n && I ? T?.map((e) => /* @__PURE__ */ t(
203
+ X,
204
+ {
205
+ connector: e,
206
+ connectedSpaces: p,
207
+ readySpaceIds: c,
208
+ activeConnectorId: v
209
+ },
210
+ `label-${e.id}`
211
+ )) : null,
212
+ u && d ? /* @__PURE__ */ t(b, { children: /* @__PURE__ */ t("group", { children: /* @__PURE__ */ t("primitive", { object: d, quaternion: G }) }) }) : null,
213
+ o.children ?? null
214
+ ]
215
+ }
216
+ );
217
+ }
218
+ export {
219
+ Ie as default
220
+ };
221
+ //# sourceMappingURL=cave-base-layer.js.map