@q9labsai/chalk-react-native 4.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 (654) hide show
  1. package/Q9ChalkReactNative.podspec +27 -0
  2. package/README.md +41 -0
  3. package/android/build.gradle +43 -0
  4. package/android/consumer-rules.pro +1 -0
  5. package/android/src/main/AndroidManifest.xml +24 -0
  6. package/android/src/main/java/ai/q9labs/chalk/reactnative/ChalkSpaceForegroundService.java +94 -0
  7. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkAndroidConnectionServiceModule.kt +161 -0
  8. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkAndroidConnectionServicePackage.kt +18 -0
  9. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkConnectionRegistry.kt +120 -0
  10. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkSelfManagedConnection.kt +64 -0
  11. package/android/src/main/kotlin/ai/q9labs/chalk/reactnative/ChalkSelfManagedConnectionService.kt +35 -0
  12. package/dist/android/connection-service.d.ts +26 -0
  13. package/dist/android/connection-service.d.ts.map +1 -0
  14. package/dist/android.d.ts +2 -0
  15. package/dist/android.d.ts.map +1 -0
  16. package/dist/android.js +47 -0
  17. package/dist/callkit/callkit.d.ts +61 -0
  18. package/dist/callkit/callkit.d.ts.map +1 -0
  19. package/dist/callkit/resolve-space-callkit-options.d.ts +17 -0
  20. package/dist/callkit/resolve-space-callkit-options.d.ts.map +1 -0
  21. package/dist/chunk-BXIZIHIO.js +4501 -0
  22. package/dist/chunk-F3NPRVHO.js +121 -0
  23. package/dist/chunk-HXYIJ75K.js +394 -0
  24. package/dist/chunk-IMKSYT7R.js +653 -0
  25. package/dist/chunk-JB4LNWVP.js +247 -0
  26. package/dist/client.d.ts +8 -0
  27. package/dist/client.d.ts.map +1 -0
  28. package/dist/client.js +6 -0
  29. package/dist/clipboard-store.d.ts +17 -0
  30. package/dist/clipboard-store.d.ts.map +1 -0
  31. package/dist/clipboard.d.ts +10 -0
  32. package/dist/clipboard.d.ts.map +1 -0
  33. package/dist/clipboard.js +108 -0
  34. package/dist/components/Chalk.d.ts +77 -0
  35. package/dist/components/Chalk.d.ts.map +1 -0
  36. package/dist/components/ChatMessageList.d.ts +11 -0
  37. package/dist/components/ChatMessageList.d.ts.map +1 -0
  38. package/dist/components/EmbeddedWhiteboard.d.ts +46 -0
  39. package/dist/components/EmbeddedWhiteboard.d.ts.map +1 -0
  40. package/dist/components/Entrance.d.ts +22 -0
  41. package/dist/components/Entrance.d.ts.map +1 -0
  42. package/dist/components/EntranceView.android.d.ts +4 -0
  43. package/dist/components/EntranceView.android.d.ts.map +1 -0
  44. package/dist/components/EntranceView.d.ts +18 -0
  45. package/dist/components/EntranceView.d.ts.map +1 -0
  46. package/dist/components/EntranceView.ios-pad.d.ts +3 -0
  47. package/dist/components/EntranceView.ios-pad.d.ts.map +1 -0
  48. package/dist/components/EntranceView.ios-phone.d.ts +3 -0
  49. package/dist/components/EntranceView.ios-phone.d.ts.map +1 -0
  50. package/dist/components/EntranceView.macos.d.ts +4 -0
  51. package/dist/components/EntranceView.macos.d.ts.map +1 -0
  52. package/dist/components/FaceAvatar.d.ts +16 -0
  53. package/dist/components/FaceAvatar.d.ts.map +1 -0
  54. package/dist/components/GradientSurface.d.ts +14 -0
  55. package/dist/components/GradientSurface.d.ts.map +1 -0
  56. package/dist/components/LogoElements.d.ts +6 -0
  57. package/dist/components/LogoElements.d.ts.map +1 -0
  58. package/dist/components/MediaView.d.ts +14 -0
  59. package/dist/components/MediaView.d.ts.map +1 -0
  60. package/dist/components/ReactionPicker.d.ts +10 -0
  61. package/dist/components/ReactionPicker.d.ts.map +1 -0
  62. package/dist/components/RtcVideoView.d.ts +4 -0
  63. package/dist/components/RtcVideoView.d.ts.map +1 -0
  64. package/dist/components/SpaceView.android.d.ts +2 -0
  65. package/dist/components/SpaceView.android.d.ts.map +1 -0
  66. package/dist/components/SpaceView.d.ts +31 -0
  67. package/dist/components/SpaceView.d.ts.map +1 -0
  68. package/dist/components/SpaceView.ios-pad.d.ts +2 -0
  69. package/dist/components/SpaceView.ios-pad.d.ts.map +1 -0
  70. package/dist/components/SpaceView.ios-phone.d.ts +2 -0
  71. package/dist/components/SpaceView.ios-phone.d.ts.map +1 -0
  72. package/dist/components/SpaceView.macos.d.ts +2 -0
  73. package/dist/components/SpaceView.macos.d.ts.map +1 -0
  74. package/dist/components/SpaceView.shared.d.ts +3 -0
  75. package/dist/components/SpaceView.shared.d.ts.map +1 -0
  76. package/dist/components/android-connection-service-controller.d.ts +33 -0
  77. package/dist/components/android-connection-service-controller.d.ts.map +1 -0
  78. package/dist/components/episode-diagnostic-render-observer.d.ts +2 -0
  79. package/dist/components/episode-diagnostic-render-observer.d.ts.map +1 -0
  80. package/dist/components/native-animation-controller.d.ts +7 -0
  81. package/dist/components/native-animation-controller.d.ts.map +1 -0
  82. package/dist/components/native-chat.d.ts +8 -0
  83. package/dist/components/native-chat.d.ts.map +1 -0
  84. package/dist/components/native-entrance/entrance-controller-store.d.ts +34 -0
  85. package/dist/components/native-entrance/entrance-controller-store.d.ts.map +1 -0
  86. package/dist/components/native-entrance/useEntranceController.d.ts +19 -0
  87. package/dist/components/native-entrance/useEntranceController.d.ts.map +1 -0
  88. package/dist/components/native-joining-loading-animation.d.ts +9 -0
  89. package/dist/components/native-joining-loading-animation.d.ts.map +1 -0
  90. package/dist/components/native-media-visibility.d.ts +8 -0
  91. package/dist/components/native-media-visibility.d.ts.map +1 -0
  92. package/dist/components/native-space-callkit-controller.d.ts +39 -0
  93. package/dist/components/native-space-callkit-controller.d.ts.map +1 -0
  94. package/dist/components/native-space-view/AppearanceSettings.d.ts +2 -0
  95. package/dist/components/native-space-view/AppearanceSettings.d.ts.map +1 -0
  96. package/dist/components/native-space-view/ParticipantActionSheet.d.ts +9 -0
  97. package/dist/components/native-space-view/ParticipantActionSheet.d.ts.map +1 -0
  98. package/dist/components/native-space-view/SettingsSheet.d.ts +7 -0
  99. package/dist/components/native-space-view/SettingsSheet.d.ts.map +1 -0
  100. package/dist/components/native-space-view/SpaceActionMenu.d.ts +8 -0
  101. package/dist/components/native-space-view/SpaceActionMenu.d.ts.map +1 -0
  102. package/dist/components/native-space-view/SpaceBottomDock.android.d.ts +4 -0
  103. package/dist/components/native-space-view/SpaceBottomDock.android.d.ts.map +1 -0
  104. package/dist/components/native-space-view/SpaceChatSheet.d.ts +5 -0
  105. package/dist/components/native-space-view/SpaceChatSheet.d.ts.map +1 -0
  106. package/dist/components/native-space-view/SpaceGrid.android.d.ts +8 -0
  107. package/dist/components/native-space-view/SpaceGrid.android.d.ts.map +1 -0
  108. package/dist/components/native-space-view/SpaceMoreSheet.d.ts +6 -0
  109. package/dist/components/native-space-view/SpaceMoreSheet.d.ts.map +1 -0
  110. package/dist/components/native-space-view/SpacePanelSheet.d.ts +5 -0
  111. package/dist/components/native-space-view/SpacePanelSheet.d.ts.map +1 -0
  112. package/dist/components/native-space-view/SpacePeopleSheet.d.ts +5 -0
  113. package/dist/components/native-space-view/SpacePeopleSheet.d.ts.map +1 -0
  114. package/dist/components/native-space-view/SpaceStage.android.d.ts +29 -0
  115. package/dist/components/native-space-view/SpaceStage.android.d.ts.map +1 -0
  116. package/dist/components/native-space-view/SpaceSurfacePrimitives.d.ts +30 -0
  117. package/dist/components/native-space-view/SpaceSurfacePrimitives.d.ts.map +1 -0
  118. package/dist/components/native-space-view/SpaceTopBar.android.d.ts +9 -0
  119. package/dist/components/native-space-view/SpaceTopBar.android.d.ts.map +1 -0
  120. package/dist/components/native-space-view/SpaceWhiteboardSurface.d.ts +15 -0
  121. package/dist/components/native-space-view/SpaceWhiteboardSurface.d.ts.map +1 -0
  122. package/dist/components/native-space-view/diagnostics.d.ts +48 -0
  123. package/dist/components/native-space-view/diagnostics.d.ts.map +1 -0
  124. package/dist/components/native-space-view/format-space-duration.d.ts +2 -0
  125. package/dist/components/native-space-view/format-space-duration.d.ts.map +1 -0
  126. package/dist/components/native-space-view/native-space-grid-keys.d.ts +3 -0
  127. package/dist/components/native-space-view/native-space-grid-keys.d.ts.map +1 -0
  128. package/dist/components/native-space-view/native-space-page-store.d.ts +8 -0
  129. package/dist/components/native-space-view/native-space-page-store.d.ts.map +1 -0
  130. package/dist/components/native-space-view/screen-share-availability.d.ts +9 -0
  131. package/dist/components/native-space-view/screen-share-availability.d.ts.map +1 -0
  132. package/dist/components/native-space-view/space-chat-attachments.d.ts +15 -0
  133. package/dist/components/native-space-view/space-chat-attachments.d.ts.map +1 -0
  134. package/dist/components/native-space-view/space-panel-layout.d.ts +10 -0
  135. package/dist/components/native-space-view/space-panel-layout.d.ts.map +1 -0
  136. package/dist/components/native-space-view/space-progressive-surface-helpers.d.ts +16 -0
  137. package/dist/components/native-space-view/space-progressive-surface-helpers.d.ts.map +1 -0
  138. package/dist/components/native-space-view/space-progressive-surface-types.d.ts +3 -0
  139. package/dist/components/native-space-view/space-progressive-surface-types.d.ts.map +1 -0
  140. package/dist/components/native-space-view/types.d.ts +24 -0
  141. package/dist/components/native-space-view/types.d.ts.map +1 -0
  142. package/dist/components/native-space-view/useSpaceViewController.contract.d.ts +41 -0
  143. package/dist/components/native-space-view/useSpaceViewController.contract.d.ts.map +1 -0
  144. package/dist/components/native-space-view/useSpaceViewController.d.ts +150 -0
  145. package/dist/components/native-space-view/useSpaceViewController.d.ts.map +1 -0
  146. package/dist/components/native-space-view/useSpaceViewDerived.d.ts +12 -0
  147. package/dist/components/native-space-view/useSpaceViewDerived.d.ts.map +1 -0
  148. package/dist/components/native-space-view/useSpaceViewPanels.d.ts +70 -0
  149. package/dist/components/native-space-view/useSpaceViewPanels.d.ts.map +1 -0
  150. package/dist/components/rtc-video-view-availability.d.ts +13 -0
  151. package/dist/components/rtc-video-view-availability.d.ts.map +1 -0
  152. package/dist/components/space-lifecycle.d.ts +3 -0
  153. package/dist/components/space-lifecycle.d.ts.map +1 -0
  154. package/dist/components/useAndroidConnectionService.d.ts +14 -0
  155. package/dist/components/useAndroidConnectionService.d.ts.map +1 -0
  156. package/dist/context/space-client-context.d.ts +9 -0
  157. package/dist/context/space-client-context.d.ts.map +1 -0
  158. package/dist/diagnostics.d.ts +50 -0
  159. package/dist/diagnostics.d.ts.map +1 -0
  160. package/dist/diagnostics.js +143 -0
  161. package/dist/hooks/entrance-preview-store.d.ts +16 -0
  162. package/dist/hooks/entrance-preview-store.d.ts.map +1 -0
  163. package/dist/hooks/external-store.d.ts +10 -0
  164. package/dist/hooks/external-store.d.ts.map +1 -0
  165. package/dist/hooks/space-hooks.d.ts +10 -0
  166. package/dist/hooks/space-hooks.d.ts.map +1 -0
  167. package/dist/hooks/useEntrancePreview.d.ts +7 -0
  168. package/dist/hooks/useEntrancePreview.d.ts.map +1 -0
  169. package/dist/hooks/useLayout.d.ts +16 -0
  170. package/dist/hooks/useLayout.d.ts.map +1 -0
  171. package/dist/hooks/usePanels.d.ts +12 -0
  172. package/dist/hooks/usePanels.d.ts.map +1 -0
  173. package/dist/index.d.ts +11 -0
  174. package/dist/index.d.ts.map +1 -0
  175. package/dist/index.js +47 -0
  176. package/dist/invites.d.ts +3 -0
  177. package/dist/invites.d.ts.map +1 -0
  178. package/dist/invites.js +41 -0
  179. package/dist/ios-pad.d.ts +2 -0
  180. package/dist/ios-pad.d.ts.map +1 -0
  181. package/dist/ios-pad.js +47 -0
  182. package/dist/ios-phone.d.ts +2 -0
  183. package/dist/ios-phone.d.ts.map +1 -0
  184. package/dist/ios-phone.js +47 -0
  185. package/dist/ios.d.ts +2 -0
  186. package/dist/ios.d.ts.map +1 -0
  187. package/dist/ios.js +47 -0
  188. package/dist/macos.d.ts +2 -0
  189. package/dist/macos.d.ts.map +1 -0
  190. package/dist/macos.js +47 -0
  191. package/dist/media/native-webrtc.d.ts +6 -0
  192. package/dist/media/native-webrtc.d.ts.map +1 -0
  193. package/dist/platform/platform.d.ts +3 -0
  194. package/dist/platform/platform.d.ts.map +1 -0
  195. package/dist/runtime.d.ts +38 -0
  196. package/dist/runtime.d.ts.map +1 -0
  197. package/dist/runtime.js +30 -0
  198. package/dist/space-client/create-native-space-client.d.ts +17 -0
  199. package/dist/space-client/create-native-space-client.d.ts.map +1 -0
  200. package/dist/telemetry.d.ts +63 -0
  201. package/dist/telemetry.d.ts.map +1 -0
  202. package/dist/test-support/test-renderer.d.ts +20 -0
  203. package/dist/test-support/test-renderer.d.ts.map +1 -0
  204. package/dist/ui/appearance.d.ts +239 -0
  205. package/dist/ui/appearance.d.ts.map +1 -0
  206. package/dist/ui/appearance.js +14 -0
  207. package/dist/ui/native-appearance-context.d.ts +15 -0
  208. package/dist/ui/native-appearance-context.d.ts.map +1 -0
  209. package/dist/ui/native-theme.d.ts +17 -0
  210. package/dist/ui/native-theme.d.ts.map +1 -0
  211. package/dist/ui/native-types.d.ts +38 -0
  212. package/dist/ui/native-types.d.ts.map +1 -0
  213. package/dist/ui/participant-avatar.d.ts +21 -0
  214. package/dist/ui/participant-avatar.d.ts.map +1 -0
  215. package/dist/ui/theme-tokens.d.ts +25 -0
  216. package/dist/ui/theme-tokens.d.ts.map +1 -0
  217. package/dist/ui/theme.d.ts +404 -0
  218. package/dist/ui/theme.d.ts.map +1 -0
  219. package/dist/ui/theme.js +8 -0
  220. package/dist/utils/build-chalk-invite-link.d.ts +2 -0
  221. package/dist/utils/build-chalk-invite-link.d.ts.map +1 -0
  222. package/dist/utils/ios-simulator.d.ts +5 -0
  223. package/dist/utils/ios-simulator.d.ts.map +1 -0
  224. package/dist/utils/native-space-layout.d.ts +42 -0
  225. package/dist/utils/native-space-layout.d.ts.map +1 -0
  226. package/dist/whiteboard/embedded-whiteboard-assets.d.ts +7 -0
  227. package/dist/whiteboard/embedded-whiteboard-assets.d.ts.map +1 -0
  228. package/embedded/chalk-whiteboard/THIRD_PARTY_NOTICES.json +17 -0
  229. package/embedded/chalk-whiteboard/asset-manifest.json +1228 -0
  230. package/embedded/chalk-whiteboard/chalk.css +5 -0
  231. package/embedded/chalk-whiteboard/compatibility-manifest.json +37 -0
  232. package/embedded/chalk-whiteboard/fonts/Assistant/Assistant-Bold.woff2 +0 -0
  233. package/embedded/chalk-whiteboard/fonts/Assistant/Assistant-Medium.woff2 +0 -0
  234. package/embedded/chalk-whiteboard/fonts/Assistant/Assistant-Regular.woff2 +0 -0
  235. package/embedded/chalk-whiteboard/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
  236. package/embedded/chalk-whiteboard/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
  237. package/embedded/chalk-whiteboard/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
  238. package/embedded/chalk-whiteboard/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
  239. package/embedded/chalk-whiteboard/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
  240. package/embedded/chalk-whiteboard/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
  241. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
  242. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
  243. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
  244. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
  245. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
  246. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
  247. package/embedded/chalk-whiteboard/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
  248. package/embedded/chalk-whiteboard/fonts/Liberation/LiberationSans-Regular.woff2 +0 -0
  249. package/embedded/chalk-whiteboard/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
  250. package/embedded/chalk-whiteboard/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
  251. package/embedded/chalk-whiteboard/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
  252. package/embedded/chalk-whiteboard/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
  253. package/embedded/chalk-whiteboard/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
  254. package/embedded/chalk-whiteboard/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
  255. package/embedded/chalk-whiteboard/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
  256. package/embedded/chalk-whiteboard/fonts/Virgil/Virgil-Regular.woff2 +0 -0
  257. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2 +0 -0
  258. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2 +0 -0
  259. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2 +0 -0
  260. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2 +0 -0
  261. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2 +0 -0
  262. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2 +0 -0
  263. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2 +0 -0
  264. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2 +0 -0
  265. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2 +0 -0
  266. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2 +0 -0
  267. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2 +0 -0
  268. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2 +0 -0
  269. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2 +0 -0
  270. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2 +0 -0
  271. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2 +0 -0
  272. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2 +0 -0
  273. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2 +0 -0
  274. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2 +0 -0
  275. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2 +0 -0
  276. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2 +0 -0
  277. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2 +0 -0
  278. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2 +0 -0
  279. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2 +0 -0
  280. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2 +0 -0
  281. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2 +0 -0
  282. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2 +0 -0
  283. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2 +0 -0
  284. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2 +0 -0
  285. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2 +0 -0
  286. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2 +0 -0
  287. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2 +0 -0
  288. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2 +0 -0
  289. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2 +0 -0
  290. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2 +0 -0
  291. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2 +0 -0
  292. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2 +0 -0
  293. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2 +0 -0
  294. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2 +0 -0
  295. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2 +0 -0
  296. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2 +0 -0
  297. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2 +0 -0
  298. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2 +0 -0
  299. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2 +0 -0
  300. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2 +0 -0
  301. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2 +0 -0
  302. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2 +0 -0
  303. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2 +0 -0
  304. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2 +0 -0
  305. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2 +0 -0
  306. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2 +0 -0
  307. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2 +0 -0
  308. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2 +0 -0
  309. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2 +0 -0
  310. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2 +0 -0
  311. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2 +0 -0
  312. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2 +0 -0
  313. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2 +0 -0
  314. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2 +0 -0
  315. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2 +0 -0
  316. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2 +0 -0
  317. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2 +0 -0
  318. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2 +0 -0
  319. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2 +0 -0
  320. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2 +0 -0
  321. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2 +0 -0
  322. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2 +0 -0
  323. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2 +0 -0
  324. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2 +0 -0
  325. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2 +0 -0
  326. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2 +0 -0
  327. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2 +0 -0
  328. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2 +0 -0
  329. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2 +0 -0
  330. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2 +0 -0
  331. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2 +0 -0
  332. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2 +0 -0
  333. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2 +0 -0
  334. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2 +0 -0
  335. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2 +0 -0
  336. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2 +0 -0
  337. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2 +0 -0
  338. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2 +0 -0
  339. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2 +0 -0
  340. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2 +0 -0
  341. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2 +0 -0
  342. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2 +0 -0
  343. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2 +0 -0
  344. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2 +0 -0
  345. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2 +0 -0
  346. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2 +0 -0
  347. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2 +0 -0
  348. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2 +0 -0
  349. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2 +0 -0
  350. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2 +0 -0
  351. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2 +0 -0
  352. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2 +0 -0
  353. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2 +0 -0
  354. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2 +0 -0
  355. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2 +0 -0
  356. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2 +0 -0
  357. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2 +0 -0
  358. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2 +0 -0
  359. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2 +0 -0
  360. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2 +0 -0
  361. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2 +0 -0
  362. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2 +0 -0
  363. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2 +0 -0
  364. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2 +0 -0
  365. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2 +0 -0
  366. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2 +0 -0
  367. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2 +0 -0
  368. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2 +0 -0
  369. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2 +0 -0
  370. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2 +0 -0
  371. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2 +0 -0
  372. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2 +0 -0
  373. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2 +0 -0
  374. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2 +0 -0
  375. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2 +0 -0
  376. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2 +0 -0
  377. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2 +0 -0
  378. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2 +0 -0
  379. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2 +0 -0
  380. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2 +0 -0
  381. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2 +0 -0
  382. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2 +0 -0
  383. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2 +0 -0
  384. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2 +0 -0
  385. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2 +0 -0
  386. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2 +0 -0
  387. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2 +0 -0
  388. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2 +0 -0
  389. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2 +0 -0
  390. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2 +0 -0
  391. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2 +0 -0
  392. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2 +0 -0
  393. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2 +0 -0
  394. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2 +0 -0
  395. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2 +0 -0
  396. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2 +0 -0
  397. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2 +0 -0
  398. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2 +0 -0
  399. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2 +0 -0
  400. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2 +0 -0
  401. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2 +0 -0
  402. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2 +0 -0
  403. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2 +0 -0
  404. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2 +0 -0
  405. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2 +0 -0
  406. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2 +0 -0
  407. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2 +0 -0
  408. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2 +0 -0
  409. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2 +0 -0
  410. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2 +0 -0
  411. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2 +0 -0
  412. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2 +0 -0
  413. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2 +0 -0
  414. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2 +0 -0
  415. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2 +0 -0
  416. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2 +0 -0
  417. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2 +0 -0
  418. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2 +0 -0
  419. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2 +0 -0
  420. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2 +0 -0
  421. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2 +0 -0
  422. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2 +0 -0
  423. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2 +0 -0
  424. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2 +0 -0
  425. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2 +0 -0
  426. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2 +0 -0
  427. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2 +0 -0
  428. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2 +0 -0
  429. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2 +0 -0
  430. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2 +0 -0
  431. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2 +0 -0
  432. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2 +0 -0
  433. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2 +0 -0
  434. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2 +0 -0
  435. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2 +0 -0
  436. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2 +0 -0
  437. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2 +0 -0
  438. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2 +0 -0
  439. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2 +0 -0
  440. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2 +0 -0
  441. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2 +0 -0
  442. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2 +0 -0
  443. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2 +0 -0
  444. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2 +0 -0
  445. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2 +0 -0
  446. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2 +0 -0
  447. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2 +0 -0
  448. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2 +0 -0
  449. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2 +0 -0
  450. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2 +0 -0
  451. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2 +0 -0
  452. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2 +0 -0
  453. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2 +0 -0
  454. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2 +0 -0
  455. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2 +0 -0
  456. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2 +0 -0
  457. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2 +0 -0
  458. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2 +0 -0
  459. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2 +0 -0
  460. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2 +0 -0
  461. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2 +0 -0
  462. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2 +0 -0
  463. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2 +0 -0
  464. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2 +0 -0
  465. package/embedded/chalk-whiteboard/fonts/Xiaolai/Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2 +0 -0
  466. package/embedded/chalk-whiteboard/index.css +1 -0
  467. package/embedded/chalk-whiteboard/index.html +17 -0
  468. package/embedded/chalk-whiteboard/licenses/Excalidraw.txt +21 -0
  469. package/embedded/chalk-whiteboard/licenses/MathJax.txt +202 -0
  470. package/embedded/chalk-whiteboard/mathjax/tex-svg.js +1 -0
  471. package/embedded/chalk-whiteboard/mathjax-config.js +1 -0
  472. package/embedded/chalk-whiteboard/renderer.js +4114 -0
  473. package/ios/ChalkCallKitManager.swift +385 -0
  474. package/ios/ChalkCallKitModule.swift +120 -0
  475. package/ios/ChalkCallKitModuleBridge.m +14 -0
  476. package/ios/ChalkWhiteboardAssets.swift +41 -0
  477. package/ios/ChalkWhiteboardAssetsBridge.m +10 -0
  478. package/package.json +184 -0
  479. package/src/android/connection-service.test.ts +114 -0
  480. package/src/android/connection-service.ts +106 -0
  481. package/src/android.ts +1 -0
  482. package/src/callkit/callkit.test.ts +95 -0
  483. package/src/callkit/callkit.ts +135 -0
  484. package/src/callkit/resolve-space-callkit-options.test.ts +68 -0
  485. package/src/callkit/resolve-space-callkit-options.ts +34 -0
  486. package/src/client.test.ts +12 -0
  487. package/src/client.ts +7 -0
  488. package/src/clipboard-store.ts +108 -0
  489. package/src/clipboard.test.ts +79 -0
  490. package/src/clipboard.ts +36 -0
  491. package/src/components/Chalk.test.tsx +213 -0
  492. package/src/components/Chalk.tsx +333 -0
  493. package/src/components/ChatMessageList.tsx +209 -0
  494. package/src/components/EmbeddedWhiteboard.test.tsx +92 -0
  495. package/src/components/EmbeddedWhiteboard.tsx +260 -0
  496. package/src/components/Entrance.test.tsx +19 -0
  497. package/src/components/Entrance.tsx +41 -0
  498. package/src/components/EntranceView.android.test.tsx +100 -0
  499. package/src/components/EntranceView.android.tsx +274 -0
  500. package/src/components/EntranceView.ios-pad.test.tsx +160 -0
  501. package/src/components/EntranceView.ios-pad.tsx +326 -0
  502. package/src/components/EntranceView.ios-phone.test.tsx +137 -0
  503. package/src/components/EntranceView.ios-phone.tsx +271 -0
  504. package/src/components/EntranceView.macos.tsx +278 -0
  505. package/src/components/EntranceView.test.tsx +15 -0
  506. package/src/components/EntranceView.tsx +38 -0
  507. package/src/components/FaceAvatar.tsx +120 -0
  508. package/src/components/GradientSurface.tsx +23 -0
  509. package/src/components/LogoElements.test.tsx +60 -0
  510. package/src/components/LogoElements.tsx +119 -0
  511. package/src/components/MediaView.tsx +76 -0
  512. package/src/components/ReactionPicker.test.tsx +19 -0
  513. package/src/components/ReactionPicker.tsx +98 -0
  514. package/src/components/RtcVideoView.test.tsx +12 -0
  515. package/src/components/RtcVideoView.tsx +15 -0
  516. package/src/components/SpaceView.android.test.tsx +11 -0
  517. package/src/components/SpaceView.android.tsx +1 -0
  518. package/src/components/SpaceView.ios-pad.test.tsx +11 -0
  519. package/src/components/SpaceView.ios-pad.tsx +1 -0
  520. package/src/components/SpaceView.ios-phone.test.tsx +11 -0
  521. package/src/components/SpaceView.ios-phone.tsx +1 -0
  522. package/src/components/SpaceView.macos.test.tsx +11 -0
  523. package/src/components/SpaceView.macos.tsx +1 -0
  524. package/src/components/SpaceView.shared.test.tsx +115 -0
  525. package/src/components/SpaceView.shared.tsx +87 -0
  526. package/src/components/SpaceView.test.tsx +15 -0
  527. package/src/components/SpaceView.tsx +52 -0
  528. package/src/components/android-connection-service-controller.test.ts +80 -0
  529. package/src/components/android-connection-service-controller.ts +132 -0
  530. package/src/components/episode-diagnostic-render-observer.test.ts +24 -0
  531. package/src/components/episode-diagnostic-render-observer.ts +12 -0
  532. package/src/components/native-animation-controller.test.ts +47 -0
  533. package/src/components/native-animation-controller.ts +36 -0
  534. package/src/components/native-chat.test.ts +22 -0
  535. package/src/components/native-chat.ts +23 -0
  536. package/src/components/native-entrance/entrance-controller-store.test.ts +75 -0
  537. package/src/components/native-entrance/entrance-controller-store.ts +112 -0
  538. package/src/components/native-entrance/useEntranceController.ts +60 -0
  539. package/src/components/native-joining-loading-animation.ts +26 -0
  540. package/src/components/native-media-visibility.test.ts +77 -0
  541. package/src/components/native-media-visibility.ts +18 -0
  542. package/src/components/native-space-callkit-controller.test.ts +62 -0
  543. package/src/components/native-space-callkit-controller.ts +131 -0
  544. package/src/components/native-space-view/AppearanceSettings.test.tsx +56 -0
  545. package/src/components/native-space-view/AppearanceSettings.tsx +114 -0
  546. package/src/components/native-space-view/ParticipantActionSheet.test.tsx +18 -0
  547. package/src/components/native-space-view/ParticipantActionSheet.tsx +99 -0
  548. package/src/components/native-space-view/SettingsSheet.test.tsx +17 -0
  549. package/src/components/native-space-view/SettingsSheet.tsx +164 -0
  550. package/src/components/native-space-view/SpaceActionMenu.test.tsx +110 -0
  551. package/src/components/native-space-view/SpaceActionMenu.tsx +78 -0
  552. package/src/components/native-space-view/SpaceBottomDock.android.test.tsx +61 -0
  553. package/src/components/native-space-view/SpaceBottomDock.android.tsx +115 -0
  554. package/src/components/native-space-view/SpaceChatSheet.test.tsx +18 -0
  555. package/src/components/native-space-view/SpaceChatSheet.tsx +179 -0
  556. package/src/components/native-space-view/SpaceGrid.android.tsx +323 -0
  557. package/src/components/native-space-view/SpaceMoreSheet.test.tsx +15 -0
  558. package/src/components/native-space-view/SpaceMoreSheet.tsx +161 -0
  559. package/src/components/native-space-view/SpacePanelSheet.test.tsx +15 -0
  560. package/src/components/native-space-view/SpacePanelSheet.tsx +45 -0
  561. package/src/components/native-space-view/SpacePeopleSheet.test.tsx +13 -0
  562. package/src/components/native-space-view/SpacePeopleSheet.tsx +116 -0
  563. package/src/components/native-space-view/SpaceStage.android.tsx +372 -0
  564. package/src/components/native-space-view/SpaceSurfacePrimitives.test.tsx +12 -0
  565. package/src/components/native-space-view/SpaceSurfacePrimitives.tsx +75 -0
  566. package/src/components/native-space-view/SpaceTopBar.android.test.tsx +43 -0
  567. package/src/components/native-space-view/SpaceTopBar.android.tsx +97 -0
  568. package/src/components/native-space-view/SpaceWhiteboardSurface.test.tsx +85 -0
  569. package/src/components/native-space-view/SpaceWhiteboardSurface.tsx +69 -0
  570. package/src/components/native-space-view/diagnostics.test.ts +31 -0
  571. package/src/components/native-space-view/diagnostics.ts +84 -0
  572. package/src/components/native-space-view/format-space-duration.test.ts +13 -0
  573. package/src/components/native-space-view/format-space-duration.ts +3 -0
  574. package/src/components/native-space-view/native-space-grid-keys.test.ts +11 -0
  575. package/src/components/native-space-view/native-space-grid-keys.ts +6 -0
  576. package/src/components/native-space-view/native-space-page-store.test.ts +23 -0
  577. package/src/components/native-space-view/native-space-page-store.ts +41 -0
  578. package/src/components/native-space-view/screen-share-availability.ts +21 -0
  579. package/src/components/native-space-view/space-chat-attachments.test.ts +33 -0
  580. package/src/components/native-space-view/space-chat-attachments.ts +39 -0
  581. package/src/components/native-space-view/space-panel-layout.ts +10 -0
  582. package/src/components/native-space-view/space-progressive-surface-helpers.test.ts +24 -0
  583. package/src/components/native-space-view/space-progressive-surface-helpers.ts +33 -0
  584. package/src/components/native-space-view/space-progressive-surface-types.ts +3 -0
  585. package/src/components/native-space-view/types.ts +25 -0
  586. package/src/components/native-space-view/useSpaceViewController.contract.test.ts +10 -0
  587. package/src/components/native-space-view/useSpaceViewController.contract.ts +34 -0
  588. package/src/components/native-space-view/useSpaceViewController.test.ts +105 -0
  589. package/src/components/native-space-view/useSpaceViewController.ts +396 -0
  590. package/src/components/native-space-view/useSpaceViewDerived.test.ts +58 -0
  591. package/src/components/native-space-view/useSpaceViewDerived.ts +29 -0
  592. package/src/components/native-space-view/useSpaceViewPanels.controlled.test.ts +40 -0
  593. package/src/components/native-space-view/useSpaceViewPanels.test.ts +73 -0
  594. package/src/components/native-space-view/useSpaceViewPanels.ts +170 -0
  595. package/src/components/rtc-video-view-availability.ts +16 -0
  596. package/src/components/space-lifecycle.test.ts +19 -0
  597. package/src/components/space-lifecycle.ts +2 -0
  598. package/src/components/useAndroidConnectionService.ts +55 -0
  599. package/src/context/space-client-context.test.tsx +10 -0
  600. package/src/context/space-client-context.tsx +21 -0
  601. package/src/diagnostics.test.ts +29 -0
  602. package/src/diagnostics.ts +187 -0
  603. package/src/hooks/entrance-preview-store.test.ts +79 -0
  604. package/src/hooks/entrance-preview-store.ts +99 -0
  605. package/src/hooks/external-store.ts +18 -0
  606. package/src/hooks/space-hooks.test.ts +76 -0
  607. package/src/hooks/space-hooks.ts +43 -0
  608. package/src/hooks/useEntrancePreview.ts +26 -0
  609. package/src/hooks/useLayout.test.ts +16 -0
  610. package/src/hooks/useLayout.ts +37 -0
  611. package/src/hooks/usePanels.ts +30 -0
  612. package/src/index.ts +10 -0
  613. package/src/invites.test.ts +56 -0
  614. package/src/invites.ts +43 -0
  615. package/src/ios-pad.ts +1 -0
  616. package/src/ios-phone.ts +1 -0
  617. package/src/ios.ts +1 -0
  618. package/src/macos.ts +1 -0
  619. package/src/media/native-webrtc.ts +11 -0
  620. package/src/platform/platform.ts +34 -0
  621. package/src/public-surface.test.ts +25 -0
  622. package/src/runtime.test.ts +83 -0
  623. package/src/runtime.ts +142 -0
  624. package/src/space-client/create-native-space-client.test.ts +247 -0
  625. package/src/space-client/create-native-space-client.ts +280 -0
  626. package/src/telemetry.test.ts +143 -0
  627. package/src/telemetry.ts +234 -0
  628. package/src/test-support/test-renderer.test.ts +9 -0
  629. package/src/test-support/test-renderer.ts +26 -0
  630. package/src/types/hugeicons-direct.d.ts +4 -0
  631. package/src/types/react-native-safe-area-context.d.ts +8 -0
  632. package/src/ui/appearance.test.ts +50 -0
  633. package/src/ui/appearance.ts +770 -0
  634. package/src/ui/native-appearance-context.controlled.test.tsx +41 -0
  635. package/src/ui/native-appearance-context.test.tsx +14 -0
  636. package/src/ui/native-appearance-context.tsx +74 -0
  637. package/src/ui/native-theme.test.ts +34 -0
  638. package/src/ui/native-theme.test.tsx +14 -0
  639. package/src/ui/native-theme.tsx +54 -0
  640. package/src/ui/native-types.ts +40 -0
  641. package/src/ui/participant-avatar.test.ts +29 -0
  642. package/src/ui/participant-avatar.ts +47 -0
  643. package/src/ui/theme-tokens.test.ts +14 -0
  644. package/src/ui/theme-tokens.ts +41 -0
  645. package/src/ui/theme.test.ts +36 -0
  646. package/src/ui/theme.ts +214 -0
  647. package/src/utils/build-chalk-invite-link.test.ts +12 -0
  648. package/src/utils/build-chalk-invite-link.ts +5 -0
  649. package/src/utils/ios-simulator.test.ts +96 -0
  650. package/src/utils/ios-simulator.ts +125 -0
  651. package/src/utils/native-space-layout.test.ts +170 -0
  652. package/src/utils/native-space-layout.ts +135 -0
  653. package/src/whiteboard/embedded-whiteboard-assets.test.ts +31 -0
  654. package/src/whiteboard/embedded-whiteboard-assets.ts +41 -0
@@ -0,0 +1,4501 @@
1
+ import {
2
+ THEME_PALETTES,
3
+ THEME_TEXTURES,
4
+ resolveNativeAppearance
5
+ } from "./chunk-IMKSYT7R.js";
6
+ import {
7
+ DEFAULT_CHALK_THEME_TOKENS,
8
+ LIGHT_CHALK_THEME_TOKENS,
9
+ Theme,
10
+ createNativeTheme
11
+ } from "./chunk-JB4LNWVP.js";
12
+ import {
13
+ createNativeSpaceClient,
14
+ getNativeJourneyContext
15
+ } from "./chunk-HXYIJ75K.js";
16
+
17
+ // src/components/Chalk.tsx
18
+ import { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo15, useRef as useRef5, useState as useState9 } from "react";
19
+ import { Pressable as Pressable16, StyleSheet as StyleSheet25, Text as Text19, View as View24 } from "react-native";
20
+
21
+ // src/context/space-client-context.tsx
22
+ import { createContext, useContext, useMemo } from "react";
23
+ import { jsx } from "react/jsx-runtime";
24
+ var SpaceClientContext = createContext(null);
25
+ function ChalkProvider({ children, client }) {
26
+ const value = useMemo(() => client, [client]);
27
+ return /* @__PURE__ */ jsx(SpaceClientContext.Provider, { value, children });
28
+ }
29
+ function useSpaceClient() {
30
+ const client = useContext(SpaceClientContext);
31
+ if (!client) throw new Error("Chalk hooks must be used within a ChalkProvider.");
32
+ return client;
33
+ }
34
+
35
+ // src/hooks/space-hooks.ts
36
+ import { useCallback, useSyncExternalStore } from "react";
37
+ function useSpaceSlice(slice) {
38
+ const client = useSpaceClient();
39
+ const subscribe = useCallback((listener) => client.subscribe(listener), [client]);
40
+ const getSnapshot = useCallback(() => client.getSnapshot()[slice], [client, slice]);
41
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
42
+ }
43
+ function useConnection() {
44
+ return useSpaceSlice("connection");
45
+ }
46
+ function useSelf() {
47
+ return useSpaceSlice("self");
48
+ }
49
+ function useParticipants() {
50
+ return useSpaceSlice("participants");
51
+ }
52
+ function useMedia() {
53
+ return useSpaceSlice("media");
54
+ }
55
+ function useChat() {
56
+ return useSpaceSlice("chat");
57
+ }
58
+ function useReactions() {
59
+ return useSpaceSlice("reactions");
60
+ }
61
+ function useWhiteboard() {
62
+ return useSpaceSlice("whiteboard");
63
+ }
64
+ function useCan(capability) {
65
+ return useSelf().can(capability);
66
+ }
67
+
68
+ // src/ui/native-appearance-context.tsx
69
+ import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useEffect, useMemo as useMemo2, useState } from "react";
70
+ import { StyleSheet, View } from "react-native";
71
+ import { jsx as jsx2 } from "react/jsx-runtime";
72
+ var NativeAppearanceContext = createContext2(null);
73
+ function NativeAppearanceProvider({ children, initialAppearance }) {
74
+ const [selection, setSelection] = useState({ palette: initialAppearance?.palette ?? "light", texture: initialAppearance?.texture ?? "none" });
75
+ useEffect(() => {
76
+ if (initialAppearance?.palette === void 0 && initialAppearance?.texture === void 0) return;
77
+ setSelection((current) => {
78
+ const next = {
79
+ palette: initialAppearance?.palette ?? current.palette,
80
+ texture: initialAppearance?.texture ?? current.texture
81
+ };
82
+ return next.palette === current.palette && next.texture === current.texture ? current : next;
83
+ });
84
+ }, [initialAppearance?.palette, initialAppearance?.texture]);
85
+ const appearance = useMemo2(() => resolveNativeAppearance(selection), [selection]);
86
+ const updateSelection = useCallback2((next) => {
87
+ setSelection(next);
88
+ }, []);
89
+ const value = useMemo2(
90
+ () => ({
91
+ appearance,
92
+ setPalette: (palette) => updateSelection({ ...selection, palette }),
93
+ setTexture: (texture) => updateSelection({ ...selection, texture })
94
+ }),
95
+ [appearance, selection, updateSelection]
96
+ );
97
+ return /* @__PURE__ */ jsx2(NativeAppearanceContext.Provider, { value, children });
98
+ }
99
+ function useNativeAppearance() {
100
+ const value = useContext2(NativeAppearanceContext);
101
+ if (!value) throw new Error("useNativeAppearance must be used inside NativeAppearanceProvider");
102
+ return value;
103
+ }
104
+ function NativeTextureOverlay() {
105
+ const { appearance } = useNativeAppearance();
106
+ const descriptor = appearance.textureDescriptor;
107
+ if (descriptor.kind === "none") return null;
108
+ const marks = descriptor.kind === "paper-grain" ? 44 : 26;
109
+ return /* @__PURE__ */ jsx2(View, { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", pointerEvents: "none", style: [StyleSheet.absoluteFill, styles.overlay, { opacity: descriptor.opacity }], children: Array.from({ length: marks }, (_, index) => {
110
+ const size = descriptor.kind === "paper-grain" ? 1 + index % 2 : 1;
111
+ return /* @__PURE__ */ jsx2(View, { style: [styles.mark, descriptor.kind === "slate" && styles.slateMark, { backgroundColor: appearance.tokens.text, height: size, left: `${index * 37 % 97}%`, top: `${index * 53 % 96}%`, width: descriptor.kind === "slate" ? 38 : size }] }, index);
112
+ }) });
113
+ }
114
+ var styles = StyleSheet.create({
115
+ overlay: { overflow: "hidden" },
116
+ mark: { borderRadius: 2, position: "absolute" },
117
+ slateMark: { opacity: 0.48, transform: [{ rotate: "7deg" }] }
118
+ });
119
+
120
+ // src/ui/native-theme.tsx
121
+ import { createContext as createContext3, useContext as useContext3, useMemo as useMemo3 } from "react";
122
+ import { jsx as jsx3 } from "react/jsx-runtime";
123
+ var NativeThemeContext = createContext3(Theme);
124
+ function resolveNativeTheme(input, appearance) {
125
+ const colorScheme = input?.colorScheme ?? appearance?.mode ?? "dark";
126
+ const base = appearance ? themeTokensFromAppearance(appearance) : colorScheme === "light" ? LIGHT_CHALK_THEME_TOKENS : DEFAULT_CHALK_THEME_TOKENS;
127
+ const accent = input?.accent;
128
+ return createNativeTheme(
129
+ {
130
+ ...base,
131
+ ...input?.tokens,
132
+ ...accent ? { accent, focus: accent } : {}
133
+ },
134
+ colorScheme
135
+ );
136
+ }
137
+ function NativeThemeProvider({ appearance, children, theme }) {
138
+ const value = useMemo3(() => resolveNativeTheme(theme, appearance), [appearance, theme?.accent, theme?.colorScheme, theme?.tokens]);
139
+ return /* @__PURE__ */ jsx3(NativeThemeContext.Provider, { value, children });
140
+ }
141
+ function useNativeTheme() {
142
+ return useContext3(NativeThemeContext);
143
+ }
144
+ function themeTokensFromAppearance(appearance) {
145
+ const tokens = appearance.tokens;
146
+ const base = appearance.mode === "light" ? LIGHT_CHALK_THEME_TOKENS : DEFAULT_CHALK_THEME_TOKENS;
147
+ return {
148
+ ...base,
149
+ canvas: tokens.canvas,
150
+ chrome: tokens.panel,
151
+ surface: tokens.panel,
152
+ stage: tokens.stage,
153
+ text: tokens.text,
154
+ mutedText: tokens.textMuted,
155
+ line: tokens.line,
156
+ focus: tokens.controlActiveLine,
157
+ accent: tokens.controlPrimary,
158
+ accentText: tokens.messageLocalText
159
+ };
160
+ }
161
+
162
+ // src/platform/platform.ts
163
+ import { Dimensions, Platform } from "react-native";
164
+ function getIsPad() {
165
+ const maybeIsPad = Platform.isPad;
166
+ if (typeof maybeIsPad === "boolean") {
167
+ return maybeIsPad;
168
+ }
169
+ if (Platform.OS !== "ios") {
170
+ return false;
171
+ }
172
+ const { width, height } = Dimensions.get("window");
173
+ return Math.min(width, height) >= 768;
174
+ }
175
+ function resolvePlatformVariant() {
176
+ const platformOS = Platform.OS;
177
+ switch (platformOS) {
178
+ case "android":
179
+ return "android";
180
+ case "ios":
181
+ return getIsPad() ? "ios-pad" : "ios-phone";
182
+ case "macos":
183
+ return "macos";
184
+ case "tvos":
185
+ return "tvos";
186
+ default:
187
+ return "android";
188
+ }
189
+ }
190
+
191
+ // src/components/SpaceView.shared.tsx
192
+ import { Alert as Alert3, StyleSheet as StyleSheet20, Text as Text14, View as View19 } from "react-native";
193
+
194
+ // src/utils/ios-simulator.ts
195
+ import { NativeModules, Platform as Platform2 } from "react-native";
196
+ var IOS_SIMULATOR_MEDIA_MESSAGE = "Camera and microphone are unavailable in the iOS Simulator. Join starts with media off.";
197
+ var EMPTY_RTP_CAPABILITIES = Object.freeze({
198
+ codecs: [],
199
+ headerExtensions: []
200
+ });
201
+ function isIosSimulator() {
202
+ if (Platform2.OS !== "ios") {
203
+ return false;
204
+ }
205
+ const runtimeInfo = NativeModules.ChalkRuntimeInfo;
206
+ return runtimeInfo?.isSimulator === true;
207
+ }
208
+ function getIosSimulatorVideoMessage() {
209
+ return IOS_SIMULATOR_MEDIA_MESSAGE;
210
+ }
211
+ function getIosSimulatorMediaMessage() {
212
+ return IOS_SIMULATOR_MEDIA_MESSAGE;
213
+ }
214
+
215
+ // src/components/ReactionPicker.tsx
216
+ import { memo } from "react";
217
+ import { Modal, Pressable, StyleSheet as StyleSheet2, Text, View as View2 } from "react-native";
218
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
219
+ var DEFAULT_REACTIONS = ["\u{1F44D}", "\u2764\uFE0F", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F389}"];
220
+ function ReactionPickerBase({ isOpen, onClose, onSelect }) {
221
+ return /* @__PURE__ */ jsx4(Modal, { animationType: "fade", transparent: true, visible: isOpen, onRequestClose: onClose, children: /* @__PURE__ */ jsxs(View2, { style: styles2.overlay, children: [
222
+ /* @__PURE__ */ jsx4(Pressable, { accessibilityLabel: "Close Reactions", onPress: onClose, style: styles2.backdrop }),
223
+ /* @__PURE__ */ jsxs(View2, { style: styles2.picker, children: [
224
+ /* @__PURE__ */ jsxs(View2, { style: styles2.header, children: [
225
+ /* @__PURE__ */ jsx4(Text, { accessibilityRole: "header", style: styles2.title, children: "Reactions" }),
226
+ /* @__PURE__ */ jsx4(Pressable, { accessibilityLabel: "Close Reactions", accessibilityRole: "button", onPress: onClose, style: ({ pressed }) => [styles2.closeButton, pressed && styles2.pressed], children: /* @__PURE__ */ jsx4(Text, { style: styles2.closeText, children: "\xD7" }) })
227
+ ] }),
228
+ DEFAULT_REACTIONS.map((emoji) => /* @__PURE__ */ jsx4(
229
+ Pressable,
230
+ {
231
+ accessibilityLabel: `Send ${emoji} reaction`,
232
+ accessibilityRole: "button",
233
+ onPress: () => {
234
+ onSelect(emoji);
235
+ onClose();
236
+ },
237
+ style: ({ pressed }) => [styles2.emojiButton, pressed && styles2.emojiButtonPressed],
238
+ children: /* @__PURE__ */ jsx4(Text, { style: styles2.emojiText, children: emoji })
239
+ },
240
+ emoji
241
+ ))
242
+ ] })
243
+ ] }) });
244
+ }
245
+ var styles2 = StyleSheet2.create({
246
+ overlay: {
247
+ flex: 1,
248
+ backgroundColor: Theme.colors.darkOverlay30,
249
+ justifyContent: "flex-end",
250
+ alignItems: "center",
251
+ paddingBottom: 100
252
+ },
253
+ backdrop: {
254
+ ...StyleSheet2.absoluteFillObject,
255
+ backgroundColor: Theme.colors.darkOverlay30
256
+ },
257
+ picker: {
258
+ flexDirection: "column",
259
+ backgroundColor: Theme.colors.insetSurface,
260
+ borderRadius: 28,
261
+ padding: 6,
262
+ gap: 4,
263
+ borderWidth: 1,
264
+ borderColor: Theme.colors.whiteOverlay08,
265
+ shadowColor: Theme.colors.darkCanvas,
266
+ shadowOffset: { width: 0, height: 8 },
267
+ shadowOpacity: 0.4,
268
+ shadowRadius: 16,
269
+ elevation: 12
270
+ },
271
+ header: { alignItems: "center", flexDirection: "row", justifyContent: "space-between", minHeight: 46, paddingHorizontal: 8, width: "100%" },
272
+ title: { color: Theme.colors.foreground, fontSize: 16, fontWeight: "700" },
273
+ closeButton: { alignItems: "center", borderColor: Theme.colors.border, borderRadius: Theme.radius.full, borderWidth: 1, height: 36, justifyContent: "center", width: 36 },
274
+ closeText: { color: Theme.colors.foreground, fontSize: 23, fontWeight: "400", lineHeight: 24 },
275
+ emojiButton: {
276
+ width: 48,
277
+ height: 48,
278
+ borderRadius: 24,
279
+ alignItems: "center",
280
+ justifyContent: "center"
281
+ },
282
+ emojiButtonPressed: {
283
+ backgroundColor: Theme.colors.whiteOverlay12,
284
+ transform: [{ scale: 0.88 }]
285
+ },
286
+ pressed: {
287
+ opacity: 0.72,
288
+ transform: [{ scale: 0.96 }]
289
+ },
290
+ emojiText: {
291
+ fontSize: 26
292
+ }
293
+ });
294
+ var ReactionPicker = memo(ReactionPickerBase);
295
+
296
+ // src/components/native-space-view/SpaceGrid.android.tsx
297
+ import { useCallback as useCallback3, useMemo as useMemo7, useRef, useSyncExternalStore as useSyncExternalStore2 } from "react";
298
+ import { FlatList, StyleSheet as StyleSheet6, Text as Text2, View as View6, useWindowDimensions } from "react-native";
299
+ import MicOff01Icon from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
300
+ import { HugeiconsIcon } from "@hugeicons/react-native";
301
+
302
+ // src/media/native-webrtc.ts
303
+ import { MediaStream, RTCView, mediaDevices } from "@cloudflare/react-native-webrtc";
304
+ function createNativeMediaStream(track) {
305
+ const stream = Reflect.construct(MediaStream, [[track]]);
306
+ if (!(stream instanceof MediaStream)) throw new TypeError("React Native WebRTC did not create a media stream");
307
+ return stream;
308
+ }
309
+
310
+ // src/components/MediaView.tsx
311
+ import { useEffect as useEffect2, useMemo as useMemo6 } from "react";
312
+ import { StyleSheet as StyleSheet5, View as View5 } from "react-native";
313
+
314
+ // src/components/native-media-visibility.ts
315
+ function shouldRenderNativeMediaTrack({ participant, track, mediaKind = "camera" }) {
316
+ if (!track) {
317
+ return false;
318
+ }
319
+ if (track.readyState === "ended") {
320
+ return false;
321
+ }
322
+ if (mediaKind === "camera" && participant && !participant.videoEnabled) {
323
+ return false;
324
+ }
325
+ return true;
326
+ }
327
+
328
+ // src/ui/participant-avatar.ts
329
+ var palettes = Theme.avatarPalettes;
330
+ var PARTICIPANT_AVATAR_PALETTE = palettes.map(([primary, , surface]) => ({ primary, surface }));
331
+ function getParticipantInitials(name) {
332
+ const parts = (name ?? "").trim().split(/\s+/).filter(Boolean);
333
+ if (parts.length === 0) return "?";
334
+ return `${parts[0]?.[0] ?? "?"}${parts[1]?.[0] ?? ""}`.toUpperCase();
335
+ }
336
+ function getParticipantColor(seed = "guest", _preference) {
337
+ const palette = palettes[hashString(seed) % palettes.length] ?? palettes[0];
338
+ return {
339
+ primary: palette[0],
340
+ gradientEnd: palette[0],
341
+ surface: palette[2]
342
+ };
343
+ }
344
+ function getParticipantAvatarRecipe(seed = "guest", preference) {
345
+ const colors = getParticipantColor(seed, preference);
346
+ return {
347
+ colors,
348
+ gradientStops: [
349
+ { color: colors.primary, offset: "0%" },
350
+ { color: colors.primary, offset: "100%" }
351
+ ],
352
+ facehashColors: [colors.primary, colors.primary, colors.primary]
353
+ };
354
+ }
355
+ function hashString(value) {
356
+ let hash = 0;
357
+ for (let index = 0; index < value.length; index += 1) {
358
+ hash = hash * 31 + value.charCodeAt(index) >>> 0;
359
+ }
360
+ return hash;
361
+ }
362
+
363
+ // src/components/FaceAvatar.tsx
364
+ import { FacehashNative } from "@q9labsai/facehash/react-native";
365
+ import { memo as memo3, useMemo as useMemo5, useState as useState2 } from "react";
366
+ import { Image, StyleSheet as StyleSheet4, View as View4 } from "react-native";
367
+
368
+ // src/components/GradientSurface.tsx
369
+ import { memo as memo2, useMemo as useMemo4 } from "react";
370
+ import { StyleSheet as StyleSheet3, View as View3 } from "react-native";
371
+ import { jsx as jsx5 } from "react/jsx-runtime";
372
+ function GradientSurfaceBase({ participantId, gradientPreference, borderRadius = 0, opacity = 1, variant = "surface" }) {
373
+ const colors = useMemo4(() => getParticipantColor(participantId, gradientPreference), [gradientPreference, participantId]);
374
+ const backgroundColor = variant === "avatar" ? colors.primary : colors.surface;
375
+ return /* @__PURE__ */ jsx5(View3, { pointerEvents: "none", style: [StyleSheet3.absoluteFillObject, { backgroundColor, borderRadius, opacity }] });
376
+ }
377
+ var GradientSurface = memo2(GradientSurfaceBase);
378
+
379
+ // src/components/FaceAvatar.tsx
380
+ import { Fragment, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
381
+ var sizeMap = {
382
+ xs: { size: 24 },
383
+ sm: { size: 32 },
384
+ md: { size: 48 },
385
+ lg: { size: 64 },
386
+ xl: { size: 96 },
387
+ "2xl": { size: 120 }
388
+ };
389
+ var statusColorMap = {
390
+ online: Theme.colors.success,
391
+ away: Theme.colors.warning,
392
+ busy: Theme.colors.error,
393
+ offline: Theme.colors.statusOffline
394
+ };
395
+ function FaceAvatarBase({ name, src, size = "md", status, gradientPreference, audioLevel = 0 }) {
396
+ const [imageError, setImageError] = useState2(false);
397
+ const hasUploadedImage = Boolean(src) && !imageError;
398
+ const { pxSize } = useMemo5(() => {
399
+ if (typeof size === "number") {
400
+ return { pxSize: size };
401
+ }
402
+ const mapped = sizeMap[size];
403
+ return { pxSize: mapped.size };
404
+ }, [size]);
405
+ const avatarRecipe = useMemo5(() => getParticipantAvatarRecipe(name || "unknown", gradientPreference), [gradientPreference, name]);
406
+ const wrapperStyle = useMemo5(
407
+ () => ({
408
+ height: pxSize,
409
+ width: pxSize,
410
+ transform: [{ scale: 1 + Math.min(0.06, Math.max(0, audioLevel) * 0.04) }]
411
+ }),
412
+ [pxSize, audioLevel]
413
+ );
414
+ const avatarStyle = useMemo5(
415
+ () => ({
416
+ borderRadius: pxSize / 2,
417
+ height: pxSize,
418
+ width: pxSize
419
+ }),
420
+ [pxSize]
421
+ );
422
+ const statusSize = Math.max(8, pxSize / 4);
423
+ return /* @__PURE__ */ jsxs2(View4, { style: [styles3.wrapper, wrapperStyle], children: [
424
+ /* @__PURE__ */ jsx6(View4, { style: [styles3.avatar, avatarStyle], children: hasUploadedImage ? /* @__PURE__ */ jsx6(Image, { source: { uri: src }, style: { width: pxSize, height: pxSize, borderRadius: pxSize / 2 }, onError: () => setImageError(true) }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
425
+ /* @__PURE__ */ jsx6(GradientSurface, { variant: "avatar", participantId: name, gradientPreference, borderRadius: pxSize / 2 }),
426
+ /* @__PURE__ */ jsx6(View4, { style: StyleSheet4.absoluteFillObject, children: /* @__PURE__ */ jsx6(FacehashNative, { colors: avatarRecipe.facehashColors, enableBlink: true, interactive: true, name: name || "guest", size: pxSize, testID: "native-facehash" }) })
427
+ ] }) }),
428
+ status && /* @__PURE__ */ jsx6(
429
+ View4,
430
+ {
431
+ style: [
432
+ styles3.statusIndicator,
433
+ {
434
+ width: statusSize,
435
+ height: statusSize,
436
+ borderRadius: statusSize / 2,
437
+ backgroundColor: statusColorMap[status],
438
+ borderWidth: 2,
439
+ borderColor: Theme.colors.darkCanvas
440
+ }
441
+ ]
442
+ }
443
+ )
444
+ ] });
445
+ }
446
+ var styles3 = StyleSheet4.create({
447
+ wrapper: {
448
+ alignItems: "center",
449
+ justifyContent: "center"
450
+ },
451
+ avatar: {
452
+ overflow: "hidden"
453
+ },
454
+ statusIndicator: {
455
+ position: "absolute",
456
+ bottom: 0,
457
+ right: 0
458
+ }
459
+ });
460
+ var FaceAvatar = memo3(FaceAvatarBase);
461
+
462
+ // src/components/rtc-video-view-availability.ts
463
+ function canRenderRtcVideoView(component) {
464
+ return typeof component === "function" || typeof component === "object" && component !== null;
465
+ }
466
+
467
+ // src/components/RtcVideoView.tsx
468
+ import { jsx as jsx7 } from "react/jsx-runtime";
469
+ function hasRtcVideoView() {
470
+ return canRenderRtcVideoView(RTCView);
471
+ }
472
+ function RtcVideoView(props) {
473
+ if (!canRenderRtcVideoView(RTCView)) {
474
+ return null;
475
+ }
476
+ const RtcView = RTCView;
477
+ return /* @__PURE__ */ jsx7(RtcView, { ...props });
478
+ }
479
+
480
+ // src/components/episode-diagnostic-render-observer.ts
481
+ var REGISTRY = /* @__PURE__ */ Symbol.for("@chalk/private/episode-diagnostic-render-registry/v1");
482
+ function observeNativeFrameNotObservable(track) {
483
+ try {
484
+ globalThis[REGISTRY]?.get(track)?.("not_observable");
485
+ } catch {
486
+ }
487
+ }
488
+
489
+ // src/components/MediaView.tsx
490
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
491
+ function MediaView({ participant, track, mediaKind = "camera", label, mirror = false, objectFit = "cover", zOrder = 0 }) {
492
+ const theme = useNativeTheme();
493
+ const shouldRenderVideo = shouldRenderNativeMediaTrack({ participant, track, mediaKind });
494
+ const canRenderPreview = hasRtcVideoView();
495
+ const stream = useMemo6(() => {
496
+ if (!shouldRenderVideo || !track) {
497
+ return null;
498
+ }
499
+ return createNativeMediaStream(track);
500
+ }, [shouldRenderVideo, track]);
501
+ const name = participant?.displayName?.trim() || label || "Participant";
502
+ const showStream = Boolean(stream && canRenderPreview);
503
+ const streamURL = showStream && stream ? stream.toURL() : null;
504
+ useEffect2(() => {
505
+ if (shouldRenderVideo && track) observeNativeFrameNotObservable(track);
506
+ }, [shouldRenderVideo, track]);
507
+ return /* @__PURE__ */ jsxs3(View5, { style: [styles4.surface, { backgroundColor: theme.colors.stageBackground }], children: [
508
+ streamURL ? /* @__PURE__ */ jsx8(RtcVideoView, { mirror, objectFit, streamURL, style: StyleSheet5.absoluteFillObject, zOrder: Math.max(1, zOrder) }) : null,
509
+ !showStream ? /* @__PURE__ */ jsxs3(View5, { style: styles4.fallback, children: [
510
+ /* @__PURE__ */ jsx8(GradientSurface, { borderRadius: 0, opacity: 0.92, participantId: name }),
511
+ /* @__PURE__ */ jsx8(FaceAvatar, { name, size: 88, textSize: 34 })
512
+ ] }) : null
513
+ ] });
514
+ }
515
+ var styles4 = StyleSheet5.create({
516
+ surface: {
517
+ flex: 1,
518
+ minHeight: 80,
519
+ width: "100%",
520
+ height: "100%",
521
+ overflow: "hidden",
522
+ backgroundColor: Theme.colors.stageBackground,
523
+ borderRadius: Theme.radius.md,
524
+ position: "relative"
525
+ },
526
+ fallback: {
527
+ ...StyleSheet5.absoluteFillObject,
528
+ alignItems: "center",
529
+ justifyContent: "center",
530
+ width: "100%",
531
+ height: "100%"
532
+ }
533
+ });
534
+
535
+ // src/components/native-space-view/native-space-page-store.ts
536
+ function createSpacePageStore() {
537
+ let page = 0;
538
+ const listeners = /* @__PURE__ */ new Set();
539
+ return {
540
+ getSnapshot: () => page,
541
+ subscribe: (listener) => {
542
+ listeners.add(listener);
543
+ return () => listeners.delete(listener);
544
+ },
545
+ setPage: (nextPage) => {
546
+ const nextPageIndex = Math.max(0, nextPage);
547
+ if (nextPageIndex === page) {
548
+ return;
549
+ }
550
+ page = nextPageIndex;
551
+ for (const listener of listeners) {
552
+ listener();
553
+ }
554
+ },
555
+ clampToPageCount: (pageCount) => {
556
+ const nextPageIndex = Math.min(page, Math.max(0, pageCount - 1));
557
+ if (nextPageIndex === page) {
558
+ return;
559
+ }
560
+ page = nextPageIndex;
561
+ for (const listener of listeners) {
562
+ listener();
563
+ }
564
+ }
565
+ };
566
+ }
567
+
568
+ // src/components/native-space-view/native-space-grid-keys.ts
569
+ function nativeSpaceGridKey(prefix, participants) {
570
+ const participantIds = participants.map((participant) => participant.id).join("|");
571
+ return `${prefix}-${participantIds || "empty"}`;
572
+ }
573
+
574
+ // src/components/native-space-view/SpaceGrid.android.tsx
575
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
576
+ function buildWideParticipantRows(participants, columnCount) {
577
+ if (participants.length === 0) {
578
+ return [];
579
+ }
580
+ const rows = [];
581
+ for (let index = 0; index < participants.length; index += columnCount) {
582
+ rows.push(participants.slice(index, index + columnCount));
583
+ }
584
+ return rows;
585
+ }
586
+ function SpaceGridAndroid({ participants, gridPages }) {
587
+ const theme = useNativeTheme();
588
+ const { width, height } = useWindowDimensions();
589
+ const isTablet = width >= 768;
590
+ const pageStoreRef = useRef(null);
591
+ const pageStore = pageStoreRef.current ?? (pageStoreRef.current = createSpacePageStore());
592
+ const finalPages = useMemo7(() => {
593
+ if (!isTablet) {
594
+ return gridPages;
595
+ }
596
+ const perPage = 6;
597
+ const pages = [];
598
+ for (let index = 0; index < participants.length; index += perPage) {
599
+ pages.push(participants.slice(index, index + perPage));
600
+ }
601
+ return pages;
602
+ }, [gridPages, isTablet, participants]);
603
+ const requestedPage = useSyncExternalStore2(pageStore.subscribe, pageStore.getSnapshot, pageStore.getSnapshot);
604
+ const activePage = Math.min(requestedPage, Math.max(0, finalPages.length - 1));
605
+ const activePageKey = nativeSpaceGridKey("indicator", finalPages[activePage] ?? []);
606
+ const clampPageRef = useCallback3(
607
+ (node) => {
608
+ if (node !== null) {
609
+ pageStore.clampToPageCount(finalPages.length);
610
+ }
611
+ },
612
+ [finalPages.length, pageStore]
613
+ );
614
+ if (participants.length === 0) {
615
+ return /* @__PURE__ */ jsxs4(View6, { ref: clampPageRef, style: [styles5.emptyState, { backgroundColor: theme.colors.darkCanvas }], children: [
616
+ /* @__PURE__ */ jsx9(Text2, { style: [styles5.emptyEyebrow, { color: theme.colors.primary }], children: "Space ready" }),
617
+ /* @__PURE__ */ jsx9(Text2, { style: [styles5.emptyTitle, { color: theme.colors.foreground }], children: "You're the first one here" }),
618
+ /* @__PURE__ */ jsx9(Text2, { style: [styles5.emptyCopy, { color: theme.colors.mutedForeground }], children: "Others will appear when they join. Invite someone to get started." })
619
+ ] });
620
+ }
621
+ if (participants.length === 1) {
622
+ return /* @__PURE__ */ jsx9(View6, { ref: clampPageRef, style: styles5.singleTile, children: /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[0] }) });
623
+ }
624
+ if (!isTablet && participants.length <= 4) {
625
+ if (participants.length === 2) {
626
+ return /* @__PURE__ */ jsx9(View6, { ref: clampPageRef, style: styles5.compactTwoUp, children: participants.map((participant) => /* @__PURE__ */ jsx9(ParticipantTile, { participant }, participant.id)) });
627
+ }
628
+ if (participants.length === 3) {
629
+ return /* @__PURE__ */ jsxs4(View6, { ref: clampPageRef, style: styles5.compactThree, children: [
630
+ /* @__PURE__ */ jsx9(View6, { style: styles5.compactThreeTop, children: /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[0] }) }),
631
+ /* @__PURE__ */ jsxs4(View6, { style: styles5.compactThreeBottom, children: [
632
+ /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[1] }),
633
+ /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[2] })
634
+ ] })
635
+ ] });
636
+ }
637
+ if (participants.length === 4) {
638
+ return /* @__PURE__ */ jsxs4(View6, { ref: clampPageRef, style: styles5.compactFour, children: [
639
+ /* @__PURE__ */ jsxs4(View6, { style: styles5.gridRow, children: [
640
+ /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[0] }),
641
+ /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[1] })
642
+ ] }),
643
+ /* @__PURE__ */ jsxs4(View6, { style: styles5.gridRow, children: [
644
+ /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[2] }),
645
+ /* @__PURE__ */ jsx9(ParticipantTile, { participant: participants[3] })
646
+ ] })
647
+ ] });
648
+ }
649
+ }
650
+ return /* @__PURE__ */ jsxs4(View6, { ref: clampPageRef, style: styles5.pagedContainer, children: [
651
+ /* @__PURE__ */ jsx9(
652
+ FlatList,
653
+ {
654
+ data: finalPages,
655
+ horizontal: true,
656
+ keyExtractor: (page) => nativeSpaceGridKey("page", page),
657
+ onMomentumScrollEnd: (event) => {
658
+ const measuredPageWidth = Math.max(1, event.nativeEvent.layoutMeasurement.width);
659
+ pageStore.setPage(Math.round(event.nativeEvent.contentOffset.x / measuredPageWidth));
660
+ },
661
+ pagingEnabled: true,
662
+ snapToInterval: width,
663
+ snapToAlignment: "center",
664
+ decelerationRate: "fast",
665
+ disableIntervalMomentum: true,
666
+ scrollEventThrottle: 16,
667
+ removeClippedSubviews: false,
668
+ showsHorizontalScrollIndicator: false,
669
+ windowSize: 3,
670
+ renderItem: ({ item: page }) => {
671
+ const columns = isTablet ? width > height ? 3 : 2 : 2;
672
+ const rows = buildWideParticipantRows(page, columns);
673
+ return /* @__PURE__ */ jsx9(View6, { style: [styles5.page, { width }], children: /* @__PURE__ */ jsxs4(View6, { style: styles5.gridContainer, children: [
674
+ rows.map((row) => /* @__PURE__ */ jsxs4(View6, { style: styles5.gridRow, children: [
675
+ row.map((participant) => /* @__PURE__ */ jsx9(ParticipantTile, { participant }, participant.id)),
676
+ row.length < columns && Array.from({ length: columns - row.length }, (_, fillerSlot) => fillerSlot + row.length).map((slot) => /* @__PURE__ */ jsx9(View6, { style: [styles5.gridTile, { backgroundColor: theme.colors.transparent }] }, nativeSpaceGridKey(`filler-${slot}`, row)))
677
+ ] }, nativeSpaceGridKey("row", row))),
678
+ isTablet && rows.length < (width > height ? 2 : 3) ? /* @__PURE__ */ jsx9(View6, { style: { flex: (width > height ? 2 : 3) - rows.length } }) : null
679
+ ] }) });
680
+ }
681
+ }
682
+ ),
683
+ finalPages.length > 1 ? /* @__PURE__ */ jsx9(View6, { style: styles5.pageIndicators, children: finalPages.map((page) => /* @__PURE__ */ jsx9(View6, { style: [styles5.pageIndicator, { backgroundColor: theme.colors.mutedForeground }, nativeSpaceGridKey("indicator", page) === activePageKey && { backgroundColor: theme.colors.primary }] }, nativeSpaceGridKey("indicator", page))) }) : null
684
+ ] });
685
+ }
686
+ function ParticipantTile({ participant, width, height }) {
687
+ const theme = useNativeTheme();
688
+ return /* @__PURE__ */ jsxs4(View6, { style: [styles5.tile, { backgroundColor: theme.colors.tileBackground, borderColor: theme.colors.border }, width !== void 0 && { width }, height !== void 0 && { height }], children: [
689
+ /* @__PURE__ */ jsx9(MediaView, { participant, track: participant.videoTrack ?? null }),
690
+ /* @__PURE__ */ jsxs4(View6, { style: [styles5.identityPuck, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border, shadowColor: theme.colors.darkCanvas }], children: [
691
+ /* @__PURE__ */ jsx9(Text2, { style: [styles5.participantName, { color: theme.colors.foreground }], numberOfLines: 1, children: participant.displayName || "Participant" }),
692
+ !participant.audioEnabled && /* @__PURE__ */ jsx9(View6, { style: styles5.muteDot, children: /* @__PURE__ */ jsx9(HugeiconsIcon, { icon: MicOff01Icon, size: 10, color: theme.colors.primaryForeground }) })
693
+ ] })
694
+ ] });
695
+ }
696
+ var styles5 = StyleSheet6.create({
697
+ emptyState: {
698
+ flex: 1,
699
+ alignItems: "center",
700
+ justifyContent: "center",
701
+ paddingHorizontal: Theme.spacing["3xl"],
702
+ gap: Theme.spacing.sm
703
+ },
704
+ emptyEyebrow: {
705
+ ...Theme.typography.eyebrow,
706
+ color: Theme.colors.primary
707
+ },
708
+ emptyTitle: {
709
+ ...Theme.typography.heading,
710
+ color: Theme.colors.foreground
711
+ },
712
+ emptyCopy: {
713
+ ...Theme.typography.body,
714
+ color: Theme.colors.mutedForeground,
715
+ textAlign: "center"
716
+ },
717
+ singleTile: {
718
+ flex: 1,
719
+ padding: 10
720
+ },
721
+ compactTwoUp: {
722
+ flex: 1,
723
+ gap: 10,
724
+ padding: 10
725
+ },
726
+ compactThree: {
727
+ flex: 1,
728
+ gap: 10,
729
+ padding: 10
730
+ },
731
+ compactThreeTop: {
732
+ flex: 3,
733
+ minHeight: 0,
734
+ overflow: "hidden"
735
+ },
736
+ compactThreeBottom: {
737
+ flex: 2,
738
+ flexDirection: "row",
739
+ gap: 10,
740
+ minHeight: 0
741
+ },
742
+ compactFour: {
743
+ flex: 1,
744
+ gap: 10,
745
+ padding: 10
746
+ },
747
+ pagedContainer: {
748
+ flex: 1,
749
+ width: "100%",
750
+ paddingBottom: 20
751
+ },
752
+ page: {
753
+ flex: 1
754
+ },
755
+ gridContainer: {
756
+ flex: 1,
757
+ gap: 10,
758
+ paddingHorizontal: 12,
759
+ paddingVertical: 10
760
+ },
761
+ gridRow: {
762
+ flex: 1,
763
+ flexDirection: "row",
764
+ gap: 10
765
+ },
766
+ gridTile: {
767
+ flex: 1
768
+ },
769
+ pageIndicators: {
770
+ flexDirection: "row",
771
+ alignSelf: "center",
772
+ gap: 6,
773
+ paddingTop: 4
774
+ },
775
+ pageIndicator: {
776
+ width: 6,
777
+ height: 6,
778
+ borderRadius: 3,
779
+ backgroundColor: Theme.colors.whiteOverlay20
780
+ },
781
+ pageIndicatorActive: {
782
+ width: 18,
783
+ backgroundColor: Theme.colors.primary
784
+ },
785
+ tile: {
786
+ borderRadius: 32,
787
+ overflow: "hidden",
788
+ backgroundColor: Theme.colors.nearDarkSurface,
789
+ borderWidth: 1,
790
+ borderColor: Theme.colors.whiteOverlay08,
791
+ flex: 1
792
+ },
793
+ identityPuck: {
794
+ position: "absolute",
795
+ left: 16,
796
+ bottom: 16,
797
+ flexDirection: "row",
798
+ alignItems: "center",
799
+ backgroundColor: Theme.colors.chromeOverlay82,
800
+ paddingHorizontal: 14,
801
+ paddingVertical: 8,
802
+ borderRadius: 20,
803
+ gap: 8,
804
+ borderWidth: 1,
805
+ borderColor: Theme.colors.whiteOverlay12,
806
+ shadowColor: Theme.colors.darkCanvas,
807
+ shadowOffset: { width: 0, height: 4 },
808
+ shadowOpacity: 0.3,
809
+ shadowRadius: 8
810
+ },
811
+ participantName: {
812
+ color: Theme.colors.onDark,
813
+ fontSize: 13,
814
+ fontWeight: "800",
815
+ maxWidth: 140
816
+ },
817
+ muteDot: {
818
+ width: 20,
819
+ height: 20,
820
+ borderRadius: 10,
821
+ backgroundColor: Theme.colors.error,
822
+ alignItems: "center",
823
+ justifyContent: "center"
824
+ }
825
+ });
826
+
827
+ // src/components/native-space-view/SpaceBottomDock.android.tsx
828
+ import CallEnd01Icon from "@hugeicons/core-free-icons/dist/esm/CallEnd01Icon";
829
+ import Chat01Icon from "@hugeicons/core-free-icons/dist/esm/Chat01Icon";
830
+ import Mic01Icon from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
831
+ import MicOff01Icon2 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
832
+ import MoreHorizontalIcon from "@hugeicons/core-free-icons/dist/esm/MoreHorizontalIcon";
833
+ import Video01Icon from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
834
+ import VideoOffIcon from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
835
+ import { HugeiconsIcon as HugeiconsIcon2 } from "@hugeicons/react-native";
836
+ import { Platform as Platform3, Pressable as Pressable2, StyleSheet as StyleSheet7, Text as Text3, View as View7 } from "react-native";
837
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
838
+ function SpaceBottomDockAndroid({ simulatorMediaDisabled, isMuted, isCameraOff, unreadChatCount, onToggleAudio, onToggleVideo, onOpenChat, onOpenMore, onLeave }) {
839
+ const theme = useNativeTheme();
840
+ return /* @__PURE__ */ jsx10(View7, { style: [styles6.bottomDock, { backgroundColor: theme.colors.darkCanvas, borderColor: theme.colors.border }], children: /* @__PURE__ */ jsxs5(View7, { style: styles6.controlPill, children: [
841
+ /* @__PURE__ */ jsx10(
842
+ Pressable2,
843
+ {
844
+ disabled: simulatorMediaDisabled,
845
+ onPress: onToggleAudio,
846
+ style: ({ pressed }) => [styles6.controlButton, { backgroundColor: isMuted ? theme.colors.error : theme.colors.controlsBackground }, simulatorMediaDisabled && styles6.controlButtonDisabled, pressed && styles6.controlButtonPressed],
847
+ children: /* @__PURE__ */ jsx10(HugeiconsIcon2, { color: isMuted ? theme.colors.onDark : theme.colors.primary, icon: isMuted ? MicOff01Icon2 : Mic01Icon, size: 22 })
848
+ }
849
+ ),
850
+ /* @__PURE__ */ jsx10(
851
+ Pressable2,
852
+ {
853
+ disabled: simulatorMediaDisabled,
854
+ onPress: onToggleVideo,
855
+ style: ({ pressed }) => [styles6.controlButton, { backgroundColor: isCameraOff ? theme.colors.error : theme.colors.controlsBackground }, simulatorMediaDisabled && styles6.controlButtonDisabled, pressed && styles6.controlButtonPressed],
856
+ children: /* @__PURE__ */ jsx10(HugeiconsIcon2, { color: isCameraOff ? theme.colors.onDark : theme.colors.primary, icon: isCameraOff ? VideoOffIcon : Video01Icon, size: 22 })
857
+ }
858
+ ),
859
+ onOpenChat ? /* @__PURE__ */ jsxs5(Pressable2, { onPress: onOpenChat, style: ({ pressed }) => [styles6.controlButton, { backgroundColor: theme.colors.controlsBackground }, pressed && styles6.controlButtonPressed], children: [
860
+ /* @__PURE__ */ jsx10(HugeiconsIcon2, { color: theme.colors.onDark, icon: Chat01Icon, size: 22 }),
861
+ unreadChatCount > 0 ? /* @__PURE__ */ jsx10(View7, { style: [styles6.controlBadge, { backgroundColor: theme.colors.primary, borderColor: theme.colors.darkCanvas }], children: /* @__PURE__ */ jsx10(Text3, { style: [styles6.controlBadgeText, { color: theme.colors.primaryForeground }], children: unreadChatCount > 9 ? "9+" : String(unreadChatCount) }) }) : null
862
+ ] }) : null,
863
+ /* @__PURE__ */ jsx10(Pressable2, { onPress: onOpenMore, style: ({ pressed }) => [styles6.controlButton, { backgroundColor: theme.colors.controlsBackground }, pressed && styles6.controlButtonPressed], children: /* @__PURE__ */ jsx10(HugeiconsIcon2, { color: theme.colors.onDark, icon: MoreHorizontalIcon, size: 22 }) }),
864
+ /* @__PURE__ */ jsx10(Pressable2, { onPress: onLeave, style: ({ pressed }) => [styles6.controlButton, styles6.controlButtonEndCall, { backgroundColor: theme.colors.error }, pressed && styles6.controlButtonPressed], children: /* @__PURE__ */ jsx10(HugeiconsIcon2, { color: theme.colors.onDark, icon: CallEnd01Icon, size: 22 }) })
865
+ ] }) });
866
+ }
867
+ var styles6 = StyleSheet7.create({
868
+ bottomDock: {
869
+ paddingTop: 20,
870
+ paddingBottom: Platform3.OS === "ios" ? 38 : 24,
871
+ paddingHorizontal: 24,
872
+ backgroundColor: Theme.colors.darkCanvas,
873
+ borderTopWidth: 1,
874
+ borderColor: Theme.colors.whiteOverlay06,
875
+ width: "100%"
876
+ },
877
+ controlPill: {
878
+ flexDirection: "row",
879
+ alignItems: "center",
880
+ justifyContent: "space-between",
881
+ width: "100%"
882
+ },
883
+ controlButton: {
884
+ width: 48,
885
+ height: 48,
886
+ borderRadius: 24,
887
+ alignItems: "center",
888
+ justifyContent: "center",
889
+ backgroundColor: Theme.colors.whiteOverlay08
890
+ },
891
+ controlButtonDisabled: {
892
+ opacity: 0.45
893
+ },
894
+ controlButtonPressed: {
895
+ opacity: 0.7,
896
+ transform: [{ scale: 0.92 }]
897
+ },
898
+ controlButtonDanger: {
899
+ backgroundColor: Theme.colors.dangerStrong
900
+ },
901
+ controlButtonEndCall: {
902
+ backgroundColor: Theme.colors.error,
903
+ width: 68,
904
+ borderRadius: 18
905
+ },
906
+ controlBadge: {
907
+ position: "absolute",
908
+ top: -2,
909
+ right: -2,
910
+ minWidth: 18,
911
+ height: 18,
912
+ borderRadius: 9,
913
+ backgroundColor: Theme.colors.primary,
914
+ alignItems: "center",
915
+ justifyContent: "center",
916
+ paddingHorizontal: 4,
917
+ borderWidth: 2,
918
+ borderColor: Theme.colors.darkCanvas
919
+ },
920
+ controlBadgeText: {
921
+ color: Theme.colors.onDark,
922
+ fontSize: 10,
923
+ fontWeight: "800"
924
+ }
925
+ });
926
+
927
+ // src/components/native-space-view/SpaceActionMenu.tsx
928
+ import { Modal as Modal2, Pressable as Pressable3, StyleSheet as StyleSheet8, Text as Text4, View as View8 } from "react-native";
929
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
930
+ function SpaceActionMenu({ controller }) {
931
+ const theme = useNativeTheme();
932
+ const actions = [
933
+ ...controller.canInvite ? [{ label: "Invite participants", onPress: controller.handleInviteParticipants }] : [],
934
+ ...controller.canParticipants ? [{ label: "Participants", onPress: () => controller.openPanel("participants") }] : [],
935
+ ...controller.canChat ? [{ label: "Chat", onPress: () => controller.openPanel("chat") }] : [],
936
+ ...controller.canScreenShare ? [{ label: controller.screenShare.isLocalSharing ? "Stop presenting" : "Present screen", onPress: controller.toggleScreenShare }] : [],
937
+ ...controller.canHandRaise ? [{ label: controller.handRaised ? "Lower hand" : "Raise hand", onPress: controller.toggleHand }] : [],
938
+ ...controller.canWhiteboard ? [{ label: controller.whiteboard.isOpen ? "Close whiteboard" : "Open whiteboard", onPress: controller.whiteboard.toggle }] : [],
939
+ ...controller.canReactions ? [
940
+ {
941
+ label: "Reactions",
942
+ onPress: () => {
943
+ controller.setActionsOpen(false);
944
+ controller.setReactionPickerOpen(true);
945
+ }
946
+ }
947
+ ] : [],
948
+ ...controller.canSettings ? [{ label: "Settings", onPress: () => controller.openPanel("settings") }] : [],
949
+ ...["grid", "focus", "presentation"].map((layout) => ({
950
+ label: `${layout === "grid" ? "Grid" : layout === "focus" ? "Focus" : "Presentation"} layout${controller.layout.layout === layout ? " (selected)" : ""}`,
951
+ onPress: () => {
952
+ controller.layout.setLayout(layout);
953
+ controller.setActionsOpen(false);
954
+ }
955
+ }))
956
+ ];
957
+ return /* @__PURE__ */ jsx11(Modal2, { animationType: "slide", onRequestClose: () => controller.setActionsOpen(false), transparent: true, visible: controller.actionsOpen, children: /* @__PURE__ */ jsx11(Pressable3, { onPress: () => controller.setActionsOpen(false), style: styles7.backdrop, children: /* @__PURE__ */ jsxs6(View8, { style: [styles7.sheet, { backgroundColor: theme.colors.background }], children: [
958
+ /* @__PURE__ */ jsx11(Text4, { style: [styles7.title, { color: theme.colors.foreground }], children: "Space actions" }),
959
+ actions.map((action) => /* @__PURE__ */ jsx11(Pressable3, { onPress: action.onPress, style: ({ pressed }) => [styles7.action, { backgroundColor: theme.colors.card }, pressed && styles7.pressed], children: /* @__PURE__ */ jsx11(Text4, { style: [styles7.actionText, { color: theme.colors.foreground }], children: action.label }) }, action.label)),
960
+ /* @__PURE__ */ jsx11(Pressable3, { onPress: controller.handleLeave, style: [styles7.action, styles7.dangerAction, { backgroundColor: theme.colors.card, borderColor: theme.colors.error }], children: /* @__PURE__ */ jsx11(Text4, { style: [styles7.actionText, styles7.dangerText, { color: theme.colors.error }], children: "Leave space" }) })
961
+ ] }) }) });
962
+ }
963
+ function selectSpaceReaction(controller, reaction) {
964
+ controller.sendReaction(reaction);
965
+ }
966
+ var styles7 = StyleSheet8.create({
967
+ backdrop: { flex: 1, justifyContent: "flex-end", backgroundColor: Theme.colors.darkOverlay55 },
968
+ sheet: {
969
+ gap: 8,
970
+ borderTopLeftRadius: 24,
971
+ borderTopRightRadius: 24,
972
+ backgroundColor: Theme.colors.background,
973
+ padding: 24,
974
+ paddingBottom: 40
975
+ },
976
+ title: { ...Theme.typography.title, color: Theme.colors.foreground },
977
+ action: { borderRadius: 14, backgroundColor: Theme.colors.card, padding: 16 },
978
+ actionText: { color: Theme.colors.foreground, fontSize: 16, fontWeight: "600" },
979
+ dangerAction: { marginTop: 8, borderWidth: 1, borderColor: Theme.colors.error },
980
+ dangerText: { color: Theme.colors.error, fontWeight: "700" },
981
+ pressed: { opacity: 0.65 }
982
+ });
983
+
984
+ // src/components/native-space-view/SpaceStage.android.tsx
985
+ import ComputerScreenShareIcon from "@hugeicons/core-free-icons/dist/esm/ComputerScreenShareIcon";
986
+ import MicOff01Icon3 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
987
+ import Presentation01Icon from "@hugeicons/core-free-icons/dist/esm/Presentation01Icon";
988
+ import WavingHand01Icon from "@hugeicons/core-free-icons/dist/esm/WavingHand01Icon";
989
+ import { HugeiconsIcon as HugeiconsIcon3 } from "@hugeicons/react-native";
990
+ import { FlatList as FlatList2, StyleSheet as StyleSheet9, Text as Text5, View as View9 } from "react-native";
991
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
992
+ function getParticipantStripTrack(participant) {
993
+ return participant.videoTrack ?? null;
994
+ }
995
+ function StageSurface({ children }) {
996
+ const theme = useNativeTheme();
997
+ return /* @__PURE__ */ jsx12(View9, { style: [styles8.surface, { backgroundColor: theme.colors.stageBackground }], children });
998
+ }
999
+ function InfoChip({ icon, label, align = "left" }) {
1000
+ const theme = useNativeTheme();
1001
+ return /* @__PURE__ */ jsxs7(View9, { style: [styles8.infoChip, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }, align === "right" ? styles8.infoChipRight : styles8.infoChipLeft], children: [
1002
+ /* @__PURE__ */ jsx12(HugeiconsIcon3, { color: theme.colors.foreground, icon, size: 14 }),
1003
+ /* @__PURE__ */ jsx12(Text5, { style: [styles8.infoChipText, { color: theme.colors.foreground }], children: label })
1004
+ ] });
1005
+ }
1006
+ function NativeWhiteboardPlaceholder({ whiteboard }) {
1007
+ return /* @__PURE__ */ jsxs7(StageSurface, { children: [
1008
+ /* @__PURE__ */ jsx12(GradientSurface, { angle: "diagonal", borderRadius: 24, opacity: 0.6, participantId: "whiteboard-stage" }),
1009
+ /* @__PURE__ */ jsxs7(View9, { style: styles8.placeholderCenter, children: [
1010
+ /* @__PURE__ */ jsx12(View9, { style: styles8.presentingIconCircle, children: /* @__PURE__ */ jsx12(HugeiconsIcon3, { color: Theme.colors.primary, icon: Presentation01Icon, size: 32 }) }),
1011
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.placeholderEyebrow, children: "SHARED CANVAS" }),
1012
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.placeholderTitle, children: "Whiteboard active" }),
1013
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.placeholderCopy, children: whiteboard.canDraw ? "Collaborative board is open." : "Board is open in view-only mode." })
1014
+ ] })
1015
+ ] });
1016
+ }
1017
+ function NativeLocalSharePlaceholder() {
1018
+ return /* @__PURE__ */ jsxs7(StageSurface, { children: [
1019
+ /* @__PURE__ */ jsx12(GradientSurface, { angle: "diagonal", borderRadius: 24, opacity: 0.4, participantId: "local-presenting" }),
1020
+ /* @__PURE__ */ jsxs7(View9, { style: styles8.placeholderCenter, children: [
1021
+ /* @__PURE__ */ jsx12(View9, { style: styles8.presentingIconCircle, children: /* @__PURE__ */ jsx12(HugeiconsIcon3, { color: Theme.colors.primary, icon: ComputerScreenShareIcon, size: 32 }) }),
1022
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.placeholderEyebrow, children: "YOU ARE PRESENTING" }),
1023
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.placeholderTitle, children: "Screen sharing active" }),
1024
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.placeholderCopy, children: "Your preview is hidden here to prevent an infinite mirror effect. Everyone else can see your screen." })
1025
+ ] })
1026
+ ] });
1027
+ }
1028
+ function NativeParticipantStrip({ participants, vertical }) {
1029
+ return /* @__PURE__ */ jsx12(
1030
+ FlatList2,
1031
+ {
1032
+ contentContainerStyle: [styles8.stripContent, vertical ? styles8.stripVertical : styles8.stripHorizontal],
1033
+ data: participants,
1034
+ horizontal: !vertical,
1035
+ initialNumToRender: vertical ? 4 : 5,
1036
+ keyExtractor: (participant, index) => `${participant.id}-${index}`,
1037
+ maxToRenderPerBatch: vertical ? 5 : 6,
1038
+ removeClippedSubviews: true,
1039
+ renderItem: ({ item: participant }) => /* @__PURE__ */ jsx12(View9, { style: [styles8.stripTile, vertical ? styles8.stripTileVertical : styles8.stripTileHorizontal], children: /* @__PURE__ */ jsx12(MediaView, { emphasizeMuted: true, participant, track: getParticipantStripTrack(participant) }) }),
1040
+ showsHorizontalScrollIndicator: false,
1041
+ showsVerticalScrollIndicator: false,
1042
+ windowSize: 4
1043
+ }
1044
+ );
1045
+ }
1046
+ function SpaceStageAndroid({ layoutMode, isCompactViewport, primaryContent, screenSharer, screenShareTrack, stripParticipants, selfName, isMuted, handRaised, raisedHandCount, activeReactions, whiteboard }) {
1047
+ const theme = useNativeTheme();
1048
+ const verticalStrip = !isCompactViewport && layoutMode === "focus";
1049
+ let primaryStage;
1050
+ if (primaryContent === "whiteboard") {
1051
+ primaryStage = /* @__PURE__ */ jsx12(NativeWhiteboardPlaceholder, { whiteboard });
1052
+ } else if (primaryContent === "screen-share-placeholder") {
1053
+ primaryStage = /* @__PURE__ */ jsx12(NativeLocalSharePlaceholder, {});
1054
+ } else if (primaryContent === "split") {
1055
+ primaryStage = /* @__PURE__ */ jsxs7(View9, { style: styles8.splitStage, children: [
1056
+ /* @__PURE__ */ jsx12(View9, { style: styles8.splitPanel, children: /* @__PURE__ */ jsx12(StageSurface, { children: /* @__PURE__ */ jsx12(MediaView, { participant: screenSharer, track: screenShareTrack, objectFit: "contain" }) }) }),
1057
+ /* @__PURE__ */ jsx12(View9, { style: styles8.splitPanel, children: /* @__PURE__ */ jsx12(NativeWhiteboardPlaceholder, { whiteboard }) })
1058
+ ] });
1059
+ } else {
1060
+ primaryStage = /* @__PURE__ */ jsx12(StageSurface, { children: /* @__PURE__ */ jsx12(MediaView, { participant: screenSharer, track: screenShareTrack, label: screenSharer?.displayName || "Participant", objectFit: "contain" }) });
1061
+ }
1062
+ return /* @__PURE__ */ jsxs7(View9, { style: [styles8.container, { backgroundColor: theme.colors.darkCanvas }, verticalStrip && styles8.containerVertical], children: [
1063
+ /* @__PURE__ */ jsxs7(View9, { style: styles8.primaryFrame, children: [
1064
+ primaryStage,
1065
+ raisedHandCount > 0 ? /* @__PURE__ */ jsx12(InfoChip, { icon: WavingHand01Icon, label: raisedHandCount === 1 ? "1 hand raised" : `${raisedHandCount} hands raised` }) : null,
1066
+ activeReactions.length > 0 ? /* @__PURE__ */ jsx12(View9, { style: styles8.reactionRail, children: activeReactions.map((reaction, index) => /* @__PURE__ */ jsxs7(View9, { style: [styles8.reactionBubble, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }], children: [
1067
+ /* @__PURE__ */ jsx12(Text5, { style: styles8.reactionEmoji, children: reaction.emoji }),
1068
+ /* @__PURE__ */ jsx12(Text5, { numberOfLines: 1, style: [styles8.reactionName, { color: theme.colors.foreground }], children: reaction.participantName })
1069
+ ] }, `${reaction.id}-${index}`)) }) : null,
1070
+ /* @__PURE__ */ jsxs7(View9, { style: [styles8.identityBar, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }], children: [
1071
+ /* @__PURE__ */ jsx12(Text5, { style: [styles8.nameLabel, { color: theme.colors.foreground }], numberOfLines: 1, children: selfName }),
1072
+ isMuted ? /* @__PURE__ */ jsx12(View9, { style: styles8.muteIndicator, children: /* @__PURE__ */ jsx12(HugeiconsIcon3, { color: theme.colors.primaryForeground, icon: MicOff01Icon3, size: 10 }) }) : null,
1073
+ handRaised ? /* @__PURE__ */ jsx12(View9, { style: styles8.handIndicator, children: /* @__PURE__ */ jsx12(HugeiconsIcon3, { color: theme.colors.primaryForeground, icon: WavingHand01Icon, size: 10 }) }) : null
1074
+ ] })
1075
+ ] }),
1076
+ stripParticipants.length > 0 ? /* @__PURE__ */ jsx12(View9, { style: [styles8.stripShell, verticalStrip ? styles8.stripShellVertical : styles8.stripShellHorizontal], children: /* @__PURE__ */ jsx12(NativeParticipantStrip, { participants: stripParticipants, vertical: verticalStrip }) }) : null
1077
+ ] });
1078
+ }
1079
+ var styles8 = StyleSheet9.create({
1080
+ container: {
1081
+ flex: 1,
1082
+ width: "100%",
1083
+ paddingHorizontal: 12
1084
+ },
1085
+ containerVertical: {
1086
+ flexDirection: "row"
1087
+ },
1088
+ primaryFrame: {
1089
+ flex: 1,
1090
+ minHeight: 0,
1091
+ width: "100%",
1092
+ marginBottom: 12
1093
+ },
1094
+ surface: {
1095
+ flex: 1,
1096
+ backgroundColor: Theme.colors.stageBackground,
1097
+ width: "100%",
1098
+ borderRadius: 24,
1099
+ overflow: "hidden"
1100
+ },
1101
+ splitStage: {
1102
+ flex: 1,
1103
+ flexDirection: "row",
1104
+ gap: 10
1105
+ },
1106
+ splitPanel: {
1107
+ flex: 1
1108
+ },
1109
+ placeholderCenter: {
1110
+ flex: 1,
1111
+ alignItems: "center",
1112
+ justifyContent: "center",
1113
+ paddingHorizontal: Theme.spacing["3xl"],
1114
+ gap: 12
1115
+ },
1116
+ presentingIconCircle: {
1117
+ width: 80,
1118
+ height: 80,
1119
+ borderRadius: 40,
1120
+ alignItems: "center",
1121
+ justifyContent: "center",
1122
+ backgroundColor: Theme.colors.whiteOverlay06,
1123
+ borderWidth: 1,
1124
+ borderColor: Theme.colors.whiteOverlay12,
1125
+ marginBottom: 8
1126
+ },
1127
+ placeholderEyebrow: {
1128
+ fontSize: 11,
1129
+ fontWeight: "800",
1130
+ color: Theme.colors.primary,
1131
+ letterSpacing: 1
1132
+ },
1133
+ placeholderTitle: {
1134
+ fontSize: 22,
1135
+ fontWeight: "800",
1136
+ color: Theme.colors.onDark,
1137
+ textAlign: "center",
1138
+ letterSpacing: -0.5
1139
+ },
1140
+ placeholderCopy: {
1141
+ fontSize: 14,
1142
+ color: Theme.colors.whiteOverlay50,
1143
+ textAlign: "center",
1144
+ lineHeight: 20,
1145
+ paddingHorizontal: 20
1146
+ },
1147
+ infoChip: {
1148
+ position: "absolute",
1149
+ top: 20,
1150
+ flexDirection: "row",
1151
+ alignItems: "center",
1152
+ gap: 5,
1153
+ backgroundColor: Theme.colors.darkOverlay50,
1154
+ paddingHorizontal: 10,
1155
+ paddingVertical: 6,
1156
+ borderRadius: 999,
1157
+ borderWidth: 1,
1158
+ borderColor: Theme.colors.whiteOverlay06
1159
+ },
1160
+ infoChipLeft: {
1161
+ left: 20
1162
+ },
1163
+ infoChipRight: {
1164
+ right: 20
1165
+ },
1166
+ infoChipText: {
1167
+ color: Theme.colors.onDark,
1168
+ fontSize: 12,
1169
+ fontWeight: "700"
1170
+ },
1171
+ reactionRail: {
1172
+ position: "absolute",
1173
+ right: 16,
1174
+ bottom: 24,
1175
+ gap: 8,
1176
+ maxWidth: 180
1177
+ },
1178
+ reactionBubble: {
1179
+ flexDirection: "row",
1180
+ alignItems: "center",
1181
+ gap: 8,
1182
+ backgroundColor: Theme.colors.darkOverlay45,
1183
+ borderRadius: 999,
1184
+ paddingHorizontal: 12,
1185
+ paddingVertical: 8,
1186
+ borderWidth: 1,
1187
+ borderColor: Theme.colors.whiteOverlay08
1188
+ },
1189
+ reactionEmoji: {
1190
+ fontSize: 16
1191
+ },
1192
+ reactionName: {
1193
+ flex: 1,
1194
+ color: Theme.colors.onDark,
1195
+ fontSize: 12,
1196
+ fontWeight: "700"
1197
+ },
1198
+ identityBar: {
1199
+ position: "absolute",
1200
+ left: 20,
1201
+ bottom: 20,
1202
+ flexDirection: "row",
1203
+ alignItems: "center",
1204
+ gap: 8,
1205
+ backgroundColor: Theme.colors.darkOverlay50,
1206
+ paddingHorizontal: 12,
1207
+ paddingVertical: 8,
1208
+ borderRadius: 999,
1209
+ borderWidth: 1,
1210
+ borderColor: Theme.colors.whiteOverlay06,
1211
+ maxWidth: "70%"
1212
+ },
1213
+ nameLabel: {
1214
+ color: Theme.colors.onDark,
1215
+ fontSize: 12,
1216
+ fontWeight: "700"
1217
+ },
1218
+ muteIndicator: {
1219
+ width: 18,
1220
+ height: 18,
1221
+ borderRadius: 9,
1222
+ backgroundColor: Theme.colors.dangerStrong,
1223
+ alignItems: "center",
1224
+ justifyContent: "center"
1225
+ },
1226
+ handIndicator: {
1227
+ width: 18,
1228
+ height: 18,
1229
+ borderRadius: 9,
1230
+ backgroundColor: Theme.colors.warning,
1231
+ alignItems: "center",
1232
+ justifyContent: "center"
1233
+ },
1234
+ stripShell: {
1235
+ minHeight: 96
1236
+ },
1237
+ stripShellHorizontal: {
1238
+ height: 110
1239
+ },
1240
+ stripShellVertical: {
1241
+ width: 110,
1242
+ marginLeft: 12
1243
+ },
1244
+ stripContent: {
1245
+ gap: 10
1246
+ },
1247
+ stripHorizontal: {
1248
+ paddingBottom: 8
1249
+ },
1250
+ stripVertical: {
1251
+ paddingRight: 8
1252
+ },
1253
+ stripTile: {
1254
+ overflow: "hidden",
1255
+ borderRadius: 18
1256
+ },
1257
+ stripTileHorizontal: {
1258
+ width: 132,
1259
+ height: 100
1260
+ },
1261
+ stripTileVertical: {
1262
+ width: 100,
1263
+ height: 132
1264
+ }
1265
+ });
1266
+
1267
+ // src/components/native-space-view/SpaceTopBar.android.tsx
1268
+ import UserGroupIcon from "@hugeicons/core-free-icons/dist/esm/UserGroupIcon";
1269
+ import { HugeiconsIcon as HugeiconsIcon4 } from "@hugeicons/react-native";
1270
+ import { Image as Image2, Platform as Platform4, StyleSheet as StyleSheet10, Text as Text6, View as View10 } from "react-native";
1271
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1272
+ function SpaceTopBarAndroid({ spaceName, participantCount, formattedDuration, logoUrl }) {
1273
+ const theme = useNativeTheme();
1274
+ return /* @__PURE__ */ jsxs8(View10, { style: [styles9.topBar, { backgroundColor: theme.colors.darkCanvas, borderColor: theme.colors.border }], children: [
1275
+ /* @__PURE__ */ jsxs8(View10, { style: styles9.topBarLeft, children: [
1276
+ logoUrl ? /* @__PURE__ */ jsx13(Image2, { accessibilityLabel: "Chalk", source: { uri: logoUrl }, style: styles9.logo }) : null,
1277
+ /* @__PURE__ */ jsx13(View10, { style: [styles9.connectionDot, { backgroundColor: theme.colors.success }] }),
1278
+ /* @__PURE__ */ jsx13(Text6, { style: [styles9.topBarSpaceName, { color: theme.colors.foreground }], numberOfLines: 1, children: spaceName }),
1279
+ /* @__PURE__ */ jsx13(View10, { style: [styles9.timerBadge, { backgroundColor: theme.colors.surface }], children: /* @__PURE__ */ jsx13(Text6, { style: [styles9.timerText, { color: theme.colors.mutedForeground }], children: formattedDuration }) })
1280
+ ] }),
1281
+ /* @__PURE__ */ jsxs8(View10, { style: [styles9.topBarRight, { backgroundColor: theme.colors.surface }], children: [
1282
+ /* @__PURE__ */ jsx13(HugeiconsIcon4, { icon: UserGroupIcon, size: 14, color: theme.colors.foreground }),
1283
+ /* @__PURE__ */ jsx13(Text6, { style: [styles9.topBarCount, { color: theme.colors.foreground }], children: participantCount })
1284
+ ] })
1285
+ ] });
1286
+ }
1287
+ var styles9 = StyleSheet10.create({
1288
+ topBar: {
1289
+ paddingTop: Platform4.OS === "ios" ? 54 : 42,
1290
+ paddingBottom: 14,
1291
+ paddingHorizontal: 24,
1292
+ backgroundColor: Theme.colors.darkCanvas,
1293
+ flexDirection: "row",
1294
+ alignItems: "center",
1295
+ justifyContent: "space-between",
1296
+ borderBottomWidth: 1,
1297
+ borderColor: Theme.colors.whiteOverlay06,
1298
+ width: "100%"
1299
+ },
1300
+ topBarLeft: {
1301
+ flexDirection: "row",
1302
+ alignItems: "center",
1303
+ gap: 10,
1304
+ flex: 1
1305
+ },
1306
+ logo: { width: 24, height: 24, borderRadius: 6 },
1307
+ connectionDot: {
1308
+ width: 6,
1309
+ height: 6,
1310
+ borderRadius: 3,
1311
+ backgroundColor: Theme.colors.success
1312
+ },
1313
+ topBarSpaceName: {
1314
+ color: Theme.colors.onDark,
1315
+ fontSize: 14,
1316
+ fontWeight: "800",
1317
+ letterSpacing: -0.2
1318
+ },
1319
+ timerBadge: {
1320
+ backgroundColor: Theme.colors.whiteOverlay10,
1321
+ paddingHorizontal: 8,
1322
+ paddingVertical: 2,
1323
+ borderRadius: 6,
1324
+ marginLeft: 4
1325
+ },
1326
+ timerText: {
1327
+ color: Theme.colors.whiteOverlay60,
1328
+ fontSize: 11,
1329
+ fontWeight: "700",
1330
+ fontVariant: ["tabular-nums"]
1331
+ },
1332
+ topBarRight: {
1333
+ flexDirection: "row",
1334
+ alignItems: "center",
1335
+ gap: 4,
1336
+ backgroundColor: Theme.colors.whiteOverlay08,
1337
+ paddingHorizontal: 8,
1338
+ paddingVertical: 4,
1339
+ borderRadius: 10
1340
+ },
1341
+ topBarCount: {
1342
+ color: Theme.colors.onDark,
1343
+ fontSize: 12,
1344
+ fontWeight: "800"
1345
+ }
1346
+ });
1347
+
1348
+ // src/components/native-space-view/SpaceWhiteboardSurface.tsx
1349
+ import { useCallback as useCallback5 } from "react";
1350
+ import { StyleSheet as StyleSheet12 } from "react-native";
1351
+
1352
+ // src/components/EmbeddedWhiteboard.tsx
1353
+ import { ChalkWhiteboardController } from "@q9labsai/chalk-whiteboard/embedded";
1354
+ import { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo8, useRef as useRef2, useState as useState3 } from "react";
1355
+ import { ActivityIndicator, Pressable as Pressable4, StyleSheet as StyleSheet11, Text as Text7, useWindowDimensions as useWindowDimensions2, View as View11 } from "react-native";
1356
+ import WebView from "react-native-webview";
1357
+
1358
+ // src/whiteboard/embedded-whiteboard-assets.ts
1359
+ import { NativeModules as NativeModules2, Platform as Platform5 } from "react-native";
1360
+ var ANDROID_RENDERER_URL = "file:///android_asset/chalk-whiteboard/index.html";
1361
+ async function resolveEmbeddedWhiteboardRendererURL(override) {
1362
+ if (override) return requireLocalRendererURL(override);
1363
+ if (Platform5.OS === "android") return ANDROID_RENDERER_URL;
1364
+ const module = NativeModules2.ChalkWhiteboardAssets;
1365
+ if (!module?.rendererURL) throw new Error(`Chalk embedded whiteboard assets are unavailable on ${Platform5.OS}`);
1366
+ return requireLocalRendererURL(await module.rendererURL());
1367
+ }
1368
+ function rendererURLWithContext(rendererURL, context) {
1369
+ const separator = rendererURL.includes("?") ? "&" : "?";
1370
+ return `${rendererURL}${separator}journeyId=${encodeURIComponent(context.journeyId)}&rendererGeneration=${encodeURIComponent(context.rendererGeneration)}`;
1371
+ }
1372
+ function isEmbeddedWhiteboardNavigationAllowed(requestURL, rendererURL) {
1373
+ if (requestURL === "about:blank") return true;
1374
+ try {
1375
+ const renderer = new URL(rendererURL);
1376
+ const request = new URL(requestURL);
1377
+ if (renderer.protocol !== "file:" || request.protocol !== "file:" || request.host !== renderer.host) return false;
1378
+ const requestPath = decodeURIComponent(request.pathname);
1379
+ if (requestPath.split("/").includes("..")) return false;
1380
+ const rendererDirectory = renderer.pathname.slice(0, renderer.pathname.lastIndexOf("/") + 1);
1381
+ return request.pathname === renderer.pathname || request.pathname.startsWith(rendererDirectory);
1382
+ } catch {
1383
+ return false;
1384
+ }
1385
+ }
1386
+ function requireLocalRendererURL(value) {
1387
+ if (!value.startsWith("file://")) throw new Error("Chalk embedded whiteboard renderer must be a local file URL");
1388
+ return value;
1389
+ }
1390
+
1391
+ // src/components/EmbeddedWhiteboard.tsx
1392
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1393
+ var embeddedWhiteboardWebViewSecurityPolicy = Object.freeze({
1394
+ allowFileAccess: true,
1395
+ allowFileAccessFromFileURLs: false,
1396
+ allowUniversalAccessFromFileURLs: false,
1397
+ cacheEnabled: false,
1398
+ domStorageEnabled: false,
1399
+ javaScriptCanOpenWindowsAutomatically: false,
1400
+ javaScriptEnabled: true,
1401
+ mixedContentMode: "never",
1402
+ setSupportMultipleWindows: false,
1403
+ sharedCookiesEnabled: false,
1404
+ thirdPartyCookiesEnabled: false
1405
+ });
1406
+ function EmbeddedWhiteboard({ transport, journeyId, traceparent, tracestate, canDraw, canClear, theme: themeOverride, localParticipantColor, rendererURL: rendererURLOverride, style, testID, onMetric, onError, onUserExport }) {
1407
+ const nativeTheme = useNativeTheme();
1408
+ const theme = themeOverride ?? nativeTheme.colorScheme;
1409
+ const webViewRef = useRef2(null);
1410
+ const controllerRef = useRef2(null);
1411
+ const listenersRef = useRef2(/* @__PURE__ */ new Set());
1412
+ const onMetricRef = useRef2(onMetric);
1413
+ const onErrorRef = useRef2(onError);
1414
+ const onUserExportRef = useRef2(onUserExport);
1415
+ const [rendererURL, setRendererURL] = useState3(null);
1416
+ const [rendererGeneration, setRendererGeneration] = useState3(createRendererGeneration);
1417
+ const [loadAttempt, setLoadAttempt] = useState3(0);
1418
+ const [loadError, setLoadError] = useState3(null);
1419
+ const [compatibilityNotice, setCompatibilityNotice] = useState3(null);
1420
+ const { width, height, scale } = useWindowDimensions2();
1421
+ onMetricRef.current = onMetric;
1422
+ onErrorRef.current = onError;
1423
+ onUserExportRef.current = onUserExport;
1424
+ const rendererPort = useMemo8(
1425
+ () => ({
1426
+ postMessage: (message) => webViewRef.current?.postMessage(message),
1427
+ subscribe: (listener) => {
1428
+ listenersRef.current.add(listener);
1429
+ return () => listenersRef.current.delete(listener);
1430
+ }
1431
+ }),
1432
+ []
1433
+ );
1434
+ const handleControllerError = useCallback4((error) => onErrorRef.current?.(error), []);
1435
+ const handleControllerMetric = useCallback4((metric) => onMetricRef.current?.(metric), []);
1436
+ const handleControllerUserExport = useCallback4((value) => onUserExportRef.current?.(value), []);
1437
+ useEffect3(() => {
1438
+ let active = true;
1439
+ setLoadError(null);
1440
+ void resolveEmbeddedWhiteboardRendererURL(rendererURLOverride).then((url) => {
1441
+ if (active) setRendererURL(url);
1442
+ }).catch((cause) => {
1443
+ if (!active) return;
1444
+ const message = cause instanceof Error ? cause.message : "Chalk whiteboard assets are unavailable";
1445
+ setLoadError(message);
1446
+ onError?.({ code: "renderer_asset_unavailable", message, recoverable: false });
1447
+ });
1448
+ return () => {
1449
+ active = false;
1450
+ };
1451
+ }, [loadAttempt, onError, rendererURLOverride]);
1452
+ useEffect3(() => {
1453
+ setCompatibilityNotice(null);
1454
+ const controller = new ChalkWhiteboardController({
1455
+ renderer: rendererPort,
1456
+ transport,
1457
+ journeyId,
1458
+ ...traceparent ? { traceparent } : {},
1459
+ ...tracestate ? { tracestate } : {},
1460
+ canDraw,
1461
+ canClear,
1462
+ theme,
1463
+ ...localParticipantColor ? { localParticipantColor } : {},
1464
+ onMetric: handleControllerMetric,
1465
+ onError: handleControllerError,
1466
+ onCompatibilityChange: (state) => setCompatibilityNotice(state.message),
1467
+ onUserExport: handleControllerUserExport
1468
+ });
1469
+ controller.start();
1470
+ controllerRef.current = controller;
1471
+ return () => {
1472
+ if (controllerRef.current === controller) controllerRef.current = null;
1473
+ controller.stop();
1474
+ };
1475
+ }, [handleControllerError, handleControllerMetric, handleControllerUserExport, journeyId, localParticipantColor, rendererPort, theme, traceparent, tracestate, transport]);
1476
+ useEffect3(() => {
1477
+ controllerRef.current?.setCapabilities({ canDraw, canClear });
1478
+ }, [canClear, canDraw]);
1479
+ const viewport = useMemo8(() => ({ width, height, scale }), [height, scale, width]);
1480
+ useEffect3(() => {
1481
+ controllerRef.current?.setViewport(viewport);
1482
+ }, [viewport]);
1483
+ const sourceURL = rendererURL ? rendererURLWithContext(rendererURL, { journeyId, rendererGeneration }) : null;
1484
+ const handleMessage = (event) => {
1485
+ const message = event.nativeEvent.data;
1486
+ listenersRef.current.forEach((listener) => listener(message));
1487
+ };
1488
+ const allowNavigation = (request) => Boolean(rendererURL && isEmbeddedWhiteboardNavigationAllowed(request.url, rendererURL));
1489
+ const reloadRenderer = () => {
1490
+ controllerRef.current?.rendererReloaded();
1491
+ setRendererGeneration(createRendererGeneration());
1492
+ };
1493
+ const retryRenderer = () => {
1494
+ setLoadError(null);
1495
+ setLoadAttempt((attempt) => attempt + 1);
1496
+ reloadRenderer();
1497
+ };
1498
+ const handleRendererTermination = () => {
1499
+ handleControllerMetric({ name: "whiteboard.renderer.termination", value: 1 });
1500
+ handleControllerError({
1501
+ code: "renderer_terminated",
1502
+ message: "The whiteboard renderer stopped and is recovering.",
1503
+ recoverable: true
1504
+ });
1505
+ reloadRenderer();
1506
+ };
1507
+ if (loadError) {
1508
+ return /* @__PURE__ */ jsxs9(View11, { style: [styles10.status, { backgroundColor: nativeTheme.colors.lightSurface }, style], testID, children: [
1509
+ /* @__PURE__ */ jsx14(Text7, { style: [styles10.errorTitle, { color: nativeTheme.colors.lightText }], children: "Whiteboard unavailable" }),
1510
+ /* @__PURE__ */ jsx14(Text7, { style: [styles10.errorMessage, { color: nativeTheme.colors.lightSubtleText }], children: loadError }),
1511
+ /* @__PURE__ */ jsx14(Pressable4, { accessibilityRole: "button", onPress: retryRenderer, style: ({ pressed }) => [styles10.retryButton, { backgroundColor: nativeTheme.colors.info }, pressed && styles10.retryButtonPressed], children: /* @__PURE__ */ jsx14(Text7, { style: [styles10.retryButtonText, { color: nativeTheme.colors.onDark }], children: "Retry" }) })
1512
+ ] });
1513
+ }
1514
+ if (!sourceURL || !rendererURL) {
1515
+ return /* @__PURE__ */ jsxs9(View11, { style: [styles10.status, { backgroundColor: nativeTheme.colors.lightSurface }, style], testID, children: [
1516
+ /* @__PURE__ */ jsx14(ActivityIndicator, { color: nativeTheme.colors.info }),
1517
+ /* @__PURE__ */ jsx14(Text7, { style: [styles10.loadingMessage, { color: nativeTheme.colors.lightMutedText }], children: "Loading whiteboard\u2026" })
1518
+ ] });
1519
+ }
1520
+ return /* @__PURE__ */ jsxs9(View11, { style: [styles10.container, style], testID, children: [
1521
+ /* @__PURE__ */ jsx14(
1522
+ WebView,
1523
+ {
1524
+ ref: webViewRef,
1525
+ ...embeddedWhiteboardWebViewSecurityPolicy,
1526
+ allowingReadAccessToURL: rendererURL.slice(0, rendererURL.lastIndexOf("/") + 1),
1527
+ mediaPlaybackRequiresUserAction: true,
1528
+ onContentProcessDidTerminate: handleRendererTermination,
1529
+ onError: (event) => {
1530
+ const message = event.nativeEvent.description || "The whiteboard renderer failed to load";
1531
+ setLoadError(message);
1532
+ handleControllerError({ code: "renderer_load_failed", message, recoverable: true });
1533
+ },
1534
+ onMessage: handleMessage,
1535
+ onRenderProcessGone: handleRendererTermination,
1536
+ onShouldStartLoadWithRequest: allowNavigation,
1537
+ originWhitelist: ["file://*"],
1538
+ pullToRefreshEnabled: false,
1539
+ scrollEnabled: false,
1540
+ source: { uri: sourceURL },
1541
+ style: [styles10.webView, { backgroundColor: nativeTheme.colors.lightSurface }],
1542
+ webviewDebuggingEnabled: typeof __DEV__ !== "undefined" && __DEV__
1543
+ },
1544
+ rendererGeneration
1545
+ ),
1546
+ compatibilityNotice ? /* @__PURE__ */ jsx14(View11, { pointerEvents: "none", style: [styles10.compatibilityNotice, { backgroundColor: nativeTheme.colors.dangerSurfaceOverlay94 }], children: /* @__PURE__ */ jsx14(Text7, { style: [styles10.compatibilityNoticeText, { color: nativeTheme.colors.onDark }], children: compatibilityNotice }) }) : null
1547
+ ] });
1548
+ }
1549
+ function createRendererGeneration() {
1550
+ return globalThis.crypto?.randomUUID?.() ?? `whiteboard-${Date.now()}-${Math.random().toString(36).slice(2)}`;
1551
+ }
1552
+ var styles10 = StyleSheet11.create({
1553
+ container: {
1554
+ flex: 1,
1555
+ overflow: "hidden"
1556
+ },
1557
+ webView: {
1558
+ flex: 1
1559
+ },
1560
+ compatibilityNotice: {
1561
+ position: "absolute",
1562
+ top: 12,
1563
+ left: 12,
1564
+ right: 12,
1565
+ borderRadius: 10,
1566
+ paddingHorizontal: 12,
1567
+ paddingVertical: 10
1568
+ },
1569
+ compatibilityNoticeText: {
1570
+ fontSize: 13,
1571
+ fontWeight: "700",
1572
+ textAlign: "center"
1573
+ },
1574
+ status: {
1575
+ flex: 1,
1576
+ alignItems: "center",
1577
+ justifyContent: "center",
1578
+ gap: 10,
1579
+ padding: 24
1580
+ },
1581
+ loadingMessage: {
1582
+ fontSize: 14,
1583
+ fontWeight: "600"
1584
+ },
1585
+ errorTitle: {
1586
+ fontSize: 17,
1587
+ fontWeight: "700"
1588
+ },
1589
+ errorMessage: {
1590
+ fontSize: 13,
1591
+ textAlign: "center"
1592
+ },
1593
+ retryButton: {
1594
+ borderRadius: 8,
1595
+ paddingHorizontal: 16,
1596
+ paddingVertical: 10
1597
+ },
1598
+ retryButtonPressed: {
1599
+ opacity: 0.75
1600
+ },
1601
+ retryButtonText: {
1602
+ fontSize: 14,
1603
+ fontWeight: "700"
1604
+ }
1605
+ });
1606
+
1607
+ // src/components/native-space-view/SpaceWhiteboardSurface.tsx
1608
+ import { jsx as jsx15 } from "react/jsx-runtime";
1609
+ function shouldRenderNativeSpaceWhiteboard(whiteboard) {
1610
+ return whiteboard.isOpen && whiteboard.transport !== null;
1611
+ }
1612
+ function forwardNativeSpaceWhiteboardMetric(metric, onMetric) {
1613
+ onMetric?.(metric);
1614
+ }
1615
+ function forwardNativeSpaceWhiteboardFailure(error, onMetric) {
1616
+ onMetric?.({
1617
+ name: "whiteboard.renderer.failure",
1618
+ value: 1,
1619
+ attributes: { code: error.code, recoverable: error.recoverable }
1620
+ });
1621
+ }
1622
+ function SpaceWhiteboardSurface({ whiteboard }) {
1623
+ const nativeTheme = useNativeTheme();
1624
+ const handleError = useCallback5(
1625
+ (error) => {
1626
+ forwardNativeSpaceWhiteboardFailure(error, whiteboard.onMetric);
1627
+ },
1628
+ [whiteboard.onMetric]
1629
+ );
1630
+ const handleMetric = useCallback5(
1631
+ (metric) => {
1632
+ forwardNativeSpaceWhiteboardMetric(metric, whiteboard.onMetric);
1633
+ },
1634
+ [whiteboard.onMetric]
1635
+ );
1636
+ if (!shouldRenderNativeSpaceWhiteboard(whiteboard)) return null;
1637
+ return /* @__PURE__ */ jsx15(
1638
+ EmbeddedWhiteboard,
1639
+ {
1640
+ canClear: whiteboard.canClear,
1641
+ canDraw: whiteboard.canDraw,
1642
+ journeyId: whiteboard.journeyId,
1643
+ onError: handleError,
1644
+ onMetric: handleMetric,
1645
+ style: styles11.surface,
1646
+ theme: nativeTheme.colorScheme,
1647
+ transport: whiteboard.transport,
1648
+ ...whiteboard.traceparent ? { traceparent: whiteboard.traceparent } : {},
1649
+ ...whiteboard.tracestate ? { tracestate: whiteboard.tracestate } : {}
1650
+ }
1651
+ );
1652
+ }
1653
+ var styles11 = StyleSheet12.create({
1654
+ surface: {
1655
+ flex: 1,
1656
+ width: "100%"
1657
+ }
1658
+ });
1659
+
1660
+ // src/components/native-space-view/SettingsSheet.tsx
1661
+ import CheckmarkCircle01Icon2 from "@hugeicons/core-free-icons/dist/esm/CheckmarkCircle01Icon";
1662
+ import Mic01Icon2 from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
1663
+ import MicOff01Icon4 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
1664
+ import Speaker01Icon from "@hugeicons/core-free-icons/dist/esm/Speaker01Icon";
1665
+ import Video01Icon2 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
1666
+ import VideoOffIcon2 from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
1667
+ import { HugeiconsIcon as HugeiconsIcon7 } from "@hugeicons/react-native";
1668
+ import { useEffect as useEffect4, useState as useState4 } from "react";
1669
+ import { Modal as Modal3, Platform as Platform6, Pressable as Pressable7, ScrollView, StyleSheet as StyleSheet15, Text as Text10, View as View14 } from "react-native";
1670
+
1671
+ // src/components/native-space-view/SpaceSurfacePrimitives.tsx
1672
+ import { HugeiconsIcon as HugeiconsIcon5 } from "@hugeicons/react-native";
1673
+ import { Pressable as Pressable5, StyleSheet as StyleSheet13, Text as Text8, View as View12 } from "react-native";
1674
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1675
+ function SheetGrip() {
1676
+ return /* @__PURE__ */ jsx16(View12, { accessibilityElementsHidden: true, style: styles12.grip });
1677
+ }
1678
+ function CloseButton({ label, onPress }) {
1679
+ return /* @__PURE__ */ jsx16(Pressable5, { accessibilityLabel: label, accessibilityRole: "button", hitSlop: 6, onPress, style: ({ pressed }) => [styles12.closeButton, pressed && styles12.pressed], children: /* @__PURE__ */ jsx16(Text8, { style: styles12.closeGlyph, children: "\xD7" }) });
1680
+ }
1681
+ function SurfaceHeader({ title, count, subtitle, onClose, closeLabel }) {
1682
+ return /* @__PURE__ */ jsxs10(View12, { style: styles12.header, children: [
1683
+ /* @__PURE__ */ jsxs10(View12, { style: styles12.headerCopy, children: [
1684
+ /* @__PURE__ */ jsxs10(View12, { style: styles12.titleRow, children: [
1685
+ /* @__PURE__ */ jsx16(Text8, { style: styles12.title, children: title }),
1686
+ count !== void 0 ? /* @__PURE__ */ jsx16(View12, { style: styles12.countPill, children: /* @__PURE__ */ jsx16(Text8, { style: styles12.countText, children: count }) }) : null
1687
+ ] }),
1688
+ subtitle ? /* @__PURE__ */ jsx16(Text8, { style: styles12.subtitle, children: subtitle }) : null
1689
+ ] }),
1690
+ /* @__PURE__ */ jsx16(CloseButton, { label: closeLabel, onPress: onClose })
1691
+ ] });
1692
+ }
1693
+ function InitialsAvatar({ name, size = 52, style }) {
1694
+ const color = getParticipantColor(name);
1695
+ return /* @__PURE__ */ jsx16(View12, { style: [styles12.avatar, { backgroundColor: color.primary, borderRadius: size / 2, height: size, width: size }, style], children: /* @__PURE__ */ jsx16(Text8, { allowFontScaling: false, style: [styles12.avatarText, { fontSize: Math.max(16, Math.round(size * 0.34)) }], children: getParticipantInitials(name) }) });
1696
+ }
1697
+ function IconTile({ icon, symbol, color = Theme.colors.ink, wash = Theme.colors.surface }) {
1698
+ return /* @__PURE__ */ jsx16(View12, { style: [styles12.iconTile, { backgroundColor: wash }], children: icon ? /* @__PURE__ */ jsx16(HugeiconsIcon5, { color, icon, size: 22 }) : /* @__PURE__ */ jsx16(Text8, { style: [styles12.symbol, { color }], children: symbol }) });
1699
+ }
1700
+ var styles12 = StyleSheet13.create({
1701
+ grip: { alignSelf: "center", backgroundColor: Theme.colors.lineStrong, borderRadius: Theme.radius.full, height: 5, marginTop: Theme.spacing.sm, width: 48 },
1702
+ closeButton: { alignItems: "center", borderColor: Theme.colors.line, borderRadius: Theme.radius.full, borderWidth: 1, height: 46, justifyContent: "center", width: 46 },
1703
+ closeGlyph: { color: Theme.colors.ink, fontSize: 28, fontWeight: "400", lineHeight: 30 },
1704
+ header: { alignItems: "center", borderBottomColor: Theme.colors.line, borderBottomWidth: 1, flexDirection: "row", justifyContent: "space-between", minHeight: 88, paddingHorizontal: Theme.spacing.lg, paddingVertical: Theme.spacing.md },
1705
+ headerCopy: { flex: 1, minWidth: 0, paddingRight: Theme.spacing.md },
1706
+ titleRow: { alignItems: "center", flexDirection: "row", gap: Theme.spacing.sm },
1707
+ title: { ...Theme.typography.heading, color: Theme.colors.ink },
1708
+ subtitle: { ...Theme.typography.meta, color: Theme.colors.ink2, marginTop: 2 },
1709
+ countPill: { alignItems: "center", backgroundColor: Theme.colors.paper2, borderRadius: Theme.radius.sm, justifyContent: "center", minHeight: 32, minWidth: 36, paddingHorizontal: Theme.spacing.sm },
1710
+ countText: { ...Theme.typography.label, color: Theme.colors.ink },
1711
+ avatar: { alignItems: "center", justifyContent: "center", overflow: "hidden" },
1712
+ avatarText: { color: Theme.colors.surface, fontWeight: "500", includeFontPadding: false, textAlign: "center" },
1713
+ iconTile: { alignItems: "center", borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, height: 44, justifyContent: "center", width: 44 },
1714
+ symbol: { fontSize: 24, fontWeight: "500", includeFontPadding: false },
1715
+ pressed: { opacity: 0.72, transform: [{ scale: 0.98 }] }
1716
+ });
1717
+
1718
+ // src/components/native-space-view/AppearanceSettings.tsx
1719
+ import CheckmarkCircle01Icon from "@hugeicons/core-free-icons/dist/esm/CheckmarkCircle01Icon";
1720
+ import { HugeiconsIcon as HugeiconsIcon6 } from "@hugeicons/react-native";
1721
+ import { Pressable as Pressable6, StyleSheet as StyleSheet14, Text as Text9, View as View13 } from "react-native";
1722
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1723
+ function AppearanceSettings() {
1724
+ const { appearance, setPalette, setTexture } = useNativeAppearance();
1725
+ const theme = useNativeTheme();
1726
+ return /* @__PURE__ */ jsxs11(View13, { style: styles13.section, children: [
1727
+ /* @__PURE__ */ jsx17(Text9, { style: [styles13.intro, { color: theme.colors.ink2 }], children: "Choose a complete color family, then layer in a material texture. Every combination is available on mobile." }),
1728
+ ["light", "dark"].map((mode) => /* @__PURE__ */ jsx17(PaletteGroup, { mode, selectedPalette: appearance.palette, theme, onSelect: setPalette }, mode)),
1729
+ /* @__PURE__ */ jsxs11(View13, { style: styles13.textureSection, children: [
1730
+ /* @__PURE__ */ jsx17(Text9, { style: styles13.groupLabel, children: "Texture" }),
1731
+ /* @__PURE__ */ jsx17(View13, { style: styles13.textureGrid, children: THEME_TEXTURES.map((texture) => {
1732
+ const selected = texture.value === appearance.texture;
1733
+ return /* @__PURE__ */ jsxs11(
1734
+ Pressable6,
1735
+ {
1736
+ accessibilityLabel: `Use ${texture.label} texture`,
1737
+ accessibilityRole: "button",
1738
+ accessibilityState: { selected },
1739
+ onPress: () => setTexture(texture.value),
1740
+ style: ({ pressed }) => [styles13.texture, { backgroundColor: theme.colors.surfaceMuted, borderColor: theme.colors.line }, selected && [styles13.selected, { borderColor: theme.colors.primary }], pressed && styles13.pressed],
1741
+ children: [
1742
+ /* @__PURE__ */ jsx17(TexturePreview, { kind: texture.value, background: appearance.tokens.stage, foreground: appearance.tokens.textMuted }),
1743
+ /* @__PURE__ */ jsx17(Text9, { numberOfLines: 1, style: [styles13.textureLabel, { color: theme.colors.ink }], children: texture.label })
1744
+ ]
1745
+ },
1746
+ texture.value
1747
+ );
1748
+ }) })
1749
+ ] })
1750
+ ] });
1751
+ }
1752
+ function PaletteGroup({ mode, selectedPalette, theme, onSelect }) {
1753
+ return /* @__PURE__ */ jsxs11(View13, { style: styles13.group, children: [
1754
+ /* @__PURE__ */ jsx17(Text9, { style: styles13.groupLabel, children: mode === "light" ? "Light palettes" : "Dark palettes" }),
1755
+ /* @__PURE__ */ jsx17(View13, { style: styles13.paletteGrid, children: THEME_PALETTES.filter((palette) => palette.mode === mode).map((palette) => {
1756
+ const selected = palette.value === selectedPalette;
1757
+ return /* @__PURE__ */ jsxs11(
1758
+ Pressable6,
1759
+ {
1760
+ accessibilityLabel: `Use ${palette.label} palette`,
1761
+ accessibilityRole: "button",
1762
+ accessibilityState: { selected },
1763
+ onPress: () => onSelect(palette.value),
1764
+ style: ({ pressed }) => [styles13.palette, { backgroundColor: theme.colors.surfaceMuted, borderColor: theme.colors.line }, selected && [styles13.selected, { borderColor: theme.colors.primary }], pressed && styles13.pressed],
1765
+ children: [
1766
+ /* @__PURE__ */ jsx17(View13, { style: styles13.swatches, children: palette.swatch.map((color) => /* @__PURE__ */ jsx17(View13, { style: [styles13.swatch, { backgroundColor: color }] }, color)) }),
1767
+ /* @__PURE__ */ jsxs11(View13, { style: styles13.paletteCopy, children: [
1768
+ /* @__PURE__ */ jsx17(Text9, { numberOfLines: 1, style: [styles13.paletteLabel, { color: theme.colors.ink }], children: palette.label }),
1769
+ /* @__PURE__ */ jsx17(Text9, { numberOfLines: 1, style: [styles13.family, { color: theme.colors.ink3 }], children: palette.family })
1770
+ ] }),
1771
+ selected ? /* @__PURE__ */ jsx17(HugeiconsIcon6, { color: theme.colors.success, icon: CheckmarkCircle01Icon, size: 18 }) : null
1772
+ ]
1773
+ },
1774
+ palette.value
1775
+ );
1776
+ }) })
1777
+ ] });
1778
+ }
1779
+ function TexturePreview({ background, foreground, kind }) {
1780
+ return /* @__PURE__ */ jsxs11(View13, { style: [styles13.texturePreview, { backgroundColor: background }], children: [
1781
+ kind === "paper" ? Array.from({ length: 11 }, (_, index) => /* @__PURE__ */ jsx17(View13, { style: [styles13.grain, { backgroundColor: foreground, left: `${index * 29 % 91}%`, top: `${index * 43 % 88}%` }] }, index)) : null,
1782
+ kind === "slate" ? Array.from({ length: 5 }, (_, index) => /* @__PURE__ */ jsx17(View13, { style: [styles13.slateLine, { backgroundColor: foreground, top: 4 + index * 8 }] }, index)) : null
1783
+ ] });
1784
+ }
1785
+ var styles13 = StyleSheet14.create({
1786
+ section: { gap: Theme.spacing.xl },
1787
+ intro: { color: Theme.colors.ink2, fontSize: 14, lineHeight: 20 },
1788
+ group: { gap: Theme.spacing.sm },
1789
+ groupLabel: { color: Theme.colors.ink3, fontSize: 11, fontWeight: "800", letterSpacing: 1, textTransform: "uppercase" },
1790
+ paletteGrid: { flexDirection: "row", flexWrap: "wrap", gap: Theme.spacing.sm },
1791
+ palette: { alignItems: "center", backgroundColor: Theme.colors.surfaceMuted, borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, flexDirection: "row", gap: 9, minHeight: 66, padding: 9, width: "48.6%" },
1792
+ selected: { borderColor: Theme.colors.chalkBlue, borderWidth: 2, padding: 8 },
1793
+ swatches: { borderColor: Theme.colors.line, borderRadius: 7, borderWidth: 1, height: 42, overflow: "hidden", width: 42 },
1794
+ swatch: { flex: 1 },
1795
+ paletteCopy: { flex: 1, minWidth: 0 },
1796
+ paletteLabel: { color: Theme.colors.ink, fontSize: 13, fontWeight: "700" },
1797
+ family: { color: Theme.colors.ink3, fontSize: 11, marginTop: 2 },
1798
+ textureSection: { gap: Theme.spacing.sm },
1799
+ textureGrid: { flexDirection: "row", gap: Theme.spacing.sm },
1800
+ texture: { backgroundColor: Theme.colors.surfaceMuted, borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, flex: 1, overflow: "hidden", padding: 9 },
1801
+ texturePreview: { borderColor: Theme.colors.line, borderRadius: Theme.radius.sm, borderWidth: 1, height: 44, overflow: "hidden", position: "relative" },
1802
+ textureLabel: { color: Theme.colors.ink, fontSize: 12, fontWeight: "700", marginTop: 7, textAlign: "center" },
1803
+ grain: { borderRadius: 1, height: 2, opacity: 0.18, position: "absolute", width: 2 },
1804
+ slateLine: { height: 1, left: -5, opacity: 0.15, position: "absolute", transform: [{ rotate: "7deg" }], width: "120%" },
1805
+ pressed: { opacity: 0.7, transform: [{ scale: 0.98 }] }
1806
+ });
1807
+
1808
+ // src/components/native-space-view/SettingsSheet.tsx
1809
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1810
+ function SettingsSheet({ controller, isOpen, onClose }) {
1811
+ const [tab, setTab] = useState4("devices");
1812
+ useEffect4(() => {
1813
+ if (!isOpen) setTab("devices");
1814
+ }, [isOpen]);
1815
+ return /* @__PURE__ */ jsx18(Modal3, { animationType: "slide", onRequestClose: onClose, transparent: true, visible: isOpen, children: /* @__PURE__ */ jsxs12(View14, { style: styles14.modalRoot, children: [
1816
+ /* @__PURE__ */ jsx18(Pressable7, { accessibilityLabel: "Close Settings", onPress: onClose, style: styles14.backdrop }),
1817
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.sheet, children: [
1818
+ /* @__PURE__ */ jsx18(SheetGrip, {}),
1819
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.header, children: [
1820
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.title, children: "Settings" }),
1821
+ /* @__PURE__ */ jsx18(CloseButton, { label: "Close Settings", onPress: onClose })
1822
+ ] }),
1823
+ /* @__PURE__ */ jsx18(View14, { accessibilityRole: "tablist", style: styles14.tabs, children: ["devices", "appearance", "space"].map((nextTab) => /* @__PURE__ */ jsx18(Pressable7, { accessibilityRole: "tab", accessibilityState: { selected: tab === nextTab }, onPress: () => setTab(nextTab), style: ({ pressed }) => [styles14.tab, tab === nextTab && styles14.tabSelected, pressed && styles14.pressed], children: /* @__PURE__ */ jsx18(Text10, { style: [styles14.tabText, tab === nextTab && styles14.tabTextSelected], children: nextTab[0].toUpperCase() + nextTab.slice(1) }) }, nextTab)) }),
1824
+ /* @__PURE__ */ jsxs12(ScrollView, { contentContainerStyle: styles14.content, showsVerticalScrollIndicator: false, children: [
1825
+ tab === "devices" ? /* @__PURE__ */ jsx18(DevicesSettings, { controller }) : null,
1826
+ tab === "appearance" ? /* @__PURE__ */ jsx18(AppearanceSettings, {}) : null,
1827
+ tab === "space" ? /* @__PURE__ */ jsx18(SpaceSettings, { controller }) : null
1828
+ ] }),
1829
+ /* @__PURE__ */ jsx18(Pressable7, { accessibilityRole: "button", onPress: onClose, style: ({ pressed }) => [styles14.doneButton, pressed && styles14.pressed], children: /* @__PURE__ */ jsx18(Text10, { style: styles14.doneText, children: "Done" }) })
1830
+ ] })
1831
+ ] }) });
1832
+ }
1833
+ function DevicesSettings({ controller }) {
1834
+ const microphoneEnabled = !controller.isMuted;
1835
+ const cameraEnabled = !controller.isCameraOff;
1836
+ return /* @__PURE__ */ jsxs12(View14, { style: styles14.section, children: [
1837
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.sectionIntro, children: "Use the controls below to set what you share in this Episode." }),
1838
+ /* @__PURE__ */ jsx18(DeviceControl, { disabled: controller.simulatorMediaDisabled, enabled: microphoneEnabled, icon: microphoneEnabled ? Mic01Icon2 : MicOff01Icon4, label: "Microphone", onPress: controller.toggleAudio, value: microphoneEnabled ? "On" : "Off" }),
1839
+ /* @__PURE__ */ jsx18(DeviceControl, { disabled: controller.simulatorMediaDisabled, enabled: cameraEnabled, icon: cameraEnabled ? Video01Icon2 : VideoOffIcon2, label: "Camera", onPress: controller.toggleVideo, value: cameraEnabled ? "On" : "Off" }),
1840
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.deviceRow, children: [
1841
+ /* @__PURE__ */ jsx18(IconTile, { icon: Speaker01Icon }),
1842
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.rowCopy, children: [
1843
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.rowLabel, children: "Speaker" }),
1844
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.rowMeta, children: "System audio output" })
1845
+ ] }),
1846
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.rowValue, children: "Automatic" })
1847
+ ] }),
1848
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.readyCard, children: [
1849
+ /* @__PURE__ */ jsx18(HugeiconsIcon7, { color: Theme.colors.success, icon: CheckmarkCircle01Icon2, size: 22 }),
1850
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.readyText, children: controller.simulatorMediaDisabled ? "Device controls are unavailable here" : "Devices are ready" })
1851
+ ] })
1852
+ ] });
1853
+ }
1854
+ function DeviceControl({ disabled, enabled, icon, label, onPress, value }) {
1855
+ return /* @__PURE__ */ jsxs12(Pressable7, { accessibilityLabel: `${label} ${value}`, accessibilityRole: "button", disabled, onPress, style: ({ pressed }) => [styles14.deviceRow, disabled && styles14.disabled, pressed && styles14.pressed], children: [
1856
+ /* @__PURE__ */ jsx18(IconTile, { icon, color: enabled ? Theme.colors.ink : Theme.colors.error, wash: enabled ? Theme.colors.surface : Theme.colors.washPink }),
1857
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.rowCopy, children: [
1858
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.rowLabel, children: label }),
1859
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.rowMeta, children: disabled ? "Unavailable on this device" : "Tap to change state" })
1860
+ ] }),
1861
+ /* @__PURE__ */ jsx18(Text10, { style: [styles14.rowValue, !enabled && styles14.valueOff], children: value })
1862
+ ] });
1863
+ }
1864
+ function SpaceSettings({ controller }) {
1865
+ return /* @__PURE__ */ jsxs12(View14, { style: styles14.section, children: [
1866
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.sectionIntro, children: "Canonical information about this Space and its current Episode." }),
1867
+ /* @__PURE__ */ jsx18(InfoRow, { label: "Space", value: "Current Space" }),
1868
+ /* @__PURE__ */ jsx18(InfoRow, { label: "Episode", value: controller.formattedDuration }),
1869
+ /* @__PURE__ */ jsx18(InfoRow, { label: "People", value: String(controller.participantCount) }),
1870
+ /* @__PURE__ */ jsxs12(View14, { style: styles14.infoCard, children: [
1871
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.infoTitle, children: "Space content stays here" }),
1872
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.infoText, children: "Chat and Board content belong to this Space and remain available across Episodes." })
1873
+ ] })
1874
+ ] });
1875
+ }
1876
+ function InfoRow({ label, value }) {
1877
+ return /* @__PURE__ */ jsxs12(View14, { style: styles14.infoRow, children: [
1878
+ /* @__PURE__ */ jsx18(Text10, { style: styles14.rowLabel, children: label }),
1879
+ /* @__PURE__ */ jsx18(Text10, { numberOfLines: 1, style: styles14.infoValue, children: value || "\u2014" })
1880
+ ] });
1881
+ }
1882
+ var styles14 = StyleSheet15.create({
1883
+ modalRoot: { flex: 1, justifyContent: "flex-end" },
1884
+ backdrop: { ...StyleSheet15.absoluteFillObject, backgroundColor: Theme.colors.darkOverlay22 },
1885
+ sheet: {
1886
+ backgroundColor: Theme.colors.surface,
1887
+ borderColor: Theme.colors.line,
1888
+ borderTopLeftRadius: Theme.radius.xl,
1889
+ borderTopRightRadius: Theme.radius.xl,
1890
+ elevation: 8,
1891
+ flex: 1,
1892
+ marginTop: 72,
1893
+ overflow: "hidden",
1894
+ paddingBottom: Platform6.OS === "ios" ? Theme.spacing.md : Theme.spacing.xs,
1895
+ shadowColor: Theme.colors.ink,
1896
+ shadowOffset: { height: -8, width: 0 },
1897
+ shadowOpacity: 0.12,
1898
+ shadowRadius: 22
1899
+ },
1900
+ header: { alignItems: "center", borderBottomColor: Theme.colors.line, borderBottomWidth: 1, flexDirection: "row", justifyContent: "space-between", minHeight: 78, paddingHorizontal: Theme.spacing.lg },
1901
+ title: { ...Theme.typography.heading, color: Theme.colors.ink },
1902
+ tabs: { backgroundColor: Theme.colors.paper2, borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, flexDirection: "row", margin: Theme.spacing.lg, padding: 3 },
1903
+ tab: { alignItems: "center", borderRadius: Theme.radius.sm, flex: 1, justifyContent: "center", minHeight: 46, paddingHorizontal: Theme.spacing.sm },
1904
+ tabSelected: { backgroundColor: Theme.colors.surface, ...Theme.shadows.sm },
1905
+ tabText: { color: Theme.colors.ink2, fontSize: 14, fontWeight: "500" },
1906
+ tabTextSelected: { color: Theme.colors.ink, fontWeight: "700" },
1907
+ content: { paddingBottom: Theme.spacing.lg, paddingHorizontal: Theme.spacing.lg },
1908
+ section: { gap: Theme.spacing.md },
1909
+ sectionIntro: { ...Theme.typography.body, color: Theme.colors.ink2, marginBottom: Theme.spacing.sm },
1910
+ deviceRow: { alignItems: "center", borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, flexDirection: "row", gap: Theme.spacing.md, minHeight: 70, padding: Theme.spacing.md },
1911
+ rowCopy: { flex: 1, minWidth: 0 },
1912
+ rowLabel: { color: Theme.colors.ink, fontSize: 16, fontWeight: "600" },
1913
+ rowMeta: { color: Theme.colors.ink2, fontSize: 13, lineHeight: 18, marginTop: 3 },
1914
+ rowValue: { color: Theme.colors.success, fontSize: 14, fontWeight: "700" },
1915
+ valueOff: { color: Theme.colors.error },
1916
+ readyCard: { alignItems: "center", backgroundColor: Theme.colors.successBackground, borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, flexDirection: "row", gap: Theme.spacing.sm, minHeight: 58, paddingHorizontal: Theme.spacing.md },
1917
+ readyText: { color: Theme.colors.ink2, fontSize: 15, fontWeight: "600" },
1918
+ disabled: { opacity: 0.52 },
1919
+ infoRow: { alignItems: "center", borderBottomColor: Theme.colors.line, borderBottomWidth: 1, flexDirection: "row", justifyContent: "space-between", minHeight: 54, paddingHorizontal: Theme.spacing.sm },
1920
+ infoValue: { color: Theme.colors.ink2, flexShrink: 1, fontSize: 15, marginLeft: Theme.spacing.md, maxWidth: "62%", textAlign: "right" },
1921
+ infoCard: { backgroundColor: Theme.colors.washBlue, borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, gap: Theme.spacing.sm, marginTop: Theme.spacing.sm, padding: Theme.spacing.md },
1922
+ infoTitle: { color: Theme.colors.ink, fontSize: 15, fontWeight: "700" },
1923
+ infoText: { color: Theme.colors.ink2, fontSize: 14, lineHeight: 20 },
1924
+ doneButton: { alignItems: "center", borderColor: Theme.colors.lineStrong, borderRadius: Theme.radius.md, borderWidth: 1, justifyContent: "center", margin: Theme.spacing.lg, minHeight: 52 },
1925
+ doneText: { color: Theme.colors.ink, fontSize: 16, fontWeight: "700" },
1926
+ pressed: { opacity: 0.72, transform: [{ scale: 0.985 }] }
1927
+ });
1928
+
1929
+ // src/components/native-space-view/SpacePanelSheet.tsx
1930
+ import { Modal as Modal5, Platform as Platform9, Pressable as Pressable11, SafeAreaView, StyleSheet as StyleSheet19, View as View18 } from "react-native";
1931
+
1932
+ // src/components/native-space-view/SpaceChatSheet.tsx
1933
+ import Message01Icon from "@hugeicons/core-free-icons/dist/esm/Message01Icon";
1934
+ import Navigation03Icon from "@hugeicons/core-free-icons/dist/esm/Navigation03Icon";
1935
+ import { HugeiconsIcon as HugeiconsIcon8 } from "@hugeicons/react-native";
1936
+ import { useMemo as useMemo9 } from "react";
1937
+ import { FlatList as FlatList3, KeyboardAvoidingView, Platform as Platform7, Pressable as Pressable8, StyleSheet as StyleSheet16, Text as Text11, TextInput, View as View15 } from "react-native";
1938
+
1939
+ // src/components/native-space-view/space-progressive-surface-helpers.ts
1940
+ function buildParticipantActionDescriptors(availability) {
1941
+ const actions = [];
1942
+ if (availability.canMuteParticipants) actions.push({ kind: "mute", label: "Mute microphone" });
1943
+ if (availability.canRequestMedia) {
1944
+ actions.push({ kind: "requestUnmute", label: "Ask to unmute" });
1945
+ actions.push({ kind: "requestCamera", label: "Ask to turn on camera" });
1946
+ }
1947
+ if (availability.canStopParticipantCamera) actions.push({ kind: "stopCamera", label: "Stop camera" });
1948
+ if (availability.canStopParticipantScreenShare) actions.push({ kind: "stopScreenShare", label: "Stop sharing" });
1949
+ if (availability.canRemoveParticipants) actions.push({ kind: "remove", label: "Remove Participant", destructive: true });
1950
+ return actions;
1951
+ }
1952
+ function formatChatTimestamp(timestamp) {
1953
+ if (!Number.isFinite(timestamp) || timestamp <= 0) return "";
1954
+ return new Date(timestamp).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
1955
+ }
1956
+
1957
+ // src/components/native-space-view/SpaceChatSheet.tsx
1958
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1959
+ function SpaceChatSheet({ controller }) {
1960
+ const localParticipantId = controller.participants.localParticipant?.id ?? null;
1961
+ const sendDisabled = !controller.chatDraft.trim() && controller.chatAttachments.length === 0 || controller.chatAttachmentUploading;
1962
+ const messages = useMemo9(() => controller.chat.messages, [controller.chat.messages]);
1963
+ return /* @__PURE__ */ jsxs13(View15, { style: styles15.content, children: [
1964
+ controller.chat.hasMore ? /* @__PURE__ */ jsx19(Pressable8, { accessibilityRole: "button", disabled: controller.chat.isLoadingOlder, onPress: () => void controller.chat.loadOlderMessages(), style: ({ pressed }) => [styles15.loadOlder, pressed && styles15.pressed], children: /* @__PURE__ */ jsx19(Text11, { style: styles15.loadOlderText, children: controller.chat.isLoadingOlder ? "Loading\u2026" : "Load earlier messages" }) }) : null,
1965
+ /* @__PURE__ */ jsx19(
1966
+ FlatList3,
1967
+ {
1968
+ accessibilityLabel: "Chat messages",
1969
+ contentContainerStyle: styles15.messageList,
1970
+ data: messages,
1971
+ keyExtractor: (message) => message.id,
1972
+ ListEmptyComponent: /* @__PURE__ */ jsx19(EmptyChat, {}),
1973
+ onViewableItemsChanged: ({ viewableItems }) => {
1974
+ const sequence = viewableItems.at(-1)?.item.sequence;
1975
+ if (sequence) controller.markChatMessageVisible(sequence);
1976
+ },
1977
+ renderItem: ({ item }) => /* @__PURE__ */ jsx19(ChatMessage, { isLocal: item.senderId === localParticipantId, message: item, onOpenAttachment: controller.openChatAttachment }),
1978
+ showsVerticalScrollIndicator: false
1979
+ }
1980
+ ),
1981
+ controller.chat.pendingMessages.map((message) => /* @__PURE__ */ jsxs13(View15, { style: styles15.pendingMessage, children: [
1982
+ /* @__PURE__ */ jsx19(Text11, { style: styles15.pendingText, children: message.text }),
1983
+ /* @__PURE__ */ jsx19(Text11, { style: styles15.pendingMeta, children: message.state === "sending" ? "Sending\u2026" : message.error?.message ?? "Send failed" }),
1984
+ message.state === "failed" ? /* @__PURE__ */ jsx19(Pressable8, { accessibilityRole: "button", onPress: () => void controller.chat.retryMessage(message.clientMessageId), children: /* @__PURE__ */ jsx19(Text11, { style: styles15.retry, children: "Retry" }) }) : null
1985
+ ] }, message.clientMessageId)),
1986
+ controller.chatAttachments.length ? /* @__PURE__ */ jsx19(View15, { accessibilityLabel: "Selected attachments", style: styles15.selectedAttachments, children: controller.chatAttachments.map((attachment, index) => /* @__PURE__ */ jsxs13(View15, { style: styles15.selectedAttachment, children: [
1987
+ /* @__PURE__ */ jsx19(Text11, { numberOfLines: 1, style: styles15.selectedAttachmentText, children: attachment.fileName }),
1988
+ /* @__PURE__ */ jsx19(Pressable8, { accessibilityLabel: `Remove ${attachment.fileName}`, accessibilityRole: "button", disabled: controller.chatAttachmentUploading, onPress: () => controller.removeChatAttachment(index), children: /* @__PURE__ */ jsx19(Text11, { style: styles15.removeAttachment, children: "Remove" }) })
1989
+ ] }, `${attachment.fileName}-${index}`)) }) : null,
1990
+ controller.chatAttachmentError ? /* @__PURE__ */ jsx19(Text11, { accessibilityLiveRegion: "polite", style: styles15.attachmentError, children: controller.chatAttachmentError }) : null,
1991
+ /* @__PURE__ */ jsx19(KeyboardAvoidingView, { behavior: Platform7.OS === "ios" ? "padding" : void 0, keyboardVerticalOffset: Platform7.OS === "ios" ? 12 : 0, children: /* @__PURE__ */ jsxs13(View15, { style: styles15.composer, children: [
1992
+ controller.canPickChatFiles ? /* @__PURE__ */ jsx19(
1993
+ Pressable8,
1994
+ {
1995
+ accessibilityLabel: "Attach file",
1996
+ accessibilityRole: "button",
1997
+ disabled: controller.chatAttachmentPicking || controller.chatAttachmentUploading,
1998
+ onPress: () => void controller.pickChatFiles(),
1999
+ style: ({ pressed }) => [styles15.composerButton, (controller.chatAttachmentPicking || controller.chatAttachmentUploading) && styles15.sendDisabled, pressed && styles15.pressed],
2000
+ children: /* @__PURE__ */ jsx19(Text11, { style: styles15.composerButtonText, children: controller.chatAttachmentPicking ? "Choosing\u2026" : "Attach" })
2001
+ }
2002
+ ) : null,
2003
+ /* @__PURE__ */ jsx19(
2004
+ TextInput,
2005
+ {
2006
+ accessibilityLabel: "Message the Space",
2007
+ editable: !controller.chatAttachmentUploading,
2008
+ multiline: true,
2009
+ onChangeText: controller.setChatDraft,
2010
+ onSubmitEditing: controller.sendChatMessage,
2011
+ placeholder: "Message the Space",
2012
+ placeholderTextColor: Theme.colors.placeholder,
2013
+ style: styles15.input,
2014
+ value: controller.chatDraft
2015
+ }
2016
+ ),
2017
+ /* @__PURE__ */ jsx19(Pressable8, { accessibilityLabel: "Send message", accessibilityRole: "button", disabled: sendDisabled, onPress: controller.sendChatMessage, style: ({ pressed }) => [styles15.sendButton, sendDisabled && styles15.sendDisabled, pressed && styles15.pressed], children: controller.chatAttachmentUploading ? /* @__PURE__ */ jsx19(Text11, { style: styles15.uploadingText, children: "\u2026" }) : /* @__PURE__ */ jsx19(HugeiconsIcon8, { color: Theme.colors.primaryForeground, icon: Navigation03Icon, size: 21 }) })
2018
+ ] }) })
2019
+ ] });
2020
+ }
2021
+ function ChatMessage({ isLocal, message, onOpenAttachment }) {
2022
+ const timestamp = formatChatTimestamp(message.timestamp);
2023
+ return /* @__PURE__ */ jsxs13(View15, { style: [styles15.messageRow, isLocal && styles15.messageRowLocal], children: [
2024
+ !isLocal ? /* @__PURE__ */ jsx19(InitialsAvatar, { name: message.senderName, size: 42 }) : null,
2025
+ /* @__PURE__ */ jsxs13(View15, { style: [styles15.messageCopy, isLocal && styles15.messageCopyLocal], children: [
2026
+ /* @__PURE__ */ jsx19(Text11, { style: [styles15.sender, isLocal && styles15.senderLocal], children: isLocal ? `${message.senderName} (You)` : message.senderName }),
2027
+ /* @__PURE__ */ jsxs13(View15, { style: [styles15.bubble, isLocal ? styles15.localBubble : styles15.remoteBubble], children: [
2028
+ message.text ? /* @__PURE__ */ jsx19(Text11, { style: [styles15.messageText, isLocal && styles15.localMessageText], children: message.text }) : null,
2029
+ message.attachments.map((attachment) => /* @__PURE__ */ jsx19(Pressable8, { accessibilityRole: "link", onPress: () => onOpenAttachment(attachment.attachmentId), style: ({ pressed }) => [styles15.attachmentLink, pressed && styles15.pressed], children: /* @__PURE__ */ jsx19(Text11, { numberOfLines: 1, style: [styles15.attachment, isLocal && styles15.localMessageText], children: attachment.fileName }) }, attachment.attachmentId))
2030
+ ] }),
2031
+ /* @__PURE__ */ jsx19(Text11, { style: [styles15.timestamp, isLocal && styles15.timestampLocal], children: timestamp }),
2032
+ message.readBy.length ? /* @__PURE__ */ jsxs13(Text11, { style: [styles15.readBy, isLocal && styles15.timestampLocal], children: [
2033
+ "Read by ",
2034
+ message.readBy.map((reader) => reader.displayName).join(", ")
2035
+ ] }) : null
2036
+ ] }),
2037
+ isLocal ? /* @__PURE__ */ jsx19(InitialsAvatar, { name: message.senderName, size: 42 }) : null
2038
+ ] });
2039
+ }
2040
+ function EmptyChat() {
2041
+ return /* @__PURE__ */ jsxs13(View15, { style: styles15.emptyState, children: [
2042
+ /* @__PURE__ */ jsx19(View15, { style: styles15.emptyIcon, children: /* @__PURE__ */ jsx19(HugeiconsIcon8, { color: Theme.colors.ink2, icon: Message01Icon, size: 26 }) }),
2043
+ /* @__PURE__ */ jsx19(Text11, { style: styles15.emptyTitle, children: "No messages yet" }),
2044
+ /* @__PURE__ */ jsx19(Text11, { style: styles15.emptyText, children: "Send a message to start the conversation." })
2045
+ ] });
2046
+ }
2047
+ var styles15 = StyleSheet16.create({
2048
+ content: { flex: 1, minHeight: 0 },
2049
+ loadOlder: { alignSelf: "center", minHeight: 44, paddingHorizontal: Theme.spacing.md, paddingVertical: Theme.spacing.sm, justifyContent: "center" },
2050
+ loadOlderText: { color: Theme.colors.information, fontSize: 14, fontWeight: "700" },
2051
+ messageList: { flexGrow: 1, gap: Theme.spacing.lg, paddingHorizontal: Theme.spacing.lg, paddingVertical: Theme.spacing.lg },
2052
+ messageRow: { alignItems: "flex-start", flexDirection: "row", gap: Theme.spacing.sm, maxWidth: "92%" },
2053
+ messageRowLocal: { alignSelf: "flex-end", justifyContent: "flex-end" },
2054
+ messageCopy: { flexShrink: 1, minWidth: 0 },
2055
+ messageCopyLocal: { alignItems: "flex-end" },
2056
+ sender: { color: Theme.colors.ink, fontSize: 15, fontWeight: "600", marginBottom: 6, paddingHorizontal: 4 },
2057
+ senderLocal: { textAlign: "right" },
2058
+ bubble: { borderRadius: Theme.radius.md, borderWidth: 1, maxWidth: "100%", paddingHorizontal: Theme.spacing.md, paddingVertical: Theme.spacing.md },
2059
+ remoteBubble: { backgroundColor: Theme.colors.surfaceMuted, borderColor: Theme.colors.line, borderTopLeftRadius: 5 },
2060
+ localBubble: { backgroundColor: Theme.colors.ink, borderColor: Theme.colors.ink, borderTopRightRadius: 5 },
2061
+ messageText: { color: Theme.colors.ink, fontSize: 17, lineHeight: 24 },
2062
+ localMessageText: { color: Theme.colors.surface },
2063
+ attachmentLink: { justifyContent: "center", marginTop: 4, maxWidth: "100%", minHeight: 32 },
2064
+ attachment: { color: Theme.colors.information, fontSize: 14 },
2065
+ timestamp: { color: Theme.colors.ink3, fontSize: 12, marginTop: 5, paddingHorizontal: 4 },
2066
+ timestampLocal: { textAlign: "right" },
2067
+ readBy: { color: Theme.colors.ink3, fontSize: 11, marginTop: 3, paddingHorizontal: 4 },
2068
+ pendingMessage: { borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, marginHorizontal: Theme.spacing.lg, marginBottom: Theme.spacing.sm, padding: Theme.spacing.md },
2069
+ pendingText: { color: Theme.colors.ink, fontSize: 14 },
2070
+ pendingMeta: { color: Theme.colors.ink2, fontSize: 12, marginTop: 4 },
2071
+ retry: { color: Theme.colors.information, fontSize: 13, fontWeight: "700", marginTop: 6 },
2072
+ selectedAttachments: { flexDirection: "row", flexWrap: "wrap", gap: Theme.spacing.sm, paddingHorizontal: Theme.spacing.lg, paddingBottom: Theme.spacing.sm },
2073
+ selectedAttachment: { backgroundColor: Theme.colors.paper2, borderColor: Theme.colors.line, borderRadius: Theme.radius.sm, borderWidth: 1, maxWidth: "100%", minHeight: 36, paddingHorizontal: Theme.spacing.sm, paddingVertical: 8 },
2074
+ selectedAttachmentText: { color: Theme.colors.ink2, fontSize: 13 },
2075
+ removeAttachment: { color: Theme.colors.information, fontSize: 12, fontWeight: "700", marginTop: 4 },
2076
+ attachmentError: { color: Theme.colors.danger, fontSize: 13, paddingHorizontal: Theme.spacing.lg, paddingBottom: Theme.spacing.sm },
2077
+ composer: { alignItems: "flex-end", borderTopColor: Theme.colors.line, borderTopWidth: 1, flexDirection: "row", gap: Theme.spacing.sm, padding: Theme.spacing.md },
2078
+ composerButton: { alignItems: "center", borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, height: 50, justifyContent: "center", width: 50 },
2079
+ composerButtonText: { color: Theme.colors.ink2, fontSize: 12, fontWeight: "700" },
2080
+ uploadingText: { color: Theme.colors.primaryForeground, fontSize: 18, fontWeight: "700" },
2081
+ input: { backgroundColor: Theme.colors.surfaceMuted, borderColor: Theme.colors.lineStrong, borderRadius: Theme.radius.md, borderWidth: 1, color: Theme.colors.ink, flex: 1, fontSize: 16, maxHeight: 112, minHeight: 50, paddingHorizontal: Theme.spacing.md, paddingVertical: 12 },
2082
+ sendButton: { alignItems: "center", backgroundColor: Theme.colors.ink, borderRadius: Theme.radius.full, height: 50, justifyContent: "center", width: 50 },
2083
+ sendDisabled: { backgroundColor: Theme.colors.lineStrong },
2084
+ emptyState: { alignItems: "center", flex: 1, justifyContent: "center", minHeight: 220, paddingHorizontal: Theme.spacing["3xl"] },
2085
+ emptyIcon: { alignItems: "center", backgroundColor: Theme.colors.washBlue, borderRadius: Theme.radius.full, height: 58, justifyContent: "center", marginBottom: Theme.spacing.md, width: 58 },
2086
+ emptyTitle: { color: Theme.colors.ink, fontSize: 16, fontWeight: "700" },
2087
+ emptyText: { color: Theme.colors.ink2, fontSize: 14, marginTop: 6, textAlign: "center" },
2088
+ pressed: { opacity: 0.72, transform: [{ scale: 0.98 }] }
2089
+ });
2090
+
2091
+ // src/components/native-space-view/SpacePeopleSheet.tsx
2092
+ import Mic01Icon3 from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
2093
+ import MicOff01Icon6 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
2094
+ import MoreHorizontalIcon2 from "@hugeicons/core-free-icons/dist/esm/MoreHorizontalIcon";
2095
+ import Video01Icon4 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
2096
+ import VideoOffIcon3 from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
2097
+ import { HugeiconsIcon as HugeiconsIcon10 } from "@hugeicons/react-native";
2098
+ import { useState as useState5 } from "react";
2099
+ import { Pressable as Pressable10, ScrollView as ScrollView2, StyleSheet as StyleSheet18, Text as Text13, View as View17 } from "react-native";
2100
+
2101
+ // src/components/native-space-view/ParticipantActionSheet.tsx
2102
+ import CancelCircleIcon from "@hugeicons/core-free-icons/dist/esm/CancelCircleIcon";
2103
+ import MicOff01Icon5 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
2104
+ import UserIcon from "@hugeicons/core-free-icons/dist/esm/UserIcon";
2105
+ import Video01Icon3 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
2106
+ import { HugeiconsIcon as HugeiconsIcon9 } from "@hugeicons/react-native";
2107
+ import { Modal as Modal4, Platform as Platform8, Pressable as Pressable9, StyleSheet as StyleSheet17, Text as Text12, View as View16 } from "react-native";
2108
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2109
+ function ParticipantActionSheet({ controller, participantId, onClose }) {
2110
+ const participant = participantId ? controller.participants.participants.find((item) => item.id === participantId) : void 0;
2111
+ const descriptors = buildParticipantActionDescriptors({
2112
+ canMuteParticipants: controller.canMuteParticipants,
2113
+ canRequestMedia: controller.canRequestMedia,
2114
+ canStopParticipantCamera: controller.canStopParticipantCamera,
2115
+ canStopParticipantScreenShare: controller.canStopParticipantScreenShare,
2116
+ canRemoveParticipants: controller.canRemoveParticipants
2117
+ });
2118
+ const run = (descriptor) => {
2119
+ if (!participantId) return;
2120
+ onClose();
2121
+ if (descriptor.kind === "mute") controller.muteParticipant(participantId);
2122
+ if (descriptor.kind === "requestUnmute") controller.requestUnmuteParticipant(participantId);
2123
+ if (descriptor.kind === "requestCamera") controller.requestStartParticipantCamera(participantId);
2124
+ if (descriptor.kind === "stopCamera") controller.stopParticipantCamera(participantId);
2125
+ if (descriptor.kind === "stopScreenShare") controller.stopParticipantScreenShare(participantId);
2126
+ if (descriptor.kind === "remove") controller.removeParticipant(participantId);
2127
+ };
2128
+ return /* @__PURE__ */ jsx20(Modal4, { animationType: "fade", onRequestClose: onClose, transparent: true, visible: participantId !== null, children: /* @__PURE__ */ jsxs14(View16, { style: styles16.modalRoot, children: [
2129
+ /* @__PURE__ */ jsx20(Pressable9, { accessibilityLabel: "Close Participant actions", onPress: onClose, style: styles16.backdrop }),
2130
+ /* @__PURE__ */ jsxs14(View16, { style: styles16.card, children: [
2131
+ /* @__PURE__ */ jsxs14(View16, { style: styles16.cardHeader, children: [
2132
+ participant ? /* @__PURE__ */ jsx20(InitialsAvatar, { name: participant.displayName, size: 44 }) : /* @__PURE__ */ jsx20(IconTile, { icon: UserIcon }),
2133
+ /* @__PURE__ */ jsx20(View16, { style: styles16.headerCopy, children: /* @__PURE__ */ jsx20(Text12, { numberOfLines: 1, style: styles16.name, children: participant?.displayName ?? "Participant" }) }),
2134
+ /* @__PURE__ */ jsx20(CloseButton, { label: "Close Participant actions", onPress: onClose })
2135
+ ] }),
2136
+ /* @__PURE__ */ jsxs14(View16, { style: styles16.actions, children: [
2137
+ descriptors.filter((descriptor) => !descriptor.destructive).map((descriptor) => /* @__PURE__ */ jsx20(ParticipantActionRow, { descriptor, onPress: () => run(descriptor) }, descriptor.kind)),
2138
+ descriptors.some((descriptor) => descriptor.destructive) ? /* @__PURE__ */ jsx20(View16, { style: styles16.divider }) : null,
2139
+ descriptors.filter((descriptor) => descriptor.destructive).map((descriptor) => /* @__PURE__ */ jsx20(ParticipantActionRow, { descriptor, onPress: () => run(descriptor) }, descriptor.kind))
2140
+ ] }),
2141
+ !descriptors.length ? /* @__PURE__ */ jsx20(Text12, { style: styles16.emptyText, children: "No actions are available for this Participant." }) : null
2142
+ ] })
2143
+ ] }) });
2144
+ }
2145
+ function ParticipantActionRow({ descriptor, onPress }) {
2146
+ const icon = descriptor.kind === "mute" || descriptor.kind === "requestUnmute" ? MicOff01Icon5 : descriptor.kind === "requestCamera" || descriptor.kind === "stopCamera" ? Video01Icon3 : CancelCircleIcon;
2147
+ return /* @__PURE__ */ jsxs14(Pressable9, { accessibilityLabel: descriptor.label, accessibilityRole: "button", onPress, style: ({ pressed }) => [styles16.actionRow, descriptor.destructive && styles16.destructiveRow, pressed && styles16.pressed], children: [
2148
+ /* @__PURE__ */ jsx20(HugeiconsIcon9, { color: descriptor.destructive ? Theme.colors.error : Theme.colors.ink, icon, size: 21 }),
2149
+ /* @__PURE__ */ jsx20(Text12, { style: [styles16.actionLabel, descriptor.destructive && styles16.destructiveText], children: descriptor.label })
2150
+ ] });
2151
+ }
2152
+ var styles16 = StyleSheet17.create({
2153
+ modalRoot: { alignItems: "center", flex: 1, justifyContent: "flex-end", paddingBottom: Platform8.OS === "ios" ? Theme.spacing["2xl"] : Theme.spacing.lg, paddingHorizontal: Theme.spacing.lg, paddingTop: Theme.spacing.lg },
2154
+ backdrop: { ...StyleSheet17.absoluteFillObject, backgroundColor: Theme.colors.darkOverlay22 },
2155
+ card: { backgroundColor: Theme.colors.surface, borderColor: Theme.colors.line, borderRadius: Theme.radius.lg, elevation: 8, maxHeight: "78%", overflow: "hidden", shadowColor: Theme.colors.ink, shadowOffset: { height: 4, width: 0 }, shadowOpacity: 0.14, shadowRadius: 20, width: "100%" },
2156
+ cardHeader: { alignItems: "center", borderBottomColor: Theme.colors.line, borderBottomWidth: 1, flexDirection: "row", gap: Theme.spacing.md, minHeight: 78, paddingHorizontal: Theme.spacing.md },
2157
+ headerCopy: { flex: 1, minWidth: 0 },
2158
+ name: { color: Theme.colors.ink, fontSize: 17, fontWeight: "700" },
2159
+ actions: { padding: Theme.spacing.sm },
2160
+ actionRow: { alignItems: "center", borderRadius: Theme.radius.sm, flexDirection: "row", gap: Theme.spacing.md, minHeight: 52, paddingHorizontal: Theme.spacing.md },
2161
+ actionLabel: { color: Theme.colors.ink, flex: 1, fontSize: 15 },
2162
+ destructiveRow: { backgroundColor: Theme.colors.washPink, marginTop: Theme.spacing.xs },
2163
+ destructiveText: { color: Theme.colors.error, fontWeight: "700" },
2164
+ divider: { backgroundColor: Theme.colors.line, height: 1, marginHorizontal: Theme.spacing.md, marginVertical: Theme.spacing.xs },
2165
+ emptyText: { color: Theme.colors.ink2, fontSize: 14, padding: Theme.spacing.lg },
2166
+ pressed: { opacity: 0.72, transform: [{ scale: 0.985 }] }
2167
+ });
2168
+
2169
+ // src/components/native-space-view/SpacePeopleSheet.tsx
2170
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
2171
+ function SpacePeopleSheet({ controller }) {
2172
+ const [actionParticipantId, setActionParticipantId] = useState5(null);
2173
+ const closeActions = () => {
2174
+ setActionParticipantId(null);
2175
+ };
2176
+ const openActions = (participantId) => {
2177
+ setActionParticipantId(participantId);
2178
+ };
2179
+ return /* @__PURE__ */ jsxs15(View17, { style: styles17.content, children: [
2180
+ /* @__PURE__ */ jsxs15(ScrollView2, { contentContainerStyle: styles17.list, showsVerticalScrollIndicator: false, children: [
2181
+ controller.admissionRequests.map((request) => /* @__PURE__ */ jsxs15(View17, { style: styles17.admissionRequest, children: [
2182
+ /* @__PURE__ */ jsx21(InitialsAvatar, { name: request.displayName, size: 48 }),
2183
+ /* @__PURE__ */ jsxs15(View17, { style: styles17.rowCopy, children: [
2184
+ /* @__PURE__ */ jsx21(Text13, { numberOfLines: 1, style: styles17.name, children: request.displayName }),
2185
+ /* @__PURE__ */ jsx21(Text13, { style: styles17.meta, children: "At the Entrance" })
2186
+ ] }),
2187
+ controller.canManageAdmission ? /* @__PURE__ */ jsxs15(View17, { style: styles17.admissionActions, children: [
2188
+ /* @__PURE__ */ jsx21(Pressable10, { accessibilityRole: "button", onPress: () => controller.denyAdmission(request.requestId), style: ({ pressed }) => [styles17.denyButton, pressed && styles17.pressed], children: /* @__PURE__ */ jsx21(Text13, { style: styles17.denyText, children: "Deny" }) }),
2189
+ /* @__PURE__ */ jsx21(Pressable10, { accessibilityRole: "button", onPress: () => controller.admitParticipant(request.requestId), style: ({ pressed }) => [styles17.admitButton, pressed && styles17.pressed], children: /* @__PURE__ */ jsx21(Text13, { style: styles17.admitText, children: "Admit" }) })
2190
+ ] }) : null
2191
+ ] }, request.requestId)),
2192
+ controller.participants.participants.map((participant) => {
2193
+ const local = participant.id === controller.participants.localParticipant?.id;
2194
+ const canAct = !local && canActOnParticipant(controller);
2195
+ return /* @__PURE__ */ jsxs15(View17, { style: styles17.participantRow, children: [
2196
+ /* @__PURE__ */ jsx21(InitialsAvatar, { name: participant.displayName, size: 54 }),
2197
+ /* @__PURE__ */ jsx21(View17, { style: styles17.rowCopy, children: /* @__PURE__ */ jsxs15(Text13, { numberOfLines: 1, style: styles17.name, children: [
2198
+ participant.displayName,
2199
+ local ? " (You)" : ""
2200
+ ] }) }),
2201
+ /* @__PURE__ */ jsxs15(View17, { style: styles17.mediaStatus, children: [
2202
+ /* @__PURE__ */ jsx21(HugeiconsIcon10, { color: participant.audioEnabled ? Theme.colors.success : Theme.colors.error, icon: participant.audioEnabled ? Mic01Icon3 : MicOff01Icon6, size: 22 }),
2203
+ /* @__PURE__ */ jsx21(View17, { style: [styles17.statusDot, { backgroundColor: participant.audioEnabled ? Theme.colors.chalkGreen : Theme.colors.chalkPink }] })
2204
+ ] }),
2205
+ /* @__PURE__ */ jsxs15(View17, { style: styles17.mediaStatus, children: [
2206
+ /* @__PURE__ */ jsx21(HugeiconsIcon10, { color: participant.videoEnabled ? Theme.colors.success : Theme.colors.error, icon: participant.videoEnabled ? Video01Icon4 : VideoOffIcon3, size: 22 }),
2207
+ /* @__PURE__ */ jsx21(View17, { style: [styles17.statusDot, { backgroundColor: participant.videoEnabled ? Theme.colors.chalkGreen : Theme.colors.chalkPink }] })
2208
+ ] }),
2209
+ canAct ? /* @__PURE__ */ jsx21(Pressable10, { accessibilityLabel: `Actions for ${participant.displayName}`, accessibilityRole: "button", onPress: () => openActions(participant.id), style: ({ pressed }) => [styles17.moreButton, pressed && styles17.pressed], children: /* @__PURE__ */ jsx21(HugeiconsIcon10, { color: Theme.colors.ink, icon: MoreHorizontalIcon2, size: 22 }) }) : null
2210
+ ] }, participant.id);
2211
+ }),
2212
+ !controller.participants.participants.length && !controller.admissionRequests.length ? /* @__PURE__ */ jsx21(EmptyPeople, {}) : null
2213
+ ] }),
2214
+ /* @__PURE__ */ jsx21(ParticipantActionSheet, { controller, onClose: closeActions, participantId: actionParticipantId })
2215
+ ] });
2216
+ }
2217
+ function canActOnParticipant(controller) {
2218
+ return controller.canMuteParticipants || controller.canRequestMedia || controller.canStopParticipantCamera || controller.canStopParticipantScreenShare || controller.canRemoveParticipants;
2219
+ }
2220
+ function EmptyPeople() {
2221
+ return /* @__PURE__ */ jsxs15(View17, { style: styles17.emptyState, children: [
2222
+ /* @__PURE__ */ jsx21(Text13, { style: styles17.emptyTitle, children: "No People yet" }),
2223
+ /* @__PURE__ */ jsx21(Text13, { style: styles17.emptyText, children: "People will appear here as they join the Space." })
2224
+ ] });
2225
+ }
2226
+ var styles17 = StyleSheet18.create({
2227
+ content: { flex: 1, minHeight: 0 },
2228
+ list: { paddingHorizontal: Theme.spacing.lg, paddingVertical: Theme.spacing.sm },
2229
+ participantRow: { alignItems: "center", borderBottomColor: Theme.colors.line, borderBottomWidth: 1, flexDirection: "row", gap: Theme.spacing.sm, minHeight: 84, paddingVertical: Theme.spacing.md },
2230
+ rowCopy: { flex: 1, minWidth: 0, paddingHorizontal: Theme.spacing.xs },
2231
+ name: { color: Theme.colors.ink, fontSize: 16, fontWeight: "700" },
2232
+ meta: { color: Theme.colors.ink2, fontSize: 14, marginTop: 4 },
2233
+ mediaStatus: { alignItems: "center", justifyContent: "center", minHeight: 44, minWidth: 34 },
2234
+ statusDot: { borderRadius: Theme.radius.full, height: 6, marginTop: 2, width: 6 },
2235
+ moreButton: { alignItems: "center", borderColor: Theme.colors.line, borderRadius: Theme.radius.full, borderWidth: 1, height: 46, justifyContent: "center", width: 46 },
2236
+ admissionRequest: { alignItems: "center", backgroundColor: Theme.colors.washYellow, borderColor: Theme.colors.line, borderRadius: Theme.radius.md, borderWidth: 1, flexDirection: "row", gap: Theme.spacing.sm, marginVertical: Theme.spacing.sm, padding: Theme.spacing.md },
2237
+ admissionActions: { alignItems: "center", flexDirection: "row", gap: Theme.spacing.sm },
2238
+ denyButton: { alignItems: "center", borderColor: Theme.colors.lineStrong, borderRadius: Theme.radius.sm, borderWidth: 1, justifyContent: "center", minHeight: 44, minWidth: 68, paddingHorizontal: Theme.spacing.md },
2239
+ denyText: { color: Theme.colors.ink, fontSize: 14, fontWeight: "600" },
2240
+ admitButton: { alignItems: "center", backgroundColor: Theme.colors.ink, borderRadius: Theme.radius.sm, justifyContent: "center", minHeight: 44, minWidth: 68, paddingHorizontal: Theme.spacing.md },
2241
+ admitText: { color: Theme.colors.surface, fontSize: 14, fontWeight: "700" },
2242
+ emptyState: { alignItems: "center", justifyContent: "center", minHeight: 220, paddingHorizontal: Theme.spacing["3xl"] },
2243
+ emptyTitle: { color: Theme.colors.ink, fontSize: 16, fontWeight: "700" },
2244
+ emptyText: { color: Theme.colors.ink2, fontSize: 14, marginTop: 6, textAlign: "center" },
2245
+ pressed: { opacity: 0.72, transform: [{ scale: 0.98 }] }
2246
+ });
2247
+
2248
+ // src/components/native-space-view/SpacePanelSheet.tsx
2249
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2250
+ function SpacePanelSheet({ controller }) {
2251
+ const visible = controller.panel !== null;
2252
+ const close = controller.closePanel;
2253
+ const isChat = controller.panel === "chat";
2254
+ return /* @__PURE__ */ jsx22(Modal5, { animationType: "slide", onRequestClose: close, transparent: true, visible, children: /* @__PURE__ */ jsxs16(View18, { style: styles18.modalRoot, children: [
2255
+ /* @__PURE__ */ jsx22(Pressable11, { accessibilityLabel: "Close panel", onPress: close, style: styles18.backdrop }),
2256
+ /* @__PURE__ */ jsxs16(SafeAreaView, { style: styles18.sheet, children: [
2257
+ /* @__PURE__ */ jsx22(SheetGrip, {}),
2258
+ /* @__PURE__ */ jsx22(SurfaceHeader, { closeLabel: `Close ${isChat ? "Chat" : "People"}`, count: !isChat ? controller.participantCount : void 0, onClose: close, title: isChat ? "Chat" : "People" }),
2259
+ isChat ? /* @__PURE__ */ jsx22(SpaceChatSheet, { controller }) : /* @__PURE__ */ jsx22(SpacePeopleSheet, { controller })
2260
+ ] })
2261
+ ] }) });
2262
+ }
2263
+ var styles18 = StyleSheet19.create({
2264
+ modalRoot: { flex: 1, justifyContent: "flex-end" },
2265
+ backdrop: { ...StyleSheet19.absoluteFillObject, backgroundColor: Theme.colors.darkOverlay22 },
2266
+ sheet: {
2267
+ backgroundColor: Theme.colors.surface,
2268
+ borderColor: Theme.colors.line,
2269
+ borderTopLeftRadius: Theme.radius.xl,
2270
+ borderTopRightRadius: Theme.radius.xl,
2271
+ elevation: 8,
2272
+ flex: 1,
2273
+ marginTop: 78,
2274
+ overflow: "hidden",
2275
+ paddingBottom: Platform9.OS === "android" ? Theme.spacing.sm : 0,
2276
+ shadowColor: Theme.colors.ink,
2277
+ shadowOffset: { height: -8, width: 0 },
2278
+ shadowOpacity: 0.12,
2279
+ shadowRadius: 22
2280
+ }
2281
+ });
2282
+
2283
+ // src/components/native-space-view/useSpaceViewController.ts
2284
+ import { useCallback as useCallback8, useEffect as useEffect7, useMemo as useMemo12, useState as useState8 } from "react";
2285
+ import { Alert as Alert2, Linking } from "react-native";
2286
+
2287
+ // src/components/native-space-view/diagnostics.ts
2288
+ function buildSpaceViewDiagnosticsSnapshot(input) {
2289
+ const availability = (enabled, feature) => enabled ? enabledAction() : disabledAction(`features.${feature}=false`);
2290
+ const screenShare = input.screenShareAvailability ?? availability(input.featureFlags.screenShare, "screenShare");
2291
+ return {
2292
+ canEndEpisode: input.canEndEpisode,
2293
+ participantCount: input.participantCount,
2294
+ raisedHandCount: input.raisedHandCount,
2295
+ unreadChatCount: input.unreadChatCount,
2296
+ featureFlags: input.featureFlags,
2297
+ actionAvailability: {
2298
+ screenShare: {
2299
+ ...screenShare,
2300
+ isActive: input.isScreenShareActive,
2301
+ isLocalSharing: input.isLocalScreenSharing,
2302
+ sharerParticipantId: input.screenShareSharerParticipantId,
2303
+ visibleInBottomDock: false,
2304
+ enabledInActionsSheet: screenShare.enabled
2305
+ },
2306
+ reactions: availability(input.featureFlags.reactions, "reactions"),
2307
+ handRaise: availability(input.featureFlags.handRaise, "handRaise"),
2308
+ chat: availability(input.featureFlags.chat, "chat"),
2309
+ participants: availability(input.featureFlags.participants, "participants"),
2310
+ whiteboard: availability(input.featureFlags.whiteboard, "whiteboard"),
2311
+ moderation: input.canModerate ? enabledAction() : { enabled: false, reason: "capability-unavailable", detail: "The local participant cannot moderate participants" }
2312
+ }
2313
+ };
2314
+ }
2315
+ function enabledAction() {
2316
+ return { enabled: true, reason: null, detail: null };
2317
+ }
2318
+ function disabledAction(detail) {
2319
+ return { enabled: false, reason: "feature-disabled", detail };
2320
+ }
2321
+
2322
+ // src/components/native-space-view/useSpaceViewDerived.ts
2323
+ import { useMemo as useMemo10 } from "react";
2324
+ import { useWindowDimensions as useWindowDimensions3 } from "react-native";
2325
+
2326
+ // src/utils/native-space-layout.ts
2327
+ var NATIVE_COMPACT_VIEWPORT_MAX_WIDTH = 768;
2328
+ var NATIVE_COMPACT_GRID_PAGE_SIZE = 4;
2329
+ function isSameParticipant(a, b) {
2330
+ return Boolean(a && b && a.id === b.id);
2331
+ }
2332
+ function isRenderableTrack(track) {
2333
+ if (!track) {
2334
+ return false;
2335
+ }
2336
+ const readyState = "readyState" in track ? track.readyState : void 0;
2337
+ return readyState == null || readyState === "live";
2338
+ }
2339
+ function normalizeStageParticipants(participants, localParticipant) {
2340
+ const seen = /* @__PURE__ */ new Set();
2341
+ const normalized = [];
2342
+ if (localParticipant) {
2343
+ normalized.push(localParticipant);
2344
+ seen.add(localParticipant.id);
2345
+ }
2346
+ for (const participant of participants) {
2347
+ if (seen.has(participant.id)) {
2348
+ continue;
2349
+ }
2350
+ normalized.push(participant);
2351
+ seen.add(participant.id);
2352
+ }
2353
+ return normalized;
2354
+ }
2355
+ function buildCompactParticipantPages(participants, pageSize = NATIVE_COMPACT_GRID_PAGE_SIZE) {
2356
+ if (participants.length === 0) {
2357
+ return [];
2358
+ }
2359
+ const pages = [];
2360
+ for (let index = 0; index < participants.length; index += pageSize) {
2361
+ pages.push(participants.slice(index, index + pageSize));
2362
+ }
2363
+ return pages;
2364
+ }
2365
+ function resolveScreenShareSource(participants, localParticipant, screenShare) {
2366
+ const sharerById = screenShare.sharerParticipantId ? participants.find((participant) => participant.id === screenShare.sharerParticipantId) ?? (localParticipant?.id === screenShare.sharerParticipantId ? localParticipant : null) : null;
2367
+ const localIsSharer = screenShare.isLocalSharing || isSameParticipant(sharerById, localParticipant);
2368
+ const fallbackTrack = sharerById?.screenShareTrack ?? null;
2369
+ const screenShareTrack = isRenderableTrack(screenShare.videoTrack) ? screenShare.videoTrack : isRenderableTrack(fallbackTrack) ? fallbackTrack : null;
2370
+ const screenSharer = sharerById ?? (localIsSharer ? localParticipant : null);
2371
+ return {
2372
+ screenSharer,
2373
+ screenShareTrack,
2374
+ isLocalScreenShare: Boolean(localIsSharer && screenShareTrack),
2375
+ showScreenShare: Boolean(screenShare.isActive && screenShareTrack)
2376
+ };
2377
+ }
2378
+ function resolveNativeSpaceLayout({ participants, localParticipant, screenShare, isWhiteboardOpen, isCompactViewport }) {
2379
+ const allParticipants = normalizeStageParticipants(participants, localParticipant);
2380
+ const gridPages = buildCompactParticipantPages(allParticipants);
2381
+ const { screenSharer, screenShareTrack, isLocalScreenShare, showScreenShare } = resolveScreenShareSource(participants, localParticipant, screenShare);
2382
+ const isSplit = !isCompactViewport && isWhiteboardOpen && showScreenShare;
2383
+ let primaryContent = "grid";
2384
+ if (isSplit) {
2385
+ primaryContent = "split";
2386
+ } else if (isWhiteboardOpen) {
2387
+ primaryContent = "whiteboard";
2388
+ } else if (showScreenShare) {
2389
+ primaryContent = isLocalScreenShare ? "screen-share-placeholder" : "screen-share";
2390
+ }
2391
+ return {
2392
+ allParticipants,
2393
+ gridPages,
2394
+ primaryContent,
2395
+ isStageMode: primaryContent !== "grid",
2396
+ isSplit,
2397
+ showScreenShare,
2398
+ isCompactViewport,
2399
+ screenSharer,
2400
+ screenShareTrack,
2401
+ isLocalScreenShare
2402
+ };
2403
+ }
2404
+
2405
+ // src/components/native-space-view/useSpaceViewDerived.ts
2406
+ function useSpaceViewDerived({ participants, localParticipant, screenShare, isWhiteboardOpen }) {
2407
+ const { width } = useWindowDimensions3();
2408
+ return useMemo10(
2409
+ () => resolveNativeSpaceLayout({
2410
+ participants,
2411
+ localParticipant,
2412
+ screenShare,
2413
+ isWhiteboardOpen,
2414
+ isCompactViewport: width < NATIVE_COMPACT_VIEWPORT_MAX_WIDTH
2415
+ }),
2416
+ [participants, localParticipant, screenShare, isWhiteboardOpen, width]
2417
+ );
2418
+ }
2419
+
2420
+ // src/components/native-space-view/useSpaceViewPanels.ts
2421
+ import { useCallback as useCallback7, useEffect as useEffect6, useMemo as useMemo11, useRef as useRef3, useState as useState7 } from "react";
2422
+ import { Alert, Share } from "react-native";
2423
+
2424
+ // src/hooks/useLayout.ts
2425
+ import { useCallback as useCallback6, useEffect as useEffect5, useState as useState6 } from "react";
2426
+ function useLayout({ layout: controlledLayout, onLayoutChange } = {}) {
2427
+ const [uncontrolledLayout, setUncontrolledLayout] = useState6(controlledLayout ?? "focus");
2428
+ const [isFullscreen, setFullscreen] = useState6(false);
2429
+ const layout = controlledLayout ?? uncontrolledLayout;
2430
+ useEffect5(() => {
2431
+ if (controlledLayout) setUncontrolledLayout(controlledLayout);
2432
+ }, [controlledLayout]);
2433
+ const setLayout = useCallback6(
2434
+ (nextLayout) => {
2435
+ if (!controlledLayout) setUncontrolledLayout(nextLayout);
2436
+ onLayoutChange?.(nextLayout);
2437
+ },
2438
+ [controlledLayout, onLayoutChange]
2439
+ );
2440
+ const toggleLayout = useCallback6(() => setLayout(layout === "grid" ? "focus" : "grid"), [layout, setLayout]);
2441
+ const toggleFullscreen = useCallback6(async () => setFullscreen((current) => !current), []);
2442
+ return { layout, isMobileView: true, isFullscreen, setLayout, toggleLayout, toggleFullscreen };
2443
+ }
2444
+
2445
+ // src/components/native-space-view/format-space-duration.ts
2446
+ function formatSpaceDuration(secondsElapsed) {
2447
+ return `${Math.floor(secondsElapsed / 60)}:${String(secondsElapsed % 60).padStart(2, "0")}`;
2448
+ }
2449
+
2450
+ // src/components/native-space-view/useSpaceViewPanels.ts
2451
+ var emptyElements = Object.freeze([]);
2452
+ var emptyParticipants = Object.freeze([]);
2453
+ function useSpaceViewPanels({ spaceName, inviteLink, layout: controlledLayout, onLayoutChange, canWhiteboard, canDraw, canClear, canEndEpisode, transport, onLeave, onEndEpisode, run, journeyContext, initialState, controlledState }) {
2454
+ const fixtureLayout = controlledState?.layout ?? initialState?.layout ?? controlledLayout;
2455
+ const layout = useLayout({ layout: fixtureLayout, onLayoutChange });
2456
+ const [panel, setPanel] = useState7(initialState?.panel ?? null);
2457
+ const [actionsOpen, setActionsOpen] = useState7(initialState?.actionsOpen ?? false);
2458
+ const [reactionPickerOpen, setReactionPickerOpen] = useState7(initialState?.reactionPickerOpen ?? false);
2459
+ const [secondsElapsed, setSecondsElapsed] = useState7(0);
2460
+ const [settingsOpen, setSettingsOpen] = useState7(initialState?.settingsOpen ?? false);
2461
+ const [whiteboardOpen, setWhiteboardOpen] = useState7(initialState?.whiteboardOpen ?? false);
2462
+ const generatedJourneyId = useRef3(globalThis.crypto?.randomUUID?.() ?? `native-whiteboard-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2463
+ useEffect6(() => {
2464
+ const durationSeconds = Math.max(0, Math.floor(controlledState?.durationSeconds ?? initialState?.durationSeconds ?? 0));
2465
+ const startedAt = Date.now() - durationSeconds * 1e3;
2466
+ const update = () => setSecondsElapsed(Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)));
2467
+ update();
2468
+ const timer = globalThis.setInterval(update, 1e3);
2469
+ return () => globalThis.clearInterval(timer);
2470
+ }, [controlledState?.durationSeconds, initialState?.durationSeconds]);
2471
+ useEffect6(() => {
2472
+ if (controlledState?.panel !== void 0) setPanel(controlledState.panel ?? null);
2473
+ if (controlledState?.actionsOpen !== void 0) setActionsOpen(controlledState.actionsOpen);
2474
+ if (controlledState?.reactionPickerOpen !== void 0) setReactionPickerOpen(controlledState.reactionPickerOpen);
2475
+ if (controlledState?.settingsOpen !== void 0) setSettingsOpen(controlledState.settingsOpen);
2476
+ if (controlledState?.whiteboardOpen !== void 0) setWhiteboardOpen(controlledState.whiteboardOpen);
2477
+ }, [controlledState]);
2478
+ const whiteboard = useMemo11(
2479
+ () => ({
2480
+ isOpen: canWhiteboard && whiteboardOpen,
2481
+ canDraw: canWhiteboard && canDraw,
2482
+ canClear: canWhiteboard && canClear,
2483
+ elements: emptyElements,
2484
+ openParticipants: emptyParticipants,
2485
+ transport,
2486
+ journeyId: journeyContext?.journeyId ?? generatedJourneyId.current,
2487
+ ...journeyContext?.traceparent ? { traceparent: journeyContext.traceparent } : {},
2488
+ ...journeyContext?.tracestate ? { tracestate: journeyContext.tracestate } : {},
2489
+ ...journeyContext ? { onMetric: journeyContext.recordWhiteboardMetric } : {},
2490
+ open: () => canWhiteboard && setWhiteboardOpen(true),
2491
+ close: () => setWhiteboardOpen(false),
2492
+ toggle: () => canWhiteboard && setWhiteboardOpen((value) => !value),
2493
+ requestSync: () => void run(() => transport?.requestSnapshot()),
2494
+ clear: () => void run(() => transport?.clear())
2495
+ }),
2496
+ [canClear, canDraw, canWhiteboard, journeyContext, run, transport, whiteboardOpen]
2497
+ );
2498
+ const handleLeave = useCallback7(() => {
2499
+ const buttons = [
2500
+ { text: "Cancel", style: "cancel" },
2501
+ { text: "Leave", style: "destructive", onPress: () => void run(onLeave) }
2502
+ ];
2503
+ if (canEndEpisode && onEndEpisode) {
2504
+ buttons.splice(1, 0, {
2505
+ text: "End for All",
2506
+ style: "destructive",
2507
+ onPress: () => void run(onEndEpisode)
2508
+ });
2509
+ }
2510
+ Alert.alert("Leave Space?", "Choose how you want to leave.", buttons);
2511
+ }, [canEndEpisode, onEndEpisode, onLeave, run]);
2512
+ const handleInviteParticipants = useCallback7(() => {
2513
+ void run(async () => {
2514
+ if (!inviteLink) throw new Error("The Space invite is not ready yet.");
2515
+ await Share.share({ message: inviteLink, title: spaceName || "Chalk Space", url: inviteLink });
2516
+ });
2517
+ }, [inviteLink, run, spaceName]);
2518
+ return {
2519
+ layout,
2520
+ panel,
2521
+ secondsElapsed,
2522
+ formattedDuration: formatSpaceDuration(secondsElapsed),
2523
+ actionsOpen,
2524
+ reactionPickerOpen,
2525
+ whiteboard,
2526
+ settingsOpen,
2527
+ setActionsOpen,
2528
+ setReactionPickerOpen,
2529
+ handleLeave,
2530
+ openPanel: (nextPanel) => {
2531
+ setActionsOpen(false);
2532
+ if (nextPanel === "whiteboard") whiteboard.open();
2533
+ else setPanel(nextPanel);
2534
+ },
2535
+ closePanel: () => setPanel(null),
2536
+ handleInviteParticipants
2537
+ };
2538
+ }
2539
+
2540
+ // src/components/native-space-view/screen-share-availability.ts
2541
+ function resolveNativeScreenShareAvailability({ featureEnabled }) {
2542
+ if (!featureEnabled) {
2543
+ return {
2544
+ enabled: false,
2545
+ reason: "feature-disabled",
2546
+ detail: "features.screenShare=false in SpaceView props"
2547
+ };
2548
+ }
2549
+ return {
2550
+ enabled: true,
2551
+ reason: null,
2552
+ detail: null
2553
+ };
2554
+ }
2555
+
2556
+ // src/components/native-space-view/space-chat-attachments.ts
2557
+ import { CHALK_CHAT_ATTACHMENT_LIMITS, CHALK_CHAT_ATTACHMENT_MIME_TYPES } from "@q9labsai/chalk-client";
2558
+ var allowedMimeTypes = new Set(CHALK_CHAT_ATTACHMENT_MIME_TYPES);
2559
+ var encoder = new TextEncoder();
2560
+ function describeChatUploadFile(file) {
2561
+ if ("bytes" in file) {
2562
+ return { file, fileName: file.fileName, mimeType: file.mimeType, byteLength: file.bytes.byteLength };
2563
+ }
2564
+ return { file, fileName: file.name, mimeType: file.type, byteLength: file.size };
2565
+ }
2566
+ function validateChatFileDraft(draft) {
2567
+ if (!draft.fileName || encoder.encode(draft.fileName).byteLength > CHALK_CHAT_ATTACHMENT_LIMITS.maximumFileNameBytes) return "This file name is too long.";
2568
+ if (!Number.isSafeInteger(draft.byteLength) || draft.byteLength < 1 || draft.byteLength > CHALK_CHAT_ATTACHMENT_LIMITS.maximumByteLength) return "This file is too large or empty.";
2569
+ if (!allowedMimeTypes.has(draft.mimeType)) return "This file type is not supported in Space chat.";
2570
+ return null;
2571
+ }
2572
+ function normalizeChatFileDrafts(files) {
2573
+ if (files.length > CHALK_CHAT_ATTACHMENT_LIMITS.maximumPerMessage) {
2574
+ return { files: [], error: `You can attach up to ${CHALK_CHAT_ATTACHMENT_LIMITS.maximumPerMessage} files per message.` };
2575
+ }
2576
+ const drafts = files.map(describeChatUploadFile);
2577
+ const error = drafts.map(validateChatFileDraft).find((message) => message !== null) ?? null;
2578
+ return error ? { files: [], error } : { files: drafts, error: null };
2579
+ }
2580
+ async function uploadAndSendNativeChatAttachments(files, text, upload, send) {
2581
+ const attachments = await Promise.all(files.map((draft) => upload(draft.file)));
2582
+ await send({ text, ...attachments.length ? { attachments } : {} });
2583
+ }
2584
+
2585
+ // src/components/native-space-view/useSpaceViewController.ts
2586
+ var spaceReactions = /* @__PURE__ */ new Set(["\u{1F44D}", "\u2764\uFE0F", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F389}"]);
2587
+ function useSpaceViewController({ spaceName, inviteLink, layout: controlledLayout, onLayoutChange, features, onLeave, onEndEpisode, onDiagnosticsChange, pickChatFiles: pickChatFilesInput }) {
2588
+ const client = useSpaceClient();
2589
+ const self = useSelf();
2590
+ const participantSlice = useParticipants();
2591
+ const media = useMedia();
2592
+ const chatSlice = useChat();
2593
+ const reactionSlice = useReactions();
2594
+ const whiteboardSlice = useWhiteboard();
2595
+ const journeyContext = getNativeJourneyContext(client);
2596
+ const [actionsOpen, setActionsOpen] = useState8(false);
2597
+ const [reactionPickerOpen, setReactionPickerOpen] = useState8(false);
2598
+ const [chatDraft, setChatDraft] = useState8("");
2599
+ const [chatAttachments, setChatAttachments] = useState8([]);
2600
+ const [chatAttachmentError, setChatAttachmentError] = useState8(null);
2601
+ const [chatAttachmentPicking, setChatAttachmentPicking] = useState8(false);
2602
+ const [chatAttachmentUploading, setChatAttachmentUploading] = useState8(false);
2603
+ const run = useCallback8(async (action) => {
2604
+ try {
2605
+ await action();
2606
+ } catch (cause) {
2607
+ Alert2.alert("Action failed", cause instanceof Error ? cause.message : "Chalk could not complete the action.");
2608
+ }
2609
+ }, []);
2610
+ const localParticipantId = self.participantId;
2611
+ const participants = useMemo12(
2612
+ () => participantSlice.roster.map((participant) => {
2613
+ const local = participant.participantId === localParticipantId;
2614
+ const remoteMedia = media.remote.filter((publication) => publication.participantId === participant.participantId);
2615
+ return {
2616
+ ...participant,
2617
+ id: participant.participantId,
2618
+ audioEnabled: local ? media.local.microphone.state === "enabled" || media.local.microphone.state === "requesting" : participant.media.microphone === "active",
2619
+ videoEnabled: local ? media.local.camera.state === "enabled" || media.local.camera.state === "requesting" : participant.media.camera === "active",
2620
+ audioTrack: local ? media.local.microphone.track : remoteMedia.find((publication) => publication.source === "microphone")?.track ?? null,
2621
+ videoTrack: local ? media.local.camera.track : remoteMedia.find((publication) => publication.source === "camera")?.track ?? null,
2622
+ screenShareTrack: local ? media.screenShare.track : remoteMedia.find((publication) => publication.source === "screen")?.track ?? null
2623
+ };
2624
+ }),
2625
+ [localParticipantId, media.local.camera, media.local.microphone, media.remote, media.screenShare.track, participantSlice.roster]
2626
+ );
2627
+ const localParticipant = useMemo12(() => participants.find((participant) => participant.id === localParticipantId) ?? null, [localParticipantId, participants]);
2628
+ const spaceParticipants = useMemo12(
2629
+ () => ({
2630
+ participants,
2631
+ localParticipant,
2632
+ remoteParticipants: participants.filter((participant) => participant.id !== localParticipantId),
2633
+ activeSpeaker: null,
2634
+ count: participants.length,
2635
+ participantCount: participants.length,
2636
+ getParticipant: (participantId) => participants.find((participant) => participant.id === participantId),
2637
+ updateDisplayName: (displayName) => client.participants.renameSelf(displayName)
2638
+ }),
2639
+ [client.participants, localParticipant, localParticipantId, participants]
2640
+ );
2641
+ const isLocalSharing = media.screenShare.state === "enabled" || media.screenShare.state === "requesting";
2642
+ const remoteScreenShare = useMemo12(() => media.remote.find((publication) => publication.source === "screen") ?? null, [media.remote]);
2643
+ const screenShare = useMemo12(
2644
+ () => ({
2645
+ isActive: isLocalSharing || remoteScreenShare !== null,
2646
+ isStarting: media.screenShare.state === "requesting",
2647
+ isLocalSharing,
2648
+ sharerParticipantId: isLocalSharing ? localParticipantId : remoteScreenShare?.participantId ?? null,
2649
+ videoTrack: isLocalSharing ? media.screenShare.track : remoteScreenShare?.track ?? null,
2650
+ audioTrack: null,
2651
+ start: async () => {
2652
+ await client.media.setScreenShareEnabled(true);
2653
+ return true;
2654
+ },
2655
+ stop: () => client.media.setScreenShareEnabled(false),
2656
+ toggle: async () => {
2657
+ const enabled = !isLocalSharing;
2658
+ await client.media.setScreenShareEnabled(enabled);
2659
+ return enabled;
2660
+ }
2661
+ }),
2662
+ [client.media, isLocalSharing, localParticipantId, media.screenShare.state, media.screenShare.track, remoteScreenShare]
2663
+ );
2664
+ const interactionState = useMemo12(() => {
2665
+ const raisedHands = participantSlice.roster.filter((participant) => participant.handRaised).map((participant) => participant.participantId);
2666
+ const activeReactions = reactionSlice.active.map((reaction) => ({
2667
+ id: reaction.eventId,
2668
+ emoji: reaction.reaction,
2669
+ participantId: reaction.participantId,
2670
+ participantName: reaction.displayName
2671
+ }));
2672
+ return {
2673
+ isHandRaised: self.handRaised,
2674
+ raisedHands,
2675
+ raisedHandCount: raisedHands.length,
2676
+ activeReactions,
2677
+ reactionEnabled: self.can("sendReaction"),
2678
+ raiseHand: () => client.participants.raiseHand(),
2679
+ lowerHand: () => client.participants.lowerHand(),
2680
+ toggleHand: () => self.handRaised ? client.participants.lowerHand() : client.participants.raiseHand(),
2681
+ sendReaction: (reaction) => client.reactions.send(reaction)
2682
+ };
2683
+ }, [client.participants, client.reactions, participantSlice.roster, reactionSlice.active, self]);
2684
+ const chat = useMemo12(() => {
2685
+ const messages = chatSlice.messages.map((message) => ({
2686
+ id: message.messageId,
2687
+ sequence: message.sequence,
2688
+ senderId: message.participantId,
2689
+ senderName: message.displayName,
2690
+ text: message.text,
2691
+ content: message.text,
2692
+ attachments: message.attachments,
2693
+ readBy: chatSlice.readReceipts.filter((receipt) => receipt.participantId !== message.participantId && receipt.participantId !== localParticipantId && sequenceAtOrAfter(receipt.readThroughSequence, message.sequence)).map((receipt) => ({
2694
+ ...receipt,
2695
+ displayName: participantSlice.roster.find((participant) => participant.participantId === receipt.participantId)?.displayName ?? "Participant"
2696
+ })),
2697
+ timestamp: Date.parse(message.createdAt)
2698
+ }));
2699
+ const pendingMessages = chatSlice.pendingSends.map((pending) => ({ ...pending, state: pending.status }));
2700
+ const sendMessage = (content) => client.chat.send(typeof content === "string" ? { text: content } : content).then(() => void 0);
2701
+ const markAsRead = (throughSequence) => {
2702
+ const target = throughSequence ? chatSlice.messages.find((message) => message.sequence === throughSequence) : chatSlice.messages.at(-1);
2703
+ return target ? client.chat.markRead(target.messageId) : Promise.resolve(null);
2704
+ };
2705
+ return {
2706
+ messages,
2707
+ isEnabled: self.can("sendChat"),
2708
+ count: messages.length,
2709
+ unreadCount: chatSlice.unreadCount,
2710
+ pendingMessages,
2711
+ hasMore: chatSlice.pagination.hasOlder,
2712
+ isLoadingOlder: chatSlice.status === "loading",
2713
+ sendMessage,
2714
+ retryMessage: (clientMessageId) => {
2715
+ const pending = chatSlice.pendingSends.find((message) => message.clientMessageId === clientMessageId);
2716
+ return pending ? client.chat.send({ text: pending.text, attachments: pending.attachments }).then(() => void 0) : Promise.reject(new Error("The pending message is no longer available."));
2717
+ },
2718
+ loadOlderMessages: () => client.chat.loadOlder().then(() => void 0),
2719
+ reactToMessage: () => {
2720
+ throw new Error("Per-message reactions are not part of the actions contract.");
2721
+ },
2722
+ markAsRead,
2723
+ markAsHidden: markAsRead,
2724
+ getMessage: (id) => messages.find((message) => message.id === id)
2725
+ };
2726
+ }, [chatSlice, client.chat, localParticipantId, participantSlice.roster, self]);
2727
+ const canWhiteboard = features?.whiteboard !== false && whiteboardSlice.engine.status !== "unsubscribed";
2728
+ const canDraw = canWhiteboard && self.can("drawWhiteboard");
2729
+ const canClear = canWhiteboard && self.can("manageWhiteboard");
2730
+ const whiteboardTransport = useMemo12(() => client.whiteboard.transport(), [client.whiteboard, whiteboardSlice.engine.status]);
2731
+ const canEndEpisode = self.can("endEpisode");
2732
+ const screenShareAvailability = useMemo12(() => resolveNativeScreenShareAvailability({ featureEnabled: features?.screenShare !== false }), [features?.screenShare]);
2733
+ const capabilities = useMemo12(
2734
+ () => ({
2735
+ canEndEpisode,
2736
+ canChat: features?.chat !== false && self.can("sendChat"),
2737
+ canParticipants: features?.participants !== false,
2738
+ canScreenShare: screenShareAvailability.enabled && self.can("publishScreen"),
2739
+ canReactions: features?.reactions !== false && self.can("sendReaction"),
2740
+ canHandRaise: features?.handRaise !== false && self.can("raiseHand"),
2741
+ canInvite: features?.info !== false && Boolean(inviteLink),
2742
+ canSettings: features?.settings !== false,
2743
+ canWhiteboard,
2744
+ canManageAdmission: features?.admission !== false && self.can("manageAdmission"),
2745
+ canRequestMedia: self.can("requestMediaOthers"),
2746
+ canMuteParticipants: self.can("muteOthers"),
2747
+ canRemoveParticipants: self.can("removeParticipant"),
2748
+ canStopParticipantCamera: self.can("stopVideoOthers"),
2749
+ canStopParticipantScreenShare: self.can("stopScreenOthers"),
2750
+ canModerate: self.can("manageAdmission") || self.can("assignRoles") || self.can("requestMediaOthers") || self.can("muteOthers") || self.can("removeParticipant") || self.can("stopVideoOthers") || self.can("stopScreenOthers"),
2751
+ screenShareAvailability
2752
+ }),
2753
+ [canEndEpisode, canWhiteboard, features?.admission, features?.chat, features?.handRaise, features?.info, features?.participants, features?.reactions, features?.settings, inviteLink, screenShareAvailability, self]
2754
+ );
2755
+ const spacePanels = useSpaceViewPanels({
2756
+ spaceName,
2757
+ inviteLink,
2758
+ layout: controlledLayout,
2759
+ onLayoutChange,
2760
+ canWhiteboard,
2761
+ canDraw,
2762
+ canClear,
2763
+ canEndEpisode,
2764
+ transport: whiteboardTransport,
2765
+ onLeave,
2766
+ onEndEpisode,
2767
+ run,
2768
+ journeyContext
2769
+ });
2770
+ const derived = useSpaceViewDerived({ participants, localParticipant, screenShare, isWhiteboardOpen: spacePanels.whiteboard.isOpen });
2771
+ useEffect7(() => {
2772
+ const request = media.incomingRequests[0];
2773
+ if (!request) return;
2774
+ Alert2.alert(request.kind === "unmute" ? "Unmute request" : "Camera request", `${request.actorDisplayName ?? "A Space organizer"} is asking you to ${request.kind === "unmute" ? "unmute" : "start your camera"}.`, [
2775
+ { text: "Not now", style: "cancel", onPress: () => void run(() => client.media.declineRequest(request.requestId)) },
2776
+ { text: "Allow", onPress: () => void run(() => client.media.acceptRequest(request.requestId)) }
2777
+ ]);
2778
+ }, [client.media, media.incomingRequests, run]);
2779
+ const spaceDiagnostics = useMemo12(
2780
+ () => buildSpaceViewDiagnosticsSnapshot({
2781
+ featureFlags: {
2782
+ chat: capabilities.canChat,
2783
+ participants: capabilities.canParticipants,
2784
+ screenShare: capabilities.canScreenShare,
2785
+ reactions: capabilities.canReactions,
2786
+ handRaise: capabilities.canHandRaise,
2787
+ whiteboard: capabilities.canWhiteboard
2788
+ },
2789
+ canEndEpisode: capabilities.canEndEpisode,
2790
+ participantCount: spaceParticipants.participantCount,
2791
+ raisedHandCount: interactionState.raisedHandCount,
2792
+ unreadChatCount: chat.unreadCount,
2793
+ isScreenShareActive: screenShare.isActive,
2794
+ isLocalScreenSharing: screenShare.isLocalSharing,
2795
+ screenShareSharerParticipantId: screenShare.sharerParticipantId,
2796
+ canModerate: capabilities.canModerate,
2797
+ screenShareAvailability
2798
+ }),
2799
+ [capabilities, chat.unreadCount, interactionState.raisedHandCount, spaceParticipants.participantCount, screenShare.isActive, screenShare.isLocalSharing, screenShare.sharerParticipantId, screenShareAvailability]
2800
+ );
2801
+ useEffect7(() => onDiagnosticsChange?.(spaceDiagnostics), [onDiagnosticsChange, spaceDiagnostics]);
2802
+ const pickChatFiles = useCallback8(async () => {
2803
+ if (!pickChatFilesInput) return;
2804
+ setChatAttachmentPicking(true);
2805
+ try {
2806
+ const picked = normalizeChatFileDrafts(await pickChatFilesInput());
2807
+ if (picked.error) {
2808
+ setChatAttachmentError(picked.error);
2809
+ return;
2810
+ }
2811
+ const combined = normalizeChatFileDrafts([...chatAttachments.map((draft) => draft.file), ...picked.files.map((draft) => draft.file)]);
2812
+ if (combined.error) {
2813
+ setChatAttachmentError(combined.error);
2814
+ return;
2815
+ }
2816
+ setChatAttachmentError(null);
2817
+ setChatAttachments(combined.files);
2818
+ } catch (cause) {
2819
+ setChatAttachmentError(cause instanceof Error ? cause.message : "Could not read the selected files.");
2820
+ } finally {
2821
+ setChatAttachmentPicking(false);
2822
+ }
2823
+ }, [chatAttachments, pickChatFilesInput]);
2824
+ const removeChatAttachment = useCallback8((index) => {
2825
+ setChatAttachments((current) => current.filter((_, currentIndex) => currentIndex !== index));
2826
+ setChatAttachmentError(null);
2827
+ }, []);
2828
+ const sendChatMessage = useCallback8(() => {
2829
+ const text = chatDraft.trim();
2830
+ if (!text && chatAttachments.length === 0) return;
2831
+ void run(async () => {
2832
+ setChatAttachmentUploading(true);
2833
+ setChatAttachmentError(null);
2834
+ try {
2835
+ await uploadAndSendNativeChatAttachments(chatAttachments, text, client.chat.files.upload, chat.sendMessage);
2836
+ setChatDraft("");
2837
+ setChatAttachments([]);
2838
+ } catch (cause) {
2839
+ setChatAttachmentError(cause instanceof Error ? cause.message : "Could not send the attachments.");
2840
+ throw cause;
2841
+ } finally {
2842
+ setChatAttachmentUploading(false);
2843
+ }
2844
+ });
2845
+ }, [chat, chatAttachments, chatDraft, client.chat.files, run]);
2846
+ return {
2847
+ simulatorMediaDisabled: isIosSimulator(),
2848
+ spaceName: spaceName || "Space",
2849
+ panel: spacePanels.panel,
2850
+ selfName: self.displayName || "Participant",
2851
+ isMuted: !(media.local.microphone.state === "enabled" || media.local.microphone.state === "requesting"),
2852
+ isCameraOff: !(media.local.camera.state === "enabled" || media.local.camera.state === "requesting"),
2853
+ handRaised: interactionState.isHandRaised,
2854
+ raisedHandCount: interactionState.raisedHandCount,
2855
+ activeReactions: interactionState.activeReactions.slice(-3),
2856
+ secondsElapsed: spacePanels.secondsElapsed,
2857
+ formattedDuration: spacePanels.formattedDuration,
2858
+ actionsOpen,
2859
+ reactionPickerOpen,
2860
+ chatDraft,
2861
+ chatAttachments,
2862
+ chatAttachmentError,
2863
+ chatAttachmentPicking,
2864
+ chatAttachmentUploading,
2865
+ canPickChatFiles: Boolean(pickChatFilesInput),
2866
+ participantCount: spaceParticipants.participantCount,
2867
+ canChat: capabilities.canChat,
2868
+ canParticipants: capabilities.canParticipants,
2869
+ canScreenShare: capabilities.canScreenShare,
2870
+ canReactions: capabilities.canReactions,
2871
+ canHandRaise: capabilities.canHandRaise,
2872
+ canInvite: capabilities.canInvite,
2873
+ canSettings: capabilities.canSettings,
2874
+ canWhiteboard: capabilities.canWhiteboard,
2875
+ canManageAdmission: capabilities.canManageAdmission,
2876
+ canRequestMedia: capabilities.canRequestMedia,
2877
+ canMuteParticipants: capabilities.canMuteParticipants,
2878
+ canRemoveParticipants: capabilities.canRemoveParticipants,
2879
+ canStopParticipantCamera: capabilities.canStopParticipantCamera,
2880
+ canStopParticipantScreenShare: capabilities.canStopParticipantScreenShare,
2881
+ admissionRequests: participantSlice.admissionQueue,
2882
+ spaceDiagnostics,
2883
+ participants: spaceParticipants,
2884
+ settings: {
2885
+ displayName: self.displayName ?? "",
2886
+ microphoneEnabled: media.local.microphone.state === "enabled" || media.local.microphone.state === "requesting",
2887
+ cameraEnabled: media.local.camera.state === "enabled" || media.local.camera.state === "requesting",
2888
+ devices: media.devices,
2889
+ selection: media.selection,
2890
+ updateDisplayName: (displayName) => {
2891
+ const nextDisplayName = displayName.trim();
2892
+ if (nextDisplayName) void run(() => client.participants.renameSelf(nextDisplayName));
2893
+ },
2894
+ selectMicrophone: (deviceId) => void run(() => client.media.selectMicrophone(deviceId)),
2895
+ selectCamera: (deviceId) => void run(() => client.media.selectCamera(deviceId)),
2896
+ selectSpeaker: (deviceId) => void run(() => client.media.selectSpeaker(deviceId))
2897
+ },
2898
+ chat,
2899
+ interactions: interactionState,
2900
+ screenShare,
2901
+ layout: spacePanels.layout,
2902
+ whiteboard: spacePanels.whiteboard,
2903
+ derived,
2904
+ setActionsOpen,
2905
+ setReactionPickerOpen,
2906
+ setChatDraft,
2907
+ pickChatFiles,
2908
+ removeChatAttachment,
2909
+ handleLeave: spacePanels.handleLeave,
2910
+ openPanel: spacePanels.openPanel,
2911
+ closePanel: spacePanels.closePanel,
2912
+ handleInviteParticipants: spacePanels.handleInviteParticipants,
2913
+ toggleAudio: () => void run(() => client.media.setMicrophoneEnabled(!(media.local.microphone.state === "enabled" || media.local.microphone.state === "requesting"))),
2914
+ toggleVideo: () => void run(() => client.media.setCameraEnabled(!(media.local.camera.state === "enabled" || media.local.camera.state === "requesting"))),
2915
+ toggleScreenShare: () => void run(screenShare.toggle),
2916
+ toggleHand: () => void run(interactionState.toggleHand),
2917
+ sendReaction: (reaction) => {
2918
+ if (!spaceReactions.has(reaction)) return;
2919
+ void run(() => interactionState.sendReaction(reaction));
2920
+ },
2921
+ sendChatMessage,
2922
+ openChatAttachment: (attachmentId) => {
2923
+ const attachment = chat.messages.flatMap((message) => message.attachments).find((candidate) => candidate.attachmentId === attachmentId);
2924
+ if (attachment) void run(() => Linking.openURL(client.chat.files.url(attachment)));
2925
+ },
2926
+ markChatMessageVisible: (sequence) => void run(() => chat.markAsRead(sequence)),
2927
+ admitParticipant: (requestId) => void run(() => client.participants.admit(requestId)),
2928
+ denyAdmission: (requestId) => void run(() => client.participants.deny(requestId)),
2929
+ removeParticipant: (participantId) => void run(() => client.participants.remove(participantId)),
2930
+ muteParticipant: (participantId) => void run(() => client.participants.mute(participantId)),
2931
+ requestUnmuteParticipant: (participantId) => void run(() => client.participants.requestMedia(participantId, "microphone")),
2932
+ requestStartParticipantCamera: (participantId) => void run(() => client.participants.requestMedia(participantId, "camera")),
2933
+ stopParticipantCamera: (participantId) => void run(() => client.participants.stopVideo(participantId)),
2934
+ stopParticipantScreenShare: (participantId) => void run(() => client.participants.stopScreenShare(participantId))
2935
+ };
2936
+ }
2937
+ function sequenceAtOrAfter(value, floor) {
2938
+ const normalizedValue = value.replace(/^0+(?=\d)/, "");
2939
+ const normalizedFloor = floor.replace(/^0+(?=\d)/, "");
2940
+ return normalizedValue.length > normalizedFloor.length || normalizedValue.length === normalizedFloor.length && normalizedValue >= normalizedFloor;
2941
+ }
2942
+
2943
+ // src/components/SpaceView.shared.tsx
2944
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
2945
+ function SpaceViewShared(props) {
2946
+ const controller = useSpaceViewController(props);
2947
+ const theme = useNativeTheme();
2948
+ const toggleMedia = (action) => {
2949
+ if (controller.simulatorMediaDisabled) {
2950
+ Alert3.alert("Media unavailable", getIosSimulatorMediaMessage());
2951
+ return;
2952
+ }
2953
+ action();
2954
+ };
2955
+ return /* @__PURE__ */ jsxs17(View19, { style: [styles19.space, { backgroundColor: theme.colors.darkCanvas }], children: [
2956
+ /* @__PURE__ */ jsx23(SpaceTopBarAndroid, { formattedDuration: controller.formattedDuration, logoUrl: props.logoUrl, participantCount: controller.participantCount, spaceName: controller.spaceName }),
2957
+ props.reconnecting ? /* @__PURE__ */ jsx23(View19, { accessibilityLiveRegion: "polite", style: [styles19.recovery, { backgroundColor: theme.colors.primary }], children: /* @__PURE__ */ jsx23(Text14, { style: [styles19.recoveryText, { color: theme.colors.primaryForeground }], children: "Reconnecting\u2026 controls will resume shortly." }) }) : null,
2958
+ /* @__PURE__ */ jsx23(View19, { style: styles19.stage, children: controller.whiteboard.isOpen ? /* @__PURE__ */ jsx23(SpaceWhiteboardSurface, { whiteboard: controller.whiteboard }) : controller.derived.isStageMode || controller.layout.layout !== "grid" ? /* @__PURE__ */ jsx23(
2959
+ SpaceStageAndroid,
2960
+ {
2961
+ activeReactions: controller.activeReactions,
2962
+ handRaised: controller.handRaised,
2963
+ isCompactViewport: controller.derived.isCompactViewport,
2964
+ isMuted: controller.isMuted,
2965
+ layoutMode: controller.layout.layout,
2966
+ primaryContent: controller.derived.primaryContent,
2967
+ raisedHandCount: controller.raisedHandCount,
2968
+ screenShareTrack: controller.derived.screenShareTrack,
2969
+ screenSharer: controller.derived.screenSharer,
2970
+ selfName: controller.selfName,
2971
+ stripParticipants: controller.derived.allParticipants,
2972
+ whiteboard: {
2973
+ isOpen: controller.whiteboard.isOpen,
2974
+ canDraw: controller.whiteboard.canDraw,
2975
+ elementCount: controller.whiteboard.elements.length,
2976
+ participantCount: controller.whiteboard.openParticipants.length
2977
+ }
2978
+ }
2979
+ ) : /* @__PURE__ */ jsx23(SpaceGridAndroid, { gridPages: controller.derived.gridPages, participants: controller.derived.allParticipants }) }),
2980
+ /* @__PURE__ */ jsx23(
2981
+ SpaceBottomDockAndroid,
2982
+ {
2983
+ isCameraOff: controller.isCameraOff,
2984
+ isMuted: controller.isMuted,
2985
+ onLeave: controller.handleLeave,
2986
+ onOpenChat: controller.canChat ? () => controller.openPanel("chat") : void 0,
2987
+ onOpenMore: () => controller.setActionsOpen(true),
2988
+ onToggleAudio: () => toggleMedia(controller.toggleAudio),
2989
+ onToggleVideo: () => toggleMedia(controller.toggleVideo),
2990
+ simulatorMediaDisabled: controller.simulatorMediaDisabled,
2991
+ unreadChatCount: controller.chat.unreadCount
2992
+ }
2993
+ ),
2994
+ /* @__PURE__ */ jsx23(SpaceActionMenu, { controller }),
2995
+ controller.panel === "settings" ? /* @__PURE__ */ jsx23(SettingsSheet, { controller, isOpen: true, onClose: controller.closePanel }) : /* @__PURE__ */ jsx23(SpacePanelSheet, { controller }),
2996
+ /* @__PURE__ */ jsx23(ReactionPicker, { isOpen: controller.reactionPickerOpen, onClose: () => controller.setReactionPickerOpen(false), onSelect: (reaction) => selectSpaceReaction(controller, reaction) })
2997
+ ] });
2998
+ }
2999
+ var styles19 = StyleSheet20.create({
3000
+ space: { flex: 1, backgroundColor: Theme.colors.darkCanvas },
3001
+ stage: { flex: 1, width: "100%", overflow: "hidden", justifyContent: "center" },
3002
+ recovery: { alignItems: "center", paddingHorizontal: 16, paddingVertical: 8 },
3003
+ recoveryText: { fontSize: 13, fontWeight: "700" }
3004
+ });
3005
+
3006
+ // src/components/SpaceView.tsx
3007
+ import { jsx as jsx24 } from "react/jsx-runtime";
3008
+ function SpaceView(props) {
3009
+ switch (resolvePlatformVariant()) {
3010
+ case "ios-pad":
3011
+ return /* @__PURE__ */ jsx24(SpaceViewShared, { ...props });
3012
+ case "ios-phone":
3013
+ return /* @__PURE__ */ jsx24(SpaceViewShared, { ...props });
3014
+ case "macos":
3015
+ return /* @__PURE__ */ jsx24(SpaceViewShared, { ...props });
3016
+ case "tvos":
3017
+ case "android":
3018
+ default:
3019
+ return /* @__PURE__ */ jsx24(SpaceViewShared, { ...props });
3020
+ }
3021
+ }
3022
+
3023
+ // src/components/EntranceView.android.tsx
3024
+ import ArrowLeft01Icon from "@hugeicons/core-free-icons/dist/esm/ArrowLeft01Icon";
3025
+ import Mic01Icon4 from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
3026
+ import MicOff01Icon7 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
3027
+ import UserIcon2 from "@hugeicons/core-free-icons/dist/esm/UserIcon";
3028
+ import Video01Icon5 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
3029
+ import VideoOffIcon4 from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
3030
+ import { HugeiconsIcon as HugeiconsIcon11 } from "@hugeicons/react-native";
3031
+ import { KeyboardAvoidingView as KeyboardAvoidingView2, Platform as Platform10, Pressable as Pressable12, StyleSheet as StyleSheet21, Text as Text15, TextInput as TextInput2, View as View20 } from "react-native";
3032
+
3033
+ // src/components/native-entrance/useEntranceController.ts
3034
+ import { useMemo as useMemo14, useSyncExternalStore as useSyncExternalStore4 } from "react";
3035
+
3036
+ // src/hooks/useEntrancePreview.ts
3037
+ import { useMemo as useMemo13, useSyncExternalStore as useSyncExternalStore3 } from "react";
3038
+
3039
+ // src/hooks/entrance-preview-store.ts
3040
+ function stopPreviewTracks(stream) {
3041
+ stream?.getTracks?.().forEach((track) => {
3042
+ try {
3043
+ track.stop();
3044
+ } catch {
3045
+ }
3046
+ });
3047
+ }
3048
+ function createEntrancePreviewStore(options) {
3049
+ const initialSnapshot = {
3050
+ previewStream: null,
3051
+ previewError: options.enabled && options.simulatorVideoDisabled ? options.simulatorVideoMessage : null
3052
+ };
3053
+ let snapshot = initialSnapshot;
3054
+ let activeStream = null;
3055
+ let requestGeneration = 0;
3056
+ const listeners = /* @__PURE__ */ new Set();
3057
+ const notify = () => {
3058
+ listeners.forEach((listener) => listener());
3059
+ };
3060
+ const reset = () => {
3061
+ requestGeneration += 1;
3062
+ stopPreviewTracks(activeStream);
3063
+ activeStream = null;
3064
+ snapshot = initialSnapshot;
3065
+ };
3066
+ const start = () => {
3067
+ if (!options.enabled || options.simulatorVideoDisabled) return;
3068
+ const generation = ++requestGeneration;
3069
+ void options.getUserMedia({ audio: false, video: { facingMode: "user" } }).then((stream) => {
3070
+ if (generation !== requestGeneration) {
3071
+ stopPreviewTracks(stream);
3072
+ return;
3073
+ }
3074
+ const videoTrack = stream.getVideoTracks?.()[0] ?? null;
3075
+ if (!videoTrack) {
3076
+ stopPreviewTracks(stream);
3077
+ snapshot = { previewStream: null, previewError: "No camera track available" };
3078
+ notify();
3079
+ return;
3080
+ }
3081
+ stopPreviewTracks(activeStream);
3082
+ activeStream = stream;
3083
+ snapshot = { previewStream: stream, previewError: null };
3084
+ notify();
3085
+ }).catch((cause) => {
3086
+ if (generation !== requestGeneration) return;
3087
+ snapshot = {
3088
+ previewStream: null,
3089
+ previewError: cause instanceof Error ? cause.message : "Unable to start camera preview"
3090
+ };
3091
+ notify();
3092
+ });
3093
+ };
3094
+ const subscribe = (listener) => {
3095
+ listeners.add(listener);
3096
+ if (listeners.size === 1) start();
3097
+ return () => {
3098
+ listeners.delete(listener);
3099
+ if (listeners.size !== 0) return;
3100
+ reset();
3101
+ };
3102
+ };
3103
+ return {
3104
+ getSnapshot: () => snapshot,
3105
+ subscribe
3106
+ };
3107
+ }
3108
+
3109
+ // src/hooks/useEntrancePreview.ts
3110
+ function useEntrancePreview(enabled) {
3111
+ const simulatorVideoDisabled = isIosSimulator();
3112
+ const store = useMemo13(
3113
+ () => createEntrancePreviewStore({
3114
+ enabled,
3115
+ simulatorVideoDisabled,
3116
+ simulatorVideoMessage: getIosSimulatorVideoMessage(),
3117
+ getUserMedia: mediaDevices.getUserMedia
3118
+ }),
3119
+ [enabled, simulatorVideoDisabled]
3120
+ );
3121
+ const { previewStream, previewError } = useSyncExternalStore3(store.subscribe, store.getSnapshot, store.getSnapshot);
3122
+ return { previewStream, previewError };
3123
+ }
3124
+
3125
+ // src/components/native-entrance/entrance-controller-store.ts
3126
+ var EntranceControllerStore = class {
3127
+ #snapshot;
3128
+ #listeners = /* @__PURE__ */ new Set();
3129
+ #simulatorMediaDisabled;
3130
+ #joinDisabled;
3131
+ #submitLatch = false;
3132
+ #onJoin;
3133
+ constructor({ displayName, initialAudioEnabled, initialVideoEnabled, simulatorMediaDisabled, joinDisabled, onJoin }) {
3134
+ this.#simulatorMediaDisabled = simulatorMediaDisabled;
3135
+ this.#joinDisabled = joinDisabled;
3136
+ this.#onJoin = onJoin;
3137
+ this.#snapshot = {
3138
+ displayName,
3139
+ audioEnabled: initialAudioEnabled && !simulatorMediaDisabled,
3140
+ videoEnabled: initialVideoEnabled && !simulatorMediaDisabled,
3141
+ isSubmitting: false,
3142
+ isInputFocused: false
3143
+ };
3144
+ }
3145
+ getSnapshot = () => this.#snapshot;
3146
+ subscribe = (listener) => {
3147
+ this.#listeners.add(listener);
3148
+ return () => {
3149
+ this.#listeners.delete(listener);
3150
+ };
3151
+ };
3152
+ update = ({ simulatorMediaDisabled, joinDisabled, onJoin }) => {
3153
+ this.#onJoin = onJoin;
3154
+ if (!this.#simulatorMediaDisabled && simulatorMediaDisabled) {
3155
+ this.#update({ audioEnabled: false, videoEnabled: false });
3156
+ }
3157
+ if (this.#joinDisabled && !joinDisabled) {
3158
+ this.#submitLatch = false;
3159
+ this.#update({ isSubmitting: false });
3160
+ }
3161
+ this.#simulatorMediaDisabled = simulatorMediaDisabled;
3162
+ this.#joinDisabled = joinDisabled;
3163
+ };
3164
+ setDisplayName = (displayName) => {
3165
+ this.#update({ displayName });
3166
+ };
3167
+ setInputFocused = (isInputFocused) => {
3168
+ this.#update({ isInputFocused });
3169
+ };
3170
+ toggleAudio = () => {
3171
+ if (this.#simulatorMediaDisabled) return;
3172
+ this.#update({ audioEnabled: !this.#snapshot.audioEnabled });
3173
+ };
3174
+ toggleVideo = () => {
3175
+ if (this.#simulatorMediaDisabled) return;
3176
+ this.#update({ videoEnabled: !this.#snapshot.videoEnabled });
3177
+ };
3178
+ handleJoin = () => {
3179
+ const displayName = this.#snapshot.displayName.trim();
3180
+ if (!displayName || this.#joinDisabled || this.#snapshot.isSubmitting || this.#submitLatch) return;
3181
+ this.#submitLatch = true;
3182
+ this.#update({ isSubmitting: true });
3183
+ this.#onJoin({
3184
+ displayName,
3185
+ microphoneEnabled: this.#snapshot.audioEnabled,
3186
+ cameraEnabled: this.#snapshot.videoEnabled
3187
+ });
3188
+ };
3189
+ #update(next) {
3190
+ const snapshot = { ...this.#snapshot, ...next };
3191
+ if (snapshot.displayName === this.#snapshot.displayName && snapshot.audioEnabled === this.#snapshot.audioEnabled && snapshot.videoEnabled === this.#snapshot.videoEnabled && snapshot.isSubmitting === this.#snapshot.isSubmitting && snapshot.isInputFocused === this.#snapshot.isInputFocused) {
3192
+ return;
3193
+ }
3194
+ this.#snapshot = snapshot;
3195
+ for (const listener of this.#listeners) listener();
3196
+ }
3197
+ };
3198
+
3199
+ // src/components/native-entrance/useEntranceController.ts
3200
+ function useEntranceController({ displayName = "", initialAudioEnabled = false, initialVideoEnabled = false, joinDisabled = false, onJoin }) {
3201
+ const simulatorMediaDisabled = isIosSimulator();
3202
+ const store = useMemo14(
3203
+ () => new EntranceControllerStore({
3204
+ displayName,
3205
+ initialAudioEnabled,
3206
+ initialVideoEnabled,
3207
+ simulatorMediaDisabled,
3208
+ joinDisabled,
3209
+ onJoin
3210
+ }),
3211
+ []
3212
+ );
3213
+ store.update({
3214
+ simulatorMediaDisabled,
3215
+ joinDisabled,
3216
+ onJoin
3217
+ });
3218
+ const snapshot = useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getSnapshot);
3219
+ const { previewError, previewStream } = useEntrancePreview(snapshot.videoEnabled);
3220
+ return {
3221
+ displayName: snapshot.displayName,
3222
+ audioEnabled: snapshot.audioEnabled,
3223
+ videoEnabled: snapshot.videoEnabled,
3224
+ isSubmitting: snapshot.isSubmitting,
3225
+ isInputFocused: snapshot.isInputFocused,
3226
+ previewError,
3227
+ previewStream,
3228
+ simulatorMediaDisabled,
3229
+ setDisplayName: store.setDisplayName,
3230
+ setInputFocused: store.setInputFocused,
3231
+ toggleAudio: store.toggleAudio,
3232
+ toggleVideo: store.toggleVideo,
3233
+ handleJoin: store.handleJoin
3234
+ };
3235
+ }
3236
+
3237
+ // src/components/EntranceView.android.tsx
3238
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
3239
+ function EntranceViewAndroid({ spaceName, error, joinDisabled = false, onCancel, ...props }) {
3240
+ const controller = useEntranceController({ ...props, joinDisabled });
3241
+ const theme = useNativeTheme();
3242
+ const canJoin = controller.displayName.trim().length > 0 && !joinDisabled && !controller.isSubmitting;
3243
+ return /* @__PURE__ */ jsx25(KeyboardAvoidingView2, { behavior: Platform10.OS === "ios" ? "padding" : "height", style: [styles20.screen, { backgroundColor: theme.colors.background }], children: /* @__PURE__ */ jsxs18(View20, { style: styles20.content, children: [
3244
+ /* @__PURE__ */ jsxs18(View20, { style: styles20.previewContainer, children: [
3245
+ /* @__PURE__ */ jsxs18(View20, { style: [styles20.previewSurface, { backgroundColor: theme.colors.raisedSurface, borderColor: theme.colors.border }], children: [
3246
+ controller.previewStream && controller.videoEnabled ? /* @__PURE__ */ jsx25(RTCView, { mirror: true, objectFit: "cover", streamURL: controller.previewStream.toURL(), style: styles20.previewVideo, zOrder: 0 }) : /* @__PURE__ */ jsx25(View20, { style: [styles20.avatarContainer, { backgroundColor: theme.colors.insetSurface }], children: /* @__PURE__ */ jsx25(FaceAvatar, { name: controller.displayName, size: 140, textSize: 52 }) }),
3247
+ onCancel ? /* @__PURE__ */ jsx25(Pressable12, { accessibilityLabel: "Cancel and leave Entrance", accessibilityRole: "button", onPress: onCancel, style: ({ pressed }) => [styles20.floatingBack, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }, pressed && styles20.topIconButtonPressed], children: /* @__PURE__ */ jsx25(HugeiconsIcon11, { icon: ArrowLeft01Icon, size: 22, color: theme.colors.foreground }) }) : null
3248
+ ] }),
3249
+ controller.previewError && controller.videoEnabled ? /* @__PURE__ */ jsx25(Text15, { style: styles20.previewError, children: controller.previewError }) : null,
3250
+ controller.simulatorMediaDisabled ? /* @__PURE__ */ jsx25(Text15, { style: styles20.previewHint, children: getIosSimulatorMediaMessage() }) : null
3251
+ ] }),
3252
+ /* @__PURE__ */ jsxs18(View20, { style: [styles20.sheetContainer, { backgroundColor: theme.colors.card, borderColor: theme.colors.border, shadowColor: theme.colors.darkCanvas }], children: [
3253
+ /* @__PURE__ */ jsx25(View20, { style: styles20.sheetHandle }),
3254
+ /* @__PURE__ */ jsx25(View20, { style: styles20.sheetHeader, children: /* @__PURE__ */ jsx25(Text15, { style: [styles20.spaceName, { color: theme.colors.foreground }], numberOfLines: 1, children: spaceName }) }),
3255
+ /* @__PURE__ */ jsxs18(View20, { style: [styles20.inputCard, { backgroundColor: theme.colors.surface, borderColor: controller.isInputFocused ? theme.colors.ring : theme.colors.border }], children: [
3256
+ /* @__PURE__ */ jsx25(HugeiconsIcon11, { icon: UserIcon2, size: 18, color: controller.isInputFocused ? theme.colors.primary : theme.colors.mutedForeground, style: styles20.inputIcon }),
3257
+ /* @__PURE__ */ jsx25(
3258
+ TextInput2,
3259
+ {
3260
+ onChangeText: controller.setDisplayName,
3261
+ onFocus: () => controller.setInputFocused(true),
3262
+ onBlur: () => controller.setInputFocused(false),
3263
+ placeholder: "Enter your name",
3264
+ placeholderTextColor: theme.colors.mutedForeground,
3265
+ style: [styles20.nameInput, { color: theme.colors.foreground }],
3266
+ value: controller.displayName,
3267
+ maxLength: 30,
3268
+ returnKeyType: "join",
3269
+ onSubmitEditing: controller.handleJoin
3270
+ }
3271
+ )
3272
+ ] }),
3273
+ /* @__PURE__ */ jsxs18(View20, { style: styles20.mediaRow, children: [
3274
+ /* @__PURE__ */ jsx25(
3275
+ Pressable12,
3276
+ {
3277
+ disabled: controller.simulatorMediaDisabled,
3278
+ onPress: controller.toggleAudio,
3279
+ style: ({ pressed }) => [styles20.controlCircle, { backgroundColor: controller.audioEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, controller.simulatorMediaDisabled && styles20.toggleCircleDisabled, pressed && styles20.togglePressed],
3280
+ children: /* @__PURE__ */ jsx25(HugeiconsIcon11, { icon: controller.audioEnabled ? Mic01Icon4 : MicOff01Icon7, size: 24, color: theme.colors.primaryForeground })
3281
+ }
3282
+ ),
3283
+ /* @__PURE__ */ jsx25(
3284
+ Pressable12,
3285
+ {
3286
+ disabled: controller.simulatorMediaDisabled,
3287
+ onPress: controller.toggleVideo,
3288
+ style: ({ pressed }) => [styles20.controlCircle, { backgroundColor: controller.videoEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, controller.simulatorMediaDisabled && styles20.toggleCircleDisabled, pressed && styles20.togglePressed],
3289
+ children: /* @__PURE__ */ jsx25(HugeiconsIcon11, { icon: controller.videoEnabled ? Video01Icon5 : VideoOffIcon4, size: 24, color: theme.colors.primaryForeground })
3290
+ }
3291
+ )
3292
+ ] }),
3293
+ error ? /* @__PURE__ */ jsx25(Text15, { style: [styles20.globalError, { color: theme.colors.error }], children: error }) : null,
3294
+ /* @__PURE__ */ jsx25(Pressable12, { disabled: !canJoin, onPress: controller.handleJoin, style: ({ pressed }) => [styles20.joinButton, { backgroundColor: canJoin ? theme.colors.primary : theme.colors.muted }, !canJoin && styles20.joinButtonDisabled, pressed && styles20.togglePressed], children: /* @__PURE__ */ jsx25(Text15, { style: [styles20.joinButtonText, { color: theme.colors.primaryForeground }], children: controller.isSubmitting || joinDisabled ? "Joining..." : "Enter Space" }) })
3295
+ ] })
3296
+ ] }) });
3297
+ }
3298
+ var styles20 = StyleSheet21.create({
3299
+ screen: {
3300
+ flex: 1,
3301
+ backgroundColor: Theme.colors.background
3302
+ },
3303
+ content: {
3304
+ flex: 1
3305
+ },
3306
+ floatingBack: {
3307
+ position: "absolute",
3308
+ top: Platform10.OS === "ios" ? 24 : 20,
3309
+ left: 20,
3310
+ width: 42,
3311
+ height: 42,
3312
+ borderRadius: 21,
3313
+ backgroundColor: Theme.colors.darkOverlay40,
3314
+ alignItems: "center",
3315
+ justifyContent: "center",
3316
+ zIndex: 10,
3317
+ borderWidth: 1,
3318
+ borderColor: Theme.colors.whiteOverlay10
3319
+ },
3320
+ previewContainer: {
3321
+ flex: 1,
3322
+ justifyContent: "center",
3323
+ paddingTop: Platform10.OS === "ios" ? 10 : 0,
3324
+ marginBottom: 0
3325
+ },
3326
+ previewSurface: {
3327
+ width: "100%",
3328
+ aspectRatio: 0.72,
3329
+ backgroundColor: Theme.colors.raisedSurface,
3330
+ borderRadius: 32,
3331
+ alignSelf: "center",
3332
+ overflow: "hidden",
3333
+ position: "relative",
3334
+ borderWidth: 1,
3335
+ borderColor: Theme.colors.whiteOverlay06
3336
+ },
3337
+ previewVideo: {
3338
+ ...StyleSheet21.absoluteFillObject
3339
+ },
3340
+ avatarContainer: {
3341
+ ...StyleSheet21.absoluteFillObject,
3342
+ alignItems: "center",
3343
+ justifyContent: "center",
3344
+ backgroundColor: Theme.colors.insetSurface
3345
+ },
3346
+ togglePressed: {
3347
+ opacity: 0.7,
3348
+ transform: [{ scale: 0.9 }]
3349
+ },
3350
+ previewError: {
3351
+ color: Theme.colors.error,
3352
+ fontSize: 12,
3353
+ marginTop: 10,
3354
+ textAlign: "center",
3355
+ fontWeight: "600",
3356
+ paddingHorizontal: 24
3357
+ },
3358
+ previewHint: {
3359
+ color: Theme.colors.mutedForeground,
3360
+ fontSize: 12,
3361
+ marginTop: 10,
3362
+ textAlign: "center",
3363
+ lineHeight: 18,
3364
+ paddingHorizontal: 24
3365
+ },
3366
+ sheetContainer: {
3367
+ backgroundColor: Theme.colors.elevatedSurface,
3368
+ borderTopLeftRadius: 32,
3369
+ borderTopRightRadius: 32,
3370
+ paddingHorizontal: 24,
3371
+ paddingTop: 16,
3372
+ paddingBottom: Platform10.OS === "ios" ? 44 : 32,
3373
+ gap: 20,
3374
+ borderTopWidth: 1,
3375
+ borderColor: Theme.colors.whiteOverlay08,
3376
+ shadowColor: Theme.colors.darkCanvas,
3377
+ shadowOffset: { width: 0, height: -12 },
3378
+ shadowOpacity: 0.3,
3379
+ shadowRadius: 16,
3380
+ elevation: 20
3381
+ },
3382
+ sheetHandle: {
3383
+ width: 36,
3384
+ height: 4,
3385
+ borderRadius: 2,
3386
+ backgroundColor: Theme.colors.whiteOverlay10,
3387
+ alignSelf: "center",
3388
+ marginBottom: 8
3389
+ },
3390
+ sheetHeader: {
3391
+ alignItems: "center",
3392
+ marginBottom: 4
3393
+ },
3394
+ spaceName: {
3395
+ color: Theme.colors.foreground,
3396
+ fontSize: 22,
3397
+ fontWeight: "800",
3398
+ textAlign: "center",
3399
+ letterSpacing: -0.6
3400
+ },
3401
+ inputCard: {
3402
+ flexDirection: "row",
3403
+ alignItems: "center",
3404
+ backgroundColor: Theme.colors.whiteOverlay04,
3405
+ borderRadius: 18,
3406
+ paddingHorizontal: 16,
3407
+ height: 56,
3408
+ borderWidth: 1,
3409
+ borderColor: Theme.colors.whiteOverlay08
3410
+ },
3411
+ inputCardFocused: {
3412
+ borderColor: Theme.colors.primary,
3413
+ backgroundColor: Theme.colors.accentOverlay04
3414
+ },
3415
+ inputIcon: {
3416
+ marginRight: 24
3417
+ },
3418
+ nameInput: {
3419
+ flex: 1,
3420
+ color: Theme.colors.onDark,
3421
+ fontSize: 16,
3422
+ fontWeight: "600",
3423
+ padding: 0
3424
+ },
3425
+ mediaRow: {
3426
+ flexDirection: "row",
3427
+ justifyContent: "center",
3428
+ gap: 20
3429
+ },
3430
+ controlCircle: {
3431
+ width: 64,
3432
+ height: 64,
3433
+ borderRadius: 32,
3434
+ backgroundColor: Theme.colors.whiteOverlay06,
3435
+ alignItems: "center",
3436
+ justifyContent: "center",
3437
+ borderWidth: 1,
3438
+ borderColor: Theme.colors.whiteOverlay10
3439
+ },
3440
+ toggleCircleOff: {
3441
+ backgroundColor: Theme.colors.dangerStrong,
3442
+ borderColor: Theme.colors.dangerStrong
3443
+ },
3444
+ toggleCircleDisabled: {
3445
+ opacity: 0.45
3446
+ },
3447
+ joinButton: {
3448
+ width: "100%",
3449
+ height: 58,
3450
+ borderRadius: 18,
3451
+ alignItems: "center",
3452
+ justifyContent: "center"
3453
+ },
3454
+ joinButtonDisabled: {
3455
+ opacity: 0.6
3456
+ },
3457
+ joinButtonText: {
3458
+ color: Theme.colors.onDark,
3459
+ fontSize: 16,
3460
+ fontWeight: "700"
3461
+ },
3462
+ globalError: {
3463
+ color: Theme.colors.error,
3464
+ fontSize: 13,
3465
+ fontWeight: "600",
3466
+ textAlign: "center"
3467
+ },
3468
+ topIconButtonPressed: {
3469
+ opacity: 0.6,
3470
+ transform: [{ scale: 0.92 }]
3471
+ }
3472
+ });
3473
+
3474
+ // src/components/EntranceView.ios-pad.tsx
3475
+ import ArrowLeft01Icon2 from "@hugeicons/core-free-icons/dist/esm/ArrowLeft01Icon";
3476
+ import Mic01Icon5 from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
3477
+ import MicOff01Icon8 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
3478
+ import Video01Icon6 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
3479
+ import VideoOffIcon5 from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
3480
+ import ArrowRight02Icon from "@hugeicons/core-free-icons/dist/esm/ArrowRight02Icon";
3481
+ import CancelCircleIcon2 from "@hugeicons/core-free-icons/dist/esm/CancelCircleIcon";
3482
+ import { HugeiconsIcon as HugeiconsIcon12 } from "@hugeicons/react-native";
3483
+ import { KeyboardAvoidingView as KeyboardAvoidingView3, Platform as Platform11, Pressable as Pressable13, StyleSheet as StyleSheet22, Text as Text16, TextInput as TextInput3, View as View21, Animated, ActivityIndicator as ActivityIndicator2 } from "react-native";
3484
+
3485
+ // src/components/native-animation-controller.ts
3486
+ function createAnimationRefController(createAnimations) {
3487
+ let attached = false;
3488
+ let animations = [];
3489
+ return (node) => {
3490
+ if (node === null) {
3491
+ if (!attached) {
3492
+ return;
3493
+ }
3494
+ attached = false;
3495
+ for (const animation of animations) {
3496
+ animation.stop();
3497
+ }
3498
+ animations = [];
3499
+ return;
3500
+ }
3501
+ if (attached) {
3502
+ return;
3503
+ }
3504
+ attached = true;
3505
+ animations = createAnimations();
3506
+ for (const animation of animations) {
3507
+ animation.start();
3508
+ }
3509
+ };
3510
+ }
3511
+
3512
+ // src/components/EntranceView.ios-pad.tsx
3513
+ import { useRef as useRef4 } from "react";
3514
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
3515
+ function EntranceViewIosPad({ spaceName, error, joinDisabled = false, onCancel, ...props }) {
3516
+ const controller = useEntranceController({ ...props, joinDisabled });
3517
+ const theme = useNativeTheme();
3518
+ const canRenderPreview = hasRtcVideoView();
3519
+ const entryAnim = useRef4(new Animated.Value(0)).current;
3520
+ const islandAnim = useRef4(new Animated.Value(0)).current;
3521
+ const animationRef = useRef4(null);
3522
+ const attachEntryAnimation = animationRef.current ?? (animationRef.current = createAnimationRefController(() => [
3523
+ Animated.stagger(300, [
3524
+ Animated.spring(entryAnim, {
3525
+ toValue: 1,
3526
+ tension: 20,
3527
+ friction: 8,
3528
+ useNativeDriver: true
3529
+ }),
3530
+ Animated.spring(islandAnim, {
3531
+ toValue: 1,
3532
+ tension: 25,
3533
+ friction: 9,
3534
+ useNativeDriver: true
3535
+ })
3536
+ ])
3537
+ ]));
3538
+ const canJoin = controller.displayName.trim().length > 0 && !joinDisabled && !controller.isSubmitting;
3539
+ const showPreview = Boolean(controller.previewStream && controller.videoEnabled && canRenderPreview);
3540
+ const previewStreamURL = showPreview && controller.previewStream ? controller.previewStream.toURL() : null;
3541
+ return /* @__PURE__ */ jsxs19(KeyboardAvoidingView3, { behavior: Platform11.OS === "ios" ? "padding" : "height", style: [styles21.screen, { backgroundColor: theme.colors.background }], children: [
3542
+ /* @__PURE__ */ jsxs19(View21, { style: [styles21.immersiveContainer, { backgroundColor: theme.colors.darkCanvas }], children: [
3543
+ previewStreamURL ? /* @__PURE__ */ jsx26(RtcVideoView, { mirror: true, objectFit: "cover", streamURL: previewStreamURL, style: styles21.fullScreenVideo, zOrder: -1 }) : /* @__PURE__ */ jsx26(View21, { style: [styles21.immersiveAvatarContainer, { backgroundColor: theme.colors.background }], children: /* @__PURE__ */ jsx26(FaceAvatar, { name: controller.displayName, size: 200, textSize: 80 }) }),
3544
+ showPreview ? /* @__PURE__ */ jsx26(View21, { style: styles21.frostOverlay }) : null
3545
+ ] }),
3546
+ /* @__PURE__ */ jsxs19(View21, { style: styles21.hudLayer, children: [
3547
+ /* @__PURE__ */ jsxs19(View21, { style: styles21.topHud, children: [
3548
+ onCancel ? /* @__PURE__ */ jsx26(Pressable13, { accessibilityLabel: "Cancel and leave Entrance", accessibilityRole: "button", onPress: onCancel, style: ({ pressed }) => [styles21.backPuck, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }, pressed && styles21.pressed], children: /* @__PURE__ */ jsx26(HugeiconsIcon12, { icon: ArrowLeft01Icon2, size: 22, color: theme.colors.foreground }) }) : null,
3549
+ /* @__PURE__ */ jsx26(View21, { style: styles21.spaceInfo, children: /* @__PURE__ */ jsx26(Text16, { style: [styles21.spaceTitle, { color: theme.colors.foreground }], numberOfLines: 1, children: spaceName }) }),
3550
+ /* @__PURE__ */ jsx26(View21, { style: styles21.topHudSpacer })
3551
+ ] }),
3552
+ /* @__PURE__ */ jsx26(View21, { style: styles21.flexFill }),
3553
+ /* @__PURE__ */ jsxs19(
3554
+ Animated.View,
3555
+ {
3556
+ ref: attachEntryAnimation,
3557
+ style: [
3558
+ styles21.bottomHud,
3559
+ {
3560
+ opacity: islandAnim,
3561
+ transform: [{ translateY: islandAnim.interpolate({ inputRange: [0, 1], outputRange: [40, 0] }) }]
3562
+ }
3563
+ ],
3564
+ children: [
3565
+ /* @__PURE__ */ jsxs19(View21, { style: [styles21.launchPad, { backgroundColor: theme.colors.card, borderColor: theme.colors.border, shadowColor: theme.colors.darkCanvas }], children: [
3566
+ /* @__PURE__ */ jsxs19(View21, { style: styles21.mediaGroup, children: [
3567
+ /* @__PURE__ */ jsx26(
3568
+ Pressable13,
3569
+ {
3570
+ accessibilityLabel: controller.audioEnabled ? "Mute microphone" : "Unmute microphone",
3571
+ accessibilityRole: "button",
3572
+ accessibilityState: { disabled: controller.simulatorMediaDisabled, selected: controller.audioEnabled },
3573
+ disabled: controller.simulatorMediaDisabled,
3574
+ onPress: controller.toggleAudio,
3575
+ style: ({ pressed }) => [styles21.mediaToggle, { backgroundColor: controller.audioEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, pressed && styles21.pressed],
3576
+ children: /* @__PURE__ */ jsx26(HugeiconsIcon12, { icon: controller.audioEnabled ? Mic01Icon5 : MicOff01Icon8, size: 22, color: theme.colors.primaryForeground })
3577
+ }
3578
+ ),
3579
+ /* @__PURE__ */ jsx26(
3580
+ Pressable13,
3581
+ {
3582
+ accessibilityLabel: controller.videoEnabled ? "Turn camera off" : "Turn camera on",
3583
+ accessibilityRole: "button",
3584
+ accessibilityState: { disabled: controller.simulatorMediaDisabled, selected: controller.videoEnabled },
3585
+ disabled: controller.simulatorMediaDisabled,
3586
+ onPress: controller.toggleVideo,
3587
+ style: ({ pressed }) => [styles21.mediaToggle, { backgroundColor: controller.videoEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, pressed && styles21.pressed],
3588
+ children: /* @__PURE__ */ jsx26(HugeiconsIcon12, { icon: controller.videoEnabled ? Video01Icon6 : VideoOffIcon5, size: 22, color: theme.colors.primaryForeground })
3589
+ }
3590
+ )
3591
+ ] }),
3592
+ /* @__PURE__ */ jsx26(View21, { style: styles21.islandDivider }),
3593
+ /* @__PURE__ */ jsxs19(View21, { style: [styles21.identityArea, { backgroundColor: theme.colors.surface, borderColor: controller.isInputFocused ? theme.colors.ring : theme.colors.border }, controller.isInputFocused && styles21.identityAreaFocused], children: [
3594
+ /* @__PURE__ */ jsx26(
3595
+ TextInput3,
3596
+ {
3597
+ accessibilityLabel: "Your name",
3598
+ onChangeText: controller.setDisplayName,
3599
+ onFocus: () => controller.setInputFocused(true),
3600
+ onBlur: () => controller.setInputFocused(false),
3601
+ placeholder: "Enter your name to join",
3602
+ placeholderTextColor: theme.colors.mutedForeground,
3603
+ style: [styles21.immersiveInput, { color: theme.colors.foreground }],
3604
+ value: controller.displayName,
3605
+ maxLength: 30,
3606
+ returnKeyType: "join",
3607
+ onSubmitEditing: controller.handleJoin
3608
+ }
3609
+ ),
3610
+ controller.displayName.length > 0 && /* @__PURE__ */ jsx26(Pressable13, { accessibilityLabel: "Clear name", accessibilityRole: "button", onPress: () => controller.setDisplayName(""), style: styles21.clearAction, children: /* @__PURE__ */ jsx26(HugeiconsIcon12, { icon: CancelCircleIcon2, size: 18, color: theme.colors.mutedForeground }) })
3611
+ ] }),
3612
+ /* @__PURE__ */ jsx26(
3613
+ Pressable13,
3614
+ {
3615
+ accessibilityLabel: "Enter Space",
3616
+ accessibilityRole: "button",
3617
+ accessibilityState: { disabled: !canJoin },
3618
+ disabled: !canJoin,
3619
+ onPress: controller.handleJoin,
3620
+ style: ({ pressed }) => [
3621
+ styles21.joinArrow,
3622
+ canJoin && {
3623
+ backgroundColor: theme.colors.primary,
3624
+ shadowColor: theme.colors.primary,
3625
+ shadowOffset: { width: 0, height: 4 },
3626
+ shadowOpacity: 0.3,
3627
+ shadowRadius: 8
3628
+ },
3629
+ pressed && canJoin && styles21.pressed,
3630
+ controller.isSubmitting && styles21.disabled
3631
+ ],
3632
+ children: controller.isSubmitting ? /* @__PURE__ */ jsx26(ActivityIndicator2, { color: theme.colors.primaryForeground, size: "small" }) : /* @__PURE__ */ jsx26(HugeiconsIcon12, { icon: ArrowRight02Icon, size: 28, color: canJoin ? theme.colors.primaryForeground : theme.colors.mutedForeground })
3633
+ }
3634
+ )
3635
+ ] }),
3636
+ error ? /* @__PURE__ */ jsx26(Text16, { style: [styles21.immersiveError, { color: theme.colors.error }], children: error }) : null,
3637
+ controller.simulatorMediaDisabled && /* @__PURE__ */ jsx26(Text16, { style: [styles21.simulatorHintText, { color: theme.colors.mutedForeground }], children: getIosSimulatorMediaMessage() })
3638
+ ]
3639
+ }
3640
+ )
3641
+ ] })
3642
+ ] });
3643
+ }
3644
+ var styles21 = StyleSheet22.create({
3645
+ screen: {
3646
+ flex: 1,
3647
+ backgroundColor: Theme.colors.darkCanvas
3648
+ },
3649
+ immersiveContainer: {
3650
+ ...StyleSheet22.absoluteFillObject,
3651
+ backgroundColor: Theme.colors.darkCanvas
3652
+ },
3653
+ fullScreenVideo: {
3654
+ ...StyleSheet22.absoluteFillObject
3655
+ },
3656
+ immersiveAvatarContainer: {
3657
+ ...StyleSheet22.absoluteFillObject,
3658
+ alignItems: "center",
3659
+ justifyContent: "center",
3660
+ backgroundColor: Theme.colors.background
3661
+ },
3662
+ frostOverlay: {
3663
+ ...StyleSheet22.absoluteFillObject,
3664
+ backgroundColor: Theme.colors.darkOverlay30
3665
+ },
3666
+ hudLayer: {
3667
+ flex: 1,
3668
+ paddingHorizontal: 60,
3669
+ paddingTop: 40,
3670
+ paddingBottom: 60
3671
+ },
3672
+ flexFill: {
3673
+ flex: 1
3674
+ },
3675
+ topHud: {
3676
+ flexDirection: "row",
3677
+ alignItems: "center",
3678
+ justifyContent: "space-between"
3679
+ },
3680
+ backPuck: {
3681
+ width: 52,
3682
+ height: 52,
3683
+ borderRadius: 26,
3684
+ backgroundColor: Theme.colors.whiteOverlay08,
3685
+ alignItems: "center",
3686
+ justifyContent: "center",
3687
+ borderWidth: 1,
3688
+ borderColor: Theme.colors.whiteOverlay10
3689
+ },
3690
+ spaceInfo: {
3691
+ alignItems: "center"
3692
+ },
3693
+ spaceTitle: {
3694
+ color: Theme.colors.onDark,
3695
+ fontSize: 28,
3696
+ fontWeight: "900",
3697
+ letterSpacing: -0.5
3698
+ },
3699
+ topHudSpacer: {
3700
+ width: 52
3701
+ },
3702
+ bottomHud: {
3703
+ width: "100%",
3704
+ maxWidth: 700,
3705
+ alignSelf: "center",
3706
+ gap: 16
3707
+ },
3708
+ launchPad: {
3709
+ flexDirection: "row",
3710
+ alignItems: "center",
3711
+ backgroundColor: Theme.colors.canvasOverlay85,
3712
+ borderRadius: 40,
3713
+ borderWidth: 1,
3714
+ borderColor: Theme.colors.whiteOverlay12,
3715
+ padding: 8,
3716
+ height: 80,
3717
+ shadowColor: Theme.colors.darkCanvas,
3718
+ shadowOffset: { width: 0, height: 12 },
3719
+ shadowOpacity: 0.5,
3720
+ shadowRadius: 20,
3721
+ elevation: 20
3722
+ },
3723
+ mediaGroup: {
3724
+ flexDirection: "row",
3725
+ gap: 8,
3726
+ paddingLeft: 4
3727
+ },
3728
+ mediaToggle: {
3729
+ width: 64,
3730
+ height: 64,
3731
+ borderRadius: 32,
3732
+ backgroundColor: Theme.colors.whiteOverlay06,
3733
+ alignItems: "center",
3734
+ justifyContent: "center",
3735
+ borderWidth: 1,
3736
+ borderColor: Theme.colors.whiteOverlay05
3737
+ },
3738
+ toggleOff: {
3739
+ backgroundColor: Theme.colors.error,
3740
+ borderColor: Theme.colors.error
3741
+ },
3742
+ islandDivider: {
3743
+ width: 1,
3744
+ height: 32,
3745
+ backgroundColor: Theme.colors.whiteOverlay10,
3746
+ marginHorizontal: 16
3747
+ },
3748
+ identityArea: {
3749
+ flex: 1,
3750
+ flexDirection: "row",
3751
+ alignItems: "center",
3752
+ height: "100%",
3753
+ paddingHorizontal: 8
3754
+ },
3755
+ identityAreaFocused: {},
3756
+ immersiveInput: {
3757
+ flex: 1,
3758
+ color: Theme.colors.onDark,
3759
+ fontSize: 20,
3760
+ fontWeight: "700",
3761
+ padding: 0,
3762
+ letterSpacing: -0.5
3763
+ },
3764
+ clearAction: {
3765
+ padding: 10
3766
+ },
3767
+ joinArrow: {
3768
+ width: 64,
3769
+ height: 64,
3770
+ borderRadius: 32,
3771
+ backgroundColor: Theme.colors.whiteOverlay05,
3772
+ alignItems: "center",
3773
+ justifyContent: "center"
3774
+ },
3775
+ immersiveError: {
3776
+ color: Theme.colors.error,
3777
+ fontSize: 14,
3778
+ fontWeight: "700",
3779
+ textAlign: "center",
3780
+ marginTop: 8
3781
+ },
3782
+ simulatorHintText: {
3783
+ color: Theme.colors.whiteOverlay50,
3784
+ fontSize: 12,
3785
+ textAlign: "center",
3786
+ fontWeight: "600"
3787
+ },
3788
+ pressed: {
3789
+ opacity: 0.7,
3790
+ transform: [{ scale: 0.94 }]
3791
+ },
3792
+ disabled: {
3793
+ opacity: 0.5
3794
+ }
3795
+ });
3796
+
3797
+ // src/components/EntranceView.ios-phone.tsx
3798
+ import ArrowLeft01Icon3 from "@hugeicons/core-free-icons/dist/esm/ArrowLeft01Icon";
3799
+ import Mic01Icon6 from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
3800
+ import MicOff01Icon9 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
3801
+ import UserIcon3 from "@hugeicons/core-free-icons/dist/esm/UserIcon";
3802
+ import Video01Icon7 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
3803
+ import VideoOffIcon6 from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
3804
+ import { HugeiconsIcon as HugeiconsIcon13 } from "@hugeicons/react-native";
3805
+ import { KeyboardAvoidingView as KeyboardAvoidingView4, Platform as Platform12, Pressable as Pressable14, StyleSheet as StyleSheet23, Text as Text17, TextInput as TextInput4, View as View22 } from "react-native";
3806
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
3807
+ function EntranceViewIosPhone({ spaceName, error, joinDisabled = false, onCancel, ...props }) {
3808
+ const controller = useEntranceController({ ...props, joinDisabled });
3809
+ const theme = useNativeTheme();
3810
+ const canJoin = controller.displayName.trim().length > 0 && !joinDisabled && !controller.isSubmitting;
3811
+ return /* @__PURE__ */ jsx27(KeyboardAvoidingView4, { behavior: Platform12.OS === "ios" ? "padding" : "height", style: [styles22.screen, { backgroundColor: theme.colors.background }], children: /* @__PURE__ */ jsxs20(View22, { style: styles22.content, children: [
3812
+ /* @__PURE__ */ jsxs20(View22, { style: styles22.previewContainer, children: [
3813
+ /* @__PURE__ */ jsxs20(View22, { style: [styles22.previewSurface, { backgroundColor: theme.colors.raisedSurface, borderColor: theme.colors.border }], children: [
3814
+ controller.previewStream && controller.videoEnabled ? /* @__PURE__ */ jsx27(RTCView, { mirror: true, objectFit: "cover", streamURL: controller.previewStream.toURL(), style: styles22.previewVideo, zOrder: 0 }) : /* @__PURE__ */ jsx27(View22, { style: [styles22.avatarContainer, { backgroundColor: theme.colors.insetSurface }], children: /* @__PURE__ */ jsx27(FaceAvatar, { name: controller.displayName, size: 140, textSize: 52 }) }),
3815
+ onCancel ? /* @__PURE__ */ jsx27(Pressable14, { accessibilityLabel: "Cancel and leave Entrance", accessibilityRole: "button", onPress: onCancel, style: ({ pressed }) => [styles22.floatingBack, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }, pressed && styles22.topIconButtonPressed], children: /* @__PURE__ */ jsx27(HugeiconsIcon13, { icon: ArrowLeft01Icon3, size: 22, color: theme.colors.foreground }) }) : null
3816
+ ] }),
3817
+ controller.previewError && controller.videoEnabled ? /* @__PURE__ */ jsx27(Text17, { style: styles22.previewError, children: controller.previewError }) : null,
3818
+ controller.simulatorMediaDisabled ? /* @__PURE__ */ jsx27(Text17, { style: styles22.previewHint, children: getIosSimulatorMediaMessage() }) : null
3819
+ ] }),
3820
+ /* @__PURE__ */ jsxs20(View22, { style: [styles22.sheetContainer, { backgroundColor: theme.colors.card, borderColor: theme.colors.border, shadowColor: theme.colors.darkCanvas }], children: [
3821
+ /* @__PURE__ */ jsx27(View22, { style: styles22.sheetHandle }),
3822
+ /* @__PURE__ */ jsx27(View22, { style: styles22.sheetHeader, children: /* @__PURE__ */ jsx27(Text17, { style: [styles22.spaceName, { color: theme.colors.foreground }], numberOfLines: 1, children: spaceName }) }),
3823
+ /* @__PURE__ */ jsxs20(View22, { style: [styles22.inputCard, { backgroundColor: theme.colors.surface, borderColor: controller.isInputFocused ? theme.colors.ring : theme.colors.border }], children: [
3824
+ /* @__PURE__ */ jsx27(HugeiconsIcon13, { icon: UserIcon3, size: 18, color: controller.isInputFocused ? theme.colors.primary : theme.colors.mutedForeground, style: styles22.inputIcon }),
3825
+ /* @__PURE__ */ jsx27(
3826
+ TextInput4,
3827
+ {
3828
+ onChangeText: controller.setDisplayName,
3829
+ onFocus: () => controller.setInputFocused(true),
3830
+ onBlur: () => controller.setInputFocused(false),
3831
+ placeholder: "Enter your name",
3832
+ placeholderTextColor: theme.colors.mutedForeground,
3833
+ style: [styles22.nameInput, { color: theme.colors.foreground }],
3834
+ value: controller.displayName,
3835
+ maxLength: 30,
3836
+ returnKeyType: "join",
3837
+ onSubmitEditing: controller.handleJoin
3838
+ }
3839
+ )
3840
+ ] }),
3841
+ /* @__PURE__ */ jsxs20(View22, { style: styles22.mediaRow, children: [
3842
+ /* @__PURE__ */ jsx27(
3843
+ Pressable14,
3844
+ {
3845
+ disabled: controller.simulatorMediaDisabled,
3846
+ onPress: controller.toggleAudio,
3847
+ style: ({ pressed }) => [styles22.controlCircle, { backgroundColor: controller.audioEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, controller.simulatorMediaDisabled && styles22.toggleCircleDisabled, pressed && styles22.togglePressed],
3848
+ children: /* @__PURE__ */ jsx27(HugeiconsIcon13, { icon: controller.audioEnabled ? Mic01Icon6 : MicOff01Icon9, size: 24, color: theme.colors.primaryForeground })
3849
+ }
3850
+ ),
3851
+ /* @__PURE__ */ jsx27(
3852
+ Pressable14,
3853
+ {
3854
+ disabled: controller.simulatorMediaDisabled,
3855
+ onPress: controller.toggleVideo,
3856
+ style: ({ pressed }) => [styles22.controlCircle, { backgroundColor: controller.videoEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, controller.simulatorMediaDisabled && styles22.toggleCircleDisabled, pressed && styles22.togglePressed],
3857
+ children: /* @__PURE__ */ jsx27(HugeiconsIcon13, { icon: controller.videoEnabled ? Video01Icon7 : VideoOffIcon6, size: 24, color: theme.colors.primaryForeground })
3858
+ }
3859
+ )
3860
+ ] }),
3861
+ error ? /* @__PURE__ */ jsx27(Text17, { style: [styles22.globalError, { color: theme.colors.error }], children: error }) : null,
3862
+ /* @__PURE__ */ jsx27(Pressable14, { disabled: !canJoin, onPress: controller.handleJoin, style: ({ pressed }) => [styles22.joinButton, { backgroundColor: canJoin ? theme.colors.primary : theme.colors.muted }, !canJoin && styles22.joinButtonDisabled, pressed && styles22.togglePressed], children: /* @__PURE__ */ jsx27(Text17, { style: [styles22.joinButtonText, { color: theme.colors.primaryForeground }], children: controller.isSubmitting || joinDisabled ? "Joining..." : "Enter Space" }) })
3863
+ ] })
3864
+ ] }) });
3865
+ }
3866
+ var styles22 = StyleSheet23.create({
3867
+ screen: {
3868
+ flex: 1,
3869
+ backgroundColor: Theme.colors.background
3870
+ },
3871
+ content: {
3872
+ flex: 1
3873
+ },
3874
+ floatingBack: {
3875
+ position: "absolute",
3876
+ left: 20,
3877
+ width: 42,
3878
+ height: 42,
3879
+ borderRadius: 21,
3880
+ backgroundColor: Theme.colors.darkOverlay40,
3881
+ alignItems: "center",
3882
+ justifyContent: "center",
3883
+ zIndex: 10,
3884
+ borderWidth: 1,
3885
+ borderColor: Theme.colors.whiteOverlay10
3886
+ },
3887
+ previewContainer: {
3888
+ flex: 1,
3889
+ justifyContent: "center",
3890
+ paddingTop: Platform12.OS === "ios" ? 10 : 0,
3891
+ marginBottom: 0
3892
+ },
3893
+ previewSurface: {
3894
+ width: "100%",
3895
+ aspectRatio: 0.72,
3896
+ backgroundColor: Theme.colors.raisedSurface,
3897
+ borderRadius: 32,
3898
+ alignSelf: "center",
3899
+ overflow: "hidden",
3900
+ position: "relative",
3901
+ borderWidth: 1,
3902
+ borderColor: Theme.colors.whiteOverlay06
3903
+ },
3904
+ previewVideo: {
3905
+ ...StyleSheet23.absoluteFillObject
3906
+ },
3907
+ avatarContainer: {
3908
+ ...StyleSheet23.absoluteFillObject,
3909
+ alignItems: "center",
3910
+ justifyContent: "center",
3911
+ backgroundColor: Theme.colors.insetSurface
3912
+ },
3913
+ togglePressed: {
3914
+ opacity: 0.7,
3915
+ transform: [{ scale: 0.9 }]
3916
+ },
3917
+ previewError: {
3918
+ color: Theme.colors.error,
3919
+ fontSize: 12,
3920
+ marginTop: 10,
3921
+ textAlign: "center",
3922
+ fontWeight: "600",
3923
+ paddingHorizontal: 24
3924
+ },
3925
+ previewHint: {
3926
+ color: Theme.colors.mutedForeground,
3927
+ fontSize: 12,
3928
+ marginTop: 10,
3929
+ textAlign: "center",
3930
+ lineHeight: 18,
3931
+ paddingHorizontal: 24
3932
+ },
3933
+ sheetContainer: {
3934
+ backgroundColor: Theme.colors.elevatedSurface,
3935
+ borderTopLeftRadius: 32,
3936
+ borderTopRightRadius: 32,
3937
+ paddingHorizontal: 24,
3938
+ paddingTop: 16,
3939
+ paddingBottom: Platform12.OS === "ios" ? 44 : 32,
3940
+ gap: 20,
3941
+ borderTopWidth: 1,
3942
+ borderColor: Theme.colors.whiteOverlay08,
3943
+ shadowColor: Theme.colors.darkCanvas,
3944
+ shadowOffset: { width: 0, height: -12 },
3945
+ shadowOpacity: 0.3,
3946
+ shadowRadius: 16,
3947
+ elevation: 20
3948
+ },
3949
+ sheetHandle: {
3950
+ width: 36,
3951
+ height: 4,
3952
+ borderRadius: 2,
3953
+ backgroundColor: Theme.colors.whiteOverlay10,
3954
+ alignSelf: "center",
3955
+ marginBottom: 8
3956
+ },
3957
+ sheetHeader: {
3958
+ alignItems: "center",
3959
+ marginBottom: 4
3960
+ },
3961
+ spaceName: {
3962
+ color: Theme.colors.foreground,
3963
+ fontSize: 22,
3964
+ fontWeight: "800",
3965
+ textAlign: "center",
3966
+ letterSpacing: -0.6
3967
+ },
3968
+ inputCard: {
3969
+ flexDirection: "row",
3970
+ alignItems: "center",
3971
+ backgroundColor: Theme.colors.whiteOverlay04,
3972
+ borderRadius: 18,
3973
+ paddingHorizontal: 16,
3974
+ height: 56,
3975
+ borderWidth: 1,
3976
+ borderColor: Theme.colors.whiteOverlay08
3977
+ },
3978
+ inputCardFocused: {
3979
+ borderColor: Theme.colors.primary,
3980
+ backgroundColor: Theme.colors.accentOverlay04
3981
+ },
3982
+ inputIcon: {
3983
+ marginRight: 24
3984
+ },
3985
+ nameInput: {
3986
+ flex: 1,
3987
+ color: Theme.colors.onDark,
3988
+ fontSize: 16,
3989
+ fontWeight: "600",
3990
+ padding: 0
3991
+ },
3992
+ mediaRow: {
3993
+ flexDirection: "row",
3994
+ justifyContent: "center",
3995
+ gap: 20
3996
+ },
3997
+ controlCircle: {
3998
+ width: 64,
3999
+ height: 64,
4000
+ borderRadius: 32,
4001
+ backgroundColor: Theme.colors.whiteOverlay06,
4002
+ alignItems: "center",
4003
+ justifyContent: "center",
4004
+ borderWidth: 1,
4005
+ borderColor: Theme.colors.whiteOverlay10
4006
+ },
4007
+ toggleCircleOff: {
4008
+ backgroundColor: Theme.colors.dangerStrong,
4009
+ borderColor: Theme.colors.dangerStrong
4010
+ },
4011
+ toggleCircleDisabled: {
4012
+ opacity: 0.45
4013
+ },
4014
+ joinButton: {
4015
+ width: "100%",
4016
+ height: 58,
4017
+ borderRadius: 18,
4018
+ alignItems: "center",
4019
+ justifyContent: "center"
4020
+ },
4021
+ joinButtonDisabled: {
4022
+ opacity: 0.6
4023
+ },
4024
+ joinButtonText: {
4025
+ color: Theme.colors.onDark,
4026
+ fontSize: 16,
4027
+ fontWeight: "700"
4028
+ },
4029
+ globalError: {
4030
+ color: Theme.colors.error,
4031
+ fontSize: 13,
4032
+ fontWeight: "600",
4033
+ textAlign: "center"
4034
+ },
4035
+ topIconButtonPressed: {
4036
+ opacity: 0.6,
4037
+ transform: [{ scale: 0.92 }]
4038
+ }
4039
+ });
4040
+
4041
+ // src/components/EntranceView.macos.tsx
4042
+ import ArrowLeft01Icon4 from "@hugeicons/core-free-icons/dist/esm/ArrowLeft01Icon";
4043
+ import Mic01Icon7 from "@hugeicons/core-free-icons/dist/esm/Mic01Icon";
4044
+ import MicOff01Icon10 from "@hugeicons/core-free-icons/dist/esm/MicOff01Icon";
4045
+ import UserIcon4 from "@hugeicons/core-free-icons/dist/esm/UserIcon";
4046
+ import Video01Icon8 from "@hugeicons/core-free-icons/dist/esm/Video01Icon";
4047
+ import VideoOffIcon7 from "@hugeicons/core-free-icons/dist/esm/VideoOffIcon";
4048
+ import { HugeiconsIcon as HugeiconsIcon14 } from "@hugeicons/react-native";
4049
+ import { KeyboardAvoidingView as KeyboardAvoidingView5, Platform as Platform13, Pressable as Pressable15, StyleSheet as StyleSheet24, Text as Text18, TextInput as TextInput5, View as View23 } from "react-native";
4050
+ import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
4051
+ function EntranceViewMacos({ spaceName, error, joinDisabled = false, onCancel, ...props }) {
4052
+ const controller = useEntranceController({ ...props, joinDisabled });
4053
+ const theme = useNativeTheme();
4054
+ const canJoin = controller.displayName.trim().length > 0 && !joinDisabled && !controller.isSubmitting;
4055
+ const canRenderPreview = hasRtcVideoView();
4056
+ const showPreview = Boolean(controller.previewStream && controller.videoEnabled && canRenderPreview);
4057
+ const previewStreamURL = showPreview && controller.previewStream ? controller.previewStream.toURL() : null;
4058
+ const previewStatusMessage = controller.videoEnabled && controller.previewStream && !canRenderPreview ? "Camera preview is unavailable on this device." : controller.previewError;
4059
+ return /* @__PURE__ */ jsx28(KeyboardAvoidingView5, { behavior: Platform13.OS === "ios" ? "padding" : "height", style: [styles23.screen, { backgroundColor: theme.colors.background }], children: /* @__PURE__ */ jsxs21(View23, { style: styles23.content, children: [
4060
+ /* @__PURE__ */ jsxs21(View23, { style: styles23.previewContainer, children: [
4061
+ /* @__PURE__ */ jsxs21(View23, { style: [styles23.previewSurface, { backgroundColor: theme.colors.raisedSurface, borderColor: theme.colors.border }], children: [
4062
+ previewStreamURL ? /* @__PURE__ */ jsx28(RtcVideoView, { mirror: true, objectFit: "cover", streamURL: previewStreamURL, style: styles23.previewVideo, zOrder: 0 }) : /* @__PURE__ */ jsx28(View23, { style: [styles23.avatarContainer, { backgroundColor: theme.colors.insetSurface }], children: /* @__PURE__ */ jsx28(FaceAvatar, { name: controller.displayName, size: 140, textSize: 52 }) }),
4063
+ onCancel ? /* @__PURE__ */ jsx28(Pressable15, { accessibilityLabel: "Cancel and leave Entrance", accessibilityRole: "button", onPress: onCancel, style: ({ pressed }) => [styles23.floatingBack, { backgroundColor: theme.colors.surface, borderColor: theme.colors.border }, pressed && styles23.topIconButtonPressed], children: /* @__PURE__ */ jsx28(HugeiconsIcon14, { icon: ArrowLeft01Icon4, size: 22, color: theme.colors.foreground }) }) : null
4064
+ ] }),
4065
+ previewStatusMessage ? /* @__PURE__ */ jsx28(Text18, { style: styles23.previewError, children: previewStatusMessage }) : null,
4066
+ controller.simulatorMediaDisabled ? /* @__PURE__ */ jsx28(Text18, { style: styles23.previewHint, children: getIosSimulatorMediaMessage() }) : null
4067
+ ] }),
4068
+ /* @__PURE__ */ jsxs21(View23, { style: [styles23.sheetContainer, { backgroundColor: theme.colors.card, borderColor: theme.colors.border, shadowColor: theme.colors.darkCanvas }], children: [
4069
+ /* @__PURE__ */ jsx28(View23, { style: styles23.sheetHandle }),
4070
+ /* @__PURE__ */ jsx28(View23, { style: styles23.sheetHeader, children: /* @__PURE__ */ jsx28(Text18, { style: [styles23.spaceName, { color: theme.colors.foreground }], numberOfLines: 1, children: spaceName }) }),
4071
+ /* @__PURE__ */ jsxs21(View23, { style: [styles23.inputCard, { backgroundColor: theme.colors.surface, borderColor: controller.isInputFocused ? theme.colors.ring : theme.colors.border }], children: [
4072
+ /* @__PURE__ */ jsx28(HugeiconsIcon14, { icon: UserIcon4, size: 18, color: controller.isInputFocused ? theme.colors.primary : theme.colors.mutedForeground, style: styles23.inputIcon }),
4073
+ /* @__PURE__ */ jsx28(
4074
+ TextInput5,
4075
+ {
4076
+ onChangeText: controller.setDisplayName,
4077
+ onFocus: () => controller.setInputFocused(true),
4078
+ onBlur: () => controller.setInputFocused(false),
4079
+ placeholder: "Enter your name",
4080
+ placeholderTextColor: theme.colors.mutedForeground,
4081
+ style: [styles23.nameInput, { color: theme.colors.foreground }],
4082
+ value: controller.displayName,
4083
+ maxLength: 30,
4084
+ returnKeyType: "join",
4085
+ onSubmitEditing: controller.handleJoin
4086
+ }
4087
+ )
4088
+ ] }),
4089
+ /* @__PURE__ */ jsxs21(View23, { style: styles23.mediaRow, children: [
4090
+ /* @__PURE__ */ jsx28(
4091
+ Pressable15,
4092
+ {
4093
+ disabled: controller.simulatorMediaDisabled,
4094
+ onPress: controller.toggleAudio,
4095
+ style: ({ pressed }) => [styles23.controlCircle, { backgroundColor: controller.audioEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, controller.simulatorMediaDisabled && styles23.toggleCircleDisabled, pressed && styles23.togglePressed],
4096
+ children: /* @__PURE__ */ jsx28(HugeiconsIcon14, { icon: controller.audioEnabled ? Mic01Icon7 : MicOff01Icon10, size: 24, color: theme.colors.primaryForeground })
4097
+ }
4098
+ ),
4099
+ /* @__PURE__ */ jsx28(
4100
+ Pressable15,
4101
+ {
4102
+ disabled: controller.simulatorMediaDisabled,
4103
+ onPress: controller.toggleVideo,
4104
+ style: ({ pressed }) => [styles23.controlCircle, { backgroundColor: controller.videoEnabled ? theme.colors.controlsBackground : theme.colors.error, borderColor: theme.colors.border }, controller.simulatorMediaDisabled && styles23.toggleCircleDisabled, pressed && styles23.togglePressed],
4105
+ children: /* @__PURE__ */ jsx28(HugeiconsIcon14, { icon: controller.videoEnabled ? Video01Icon8 : VideoOffIcon7, size: 24, color: theme.colors.primaryForeground })
4106
+ }
4107
+ )
4108
+ ] }),
4109
+ error ? /* @__PURE__ */ jsx28(Text18, { style: [styles23.globalError, { color: theme.colors.error }], children: error }) : null,
4110
+ /* @__PURE__ */ jsx28(Pressable15, { disabled: !canJoin, onPress: controller.handleJoin, style: ({ pressed }) => [styles23.joinButton, { backgroundColor: canJoin ? theme.colors.primary : theme.colors.muted }, !canJoin && styles23.joinButtonDisabled, pressed && styles23.togglePressed], children: /* @__PURE__ */ jsx28(Text18, { style: [styles23.joinButtonText, { color: theme.colors.primaryForeground }], children: controller.isSubmitting || joinDisabled ? "Joining..." : "Enter Space" }) })
4111
+ ] })
4112
+ ] }) });
4113
+ }
4114
+ var styles23 = StyleSheet24.create({
4115
+ screen: {
4116
+ flex: 1,
4117
+ backgroundColor: Theme.colors.background
4118
+ },
4119
+ content: {
4120
+ flex: 1
4121
+ },
4122
+ floatingBack: {
4123
+ position: "absolute",
4124
+ top: Platform13.OS === "ios" ? 24 : 20,
4125
+ left: 20,
4126
+ width: 42,
4127
+ height: 42,
4128
+ borderRadius: 21,
4129
+ backgroundColor: Theme.colors.darkOverlay40,
4130
+ alignItems: "center",
4131
+ justifyContent: "center",
4132
+ zIndex: 10,
4133
+ borderWidth: 1,
4134
+ borderColor: Theme.colors.whiteOverlay10
4135
+ },
4136
+ previewContainer: {
4137
+ flex: 1,
4138
+ justifyContent: "center",
4139
+ paddingTop: Platform13.OS === "ios" ? 10 : 0,
4140
+ marginBottom: 0
4141
+ },
4142
+ previewSurface: {
4143
+ width: "100%",
4144
+ aspectRatio: 0.72,
4145
+ backgroundColor: Theme.colors.raisedSurface,
4146
+ borderRadius: 32,
4147
+ alignSelf: "center",
4148
+ overflow: "hidden",
4149
+ position: "relative",
4150
+ borderWidth: 1,
4151
+ borderColor: Theme.colors.whiteOverlay06
4152
+ },
4153
+ previewVideo: {
4154
+ ...StyleSheet24.absoluteFillObject
4155
+ },
4156
+ avatarContainer: {
4157
+ ...StyleSheet24.absoluteFillObject,
4158
+ alignItems: "center",
4159
+ justifyContent: "center",
4160
+ backgroundColor: Theme.colors.insetSurface
4161
+ },
4162
+ togglePressed: {
4163
+ opacity: 0.7,
4164
+ transform: [{ scale: 0.9 }]
4165
+ },
4166
+ previewError: {
4167
+ color: Theme.colors.error,
4168
+ fontSize: 12,
4169
+ marginTop: 10,
4170
+ textAlign: "center",
4171
+ fontWeight: "600",
4172
+ paddingHorizontal: 24
4173
+ },
4174
+ previewHint: {
4175
+ color: Theme.colors.mutedForeground,
4176
+ fontSize: 12,
4177
+ marginTop: 10,
4178
+ textAlign: "center",
4179
+ lineHeight: 18,
4180
+ paddingHorizontal: 24
4181
+ },
4182
+ sheetContainer: {
4183
+ backgroundColor: Theme.colors.elevatedSurface,
4184
+ borderTopLeftRadius: 32,
4185
+ borderTopRightRadius: 32,
4186
+ paddingHorizontal: 24,
4187
+ paddingTop: 16,
4188
+ paddingBottom: Platform13.OS === "ios" ? 44 : 32,
4189
+ gap: 20,
4190
+ borderTopWidth: 1,
4191
+ borderColor: Theme.colors.whiteOverlay08,
4192
+ shadowColor: Theme.colors.darkCanvas,
4193
+ shadowOffset: { width: 0, height: -12 },
4194
+ shadowOpacity: 0.3,
4195
+ shadowRadius: 16,
4196
+ elevation: 20
4197
+ },
4198
+ sheetHandle: {
4199
+ width: 36,
4200
+ height: 4,
4201
+ borderRadius: 2,
4202
+ backgroundColor: Theme.colors.whiteOverlay10,
4203
+ alignSelf: "center",
4204
+ marginBottom: 8
4205
+ },
4206
+ sheetHeader: {
4207
+ alignItems: "center",
4208
+ marginBottom: 4
4209
+ },
4210
+ spaceName: {
4211
+ color: Theme.colors.foreground,
4212
+ fontSize: 22,
4213
+ fontWeight: "800",
4214
+ textAlign: "center",
4215
+ letterSpacing: -0.6
4216
+ },
4217
+ inputCard: {
4218
+ flexDirection: "row",
4219
+ alignItems: "center",
4220
+ backgroundColor: Theme.colors.whiteOverlay04,
4221
+ borderRadius: 18,
4222
+ paddingHorizontal: 16,
4223
+ height: 56,
4224
+ borderWidth: 1,
4225
+ borderColor: Theme.colors.whiteOverlay08
4226
+ },
4227
+ inputCardFocused: {
4228
+ borderColor: Theme.colors.primary,
4229
+ backgroundColor: Theme.colors.accentOverlay04
4230
+ },
4231
+ inputIcon: {
4232
+ marginRight: 24
4233
+ },
4234
+ nameInput: {
4235
+ flex: 1,
4236
+ color: Theme.colors.onDark,
4237
+ fontSize: 16,
4238
+ fontWeight: "600",
4239
+ padding: 0
4240
+ },
4241
+ mediaRow: {
4242
+ flexDirection: "row",
4243
+ justifyContent: "center",
4244
+ gap: 20
4245
+ },
4246
+ controlCircle: {
4247
+ width: 64,
4248
+ height: 64,
4249
+ borderRadius: 32,
4250
+ backgroundColor: Theme.colors.whiteOverlay06,
4251
+ alignItems: "center",
4252
+ justifyContent: "center",
4253
+ borderWidth: 1,
4254
+ borderColor: Theme.colors.whiteOverlay10
4255
+ },
4256
+ toggleCircleOff: {
4257
+ backgroundColor: Theme.colors.dangerStrong,
4258
+ borderColor: Theme.colors.dangerStrong
4259
+ },
4260
+ toggleCircleDisabled: {
4261
+ opacity: 0.45
4262
+ },
4263
+ joinButton: {
4264
+ width: "100%",
4265
+ height: 58,
4266
+ borderRadius: 18,
4267
+ alignItems: "center",
4268
+ justifyContent: "center"
4269
+ },
4270
+ joinButtonDisabled: {
4271
+ opacity: 0.6
4272
+ },
4273
+ joinButtonText: {
4274
+ color: Theme.colors.onDark,
4275
+ fontSize: 16,
4276
+ fontWeight: "700"
4277
+ },
4278
+ globalError: {
4279
+ color: Theme.colors.error,
4280
+ fontSize: 13,
4281
+ fontWeight: "600",
4282
+ textAlign: "center"
4283
+ },
4284
+ topIconButtonPressed: {
4285
+ opacity: 0.6,
4286
+ transform: [{ scale: 0.92 }]
4287
+ }
4288
+ });
4289
+
4290
+ // src/components/EntranceView.tsx
4291
+ import { jsx as jsx29 } from "react/jsx-runtime";
4292
+ function EntranceView(props) {
4293
+ switch (resolvePlatformVariant()) {
4294
+ case "ios-pad":
4295
+ return /* @__PURE__ */ jsx29(EntranceViewIosPad, { ...props });
4296
+ case "ios-phone":
4297
+ return /* @__PURE__ */ jsx29(EntranceViewIosPhone, { ...props });
4298
+ case "macos":
4299
+ return /* @__PURE__ */ jsx29(EntranceViewMacos, { ...props });
4300
+ case "tvos":
4301
+ case "android":
4302
+ default:
4303
+ return /* @__PURE__ */ jsx29(EntranceViewAndroid, { ...props });
4304
+ }
4305
+ }
4306
+
4307
+ // src/components/Entrance.tsx
4308
+ import { Image as Image3 } from "react-native";
4309
+ import { jsx as jsx30 } from "react/jsx-runtime";
4310
+ function Entrance({ spaceName, logoUrl, defaultDisplayName, defaults, error, joining = false, onCancel, onJoin }) {
4311
+ return /* @__PURE__ */ jsx30(
4312
+ EntranceView,
4313
+ {
4314
+ error,
4315
+ initialAudioEnabled: defaults?.microphone ?? true,
4316
+ initialVideoEnabled: defaults?.camera ?? true,
4317
+ joinDisabled: joining,
4318
+ logo: logoUrl ? /* @__PURE__ */ jsx30(Image3, { accessibilityLabel: "Chalk", source: { uri: logoUrl }, style: { height: 32, width: 120 } }) : void 0,
4319
+ onCancel,
4320
+ onJoin: ({ displayName, microphoneEnabled, cameraEnabled }) => void onJoin({ displayName, microphone: microphoneEnabled, camera: cameraEnabled }),
4321
+ spaceName,
4322
+ displayName: defaultDisplayName
4323
+ }
4324
+ );
4325
+ }
4326
+
4327
+ // src/components/Chalk.tsx
4328
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
4329
+ function Chalk(props) {
4330
+ const suppliedClient = props.client;
4331
+ const space = props.space;
4332
+ const getAccess = props.getAccess;
4333
+ const getAccessRef = useRef5(getAccess);
4334
+ getAccessRef.current = getAccess;
4335
+ const defaults = useRef5(props.defaults).current;
4336
+ const getLatestAccess = useCallback9((...args) => {
4337
+ const currentGetAccess = getAccessRef.current;
4338
+ if (!currentGetAccess) throw new Error("Chalk requires getAccess when it creates the SpaceClient.");
4339
+ return currentGetAccess(...args);
4340
+ }, []);
4341
+ const ownedClient = useMemo15(
4342
+ () => suppliedClient ? null : createNativeSpaceClient({
4343
+ space,
4344
+ getAccess: getLatestAccess,
4345
+ microphone: defaults?.microphone,
4346
+ camera: defaults?.camera
4347
+ }),
4348
+ [getLatestAccess, space, suppliedClient]
4349
+ );
4350
+ const client = suppliedClient ?? ownedClient;
4351
+ useEffect8(() => {
4352
+ if (!ownedClient) return;
4353
+ return () => {
4354
+ void ownedClient.leave().catch(() => void 0).finally(() => ownedClient.dispose());
4355
+ };
4356
+ }, [ownedClient]);
4357
+ return /* @__PURE__ */ jsx31(NativeAppearanceProvider, { initialAppearance: { palette: props.theme?.palette, texture: props.theme?.texture }, children: /* @__PURE__ */ jsx31(AppearanceThemeBridge, { theme: props.theme, children: /* @__PURE__ */ jsx31(ChalkProvider, { client, children: /* @__PURE__ */ jsx31(SpaceExperience, { ...props }) }) }) });
4358
+ }
4359
+ function AppearanceThemeBridge({ children, theme }) {
4360
+ const { appearance } = useNativeAppearance();
4361
+ return /* @__PURE__ */ jsx31(NativeThemeProvider, { appearance, theme, children });
4362
+ }
4363
+ function SpaceExperience(props) {
4364
+ const client = useSpaceClient();
4365
+ const connection = useConnection();
4366
+ const previousStatus = useRef5(connection.status);
4367
+ const hasObservedStatus = useRef5(false);
4368
+ const hasBeenLive = useRef5(connection.status === "live" || connection.status === "reconnecting");
4369
+ const autoJoinAttempted = useRef5(false);
4370
+ const previousClient = useRef5(client);
4371
+ const [joinError, setJoinError] = useState9(null);
4372
+ if (previousClient.current !== client) {
4373
+ previousClient.current = client;
4374
+ previousStatus.current = connection.status;
4375
+ hasObservedStatus.current = false;
4376
+ hasBeenLive.current = connection.status === "live" || connection.status === "reconnecting";
4377
+ autoJoinAttempted.current = false;
4378
+ }
4379
+ const entrance = props.entrance ?? true;
4380
+ const spaceName = props.spaceName ?? props.space ?? "Space";
4381
+ const join = useCallback9(
4382
+ async (options) => {
4383
+ try {
4384
+ setJoinError(null);
4385
+ await client.join(options);
4386
+ } catch (cause) {
4387
+ setJoinError(cause instanceof Error ? cause.message : "Could not enter this Space.");
4388
+ }
4389
+ },
4390
+ [client]
4391
+ );
4392
+ const retryAutomaticJoin = useCallback9(() => {
4393
+ autoJoinAttempted.current = true;
4394
+ void join(defaultJoinOptions(props));
4395
+ }, [join, props]);
4396
+ useEffect8(() => {
4397
+ setJoinError(null);
4398
+ }, [client]);
4399
+ useEffect8(() => {
4400
+ const subscriptions = [
4401
+ props.onEpisodeEnded && client.on("episodeEnded", props.onEpisodeEnded),
4402
+ props.onParticipantJoined && client.on("participantJoined", props.onParticipantJoined),
4403
+ props.onParticipantLeft && client.on("participantLeft", props.onParticipantLeft),
4404
+ props.onScreenShareStarted && client.on("screenShareStarted", props.onScreenShareStarted),
4405
+ props.onScreenShareStopped && client.on("screenShareStopped", props.onScreenShareStopped),
4406
+ props.onError && client.on("error", props.onError)
4407
+ ].filter((unsubscribe) => Boolean(unsubscribe));
4408
+ return () => subscriptions.forEach((unsubscribe) => unsubscribe());
4409
+ }, [client, props.onEpisodeEnded, props.onError, props.onParticipantJoined, props.onParticipantLeft, props.onScreenShareStarted, props.onScreenShareStopped]);
4410
+ useEffect8(() => {
4411
+ if (!entrance && connection.status === "idle" && !autoJoinAttempted.current) {
4412
+ autoJoinAttempted.current = true;
4413
+ void join(defaultJoinOptions(props));
4414
+ }
4415
+ }, [connection.status, entrance, join, props.defaults?.camera, props.defaults?.microphone, props.displayName]);
4416
+ useEffect8(() => {
4417
+ const previous = previousStatus.current;
4418
+ if (hasObservedStatus.current) {
4419
+ if (connection.status === "live" && previous !== "live" && previous !== "reconnecting") props.onJoined?.();
4420
+ if (connection.status === "left" && previous !== "left") props.onLeft?.();
4421
+ }
4422
+ previousStatus.current = connection.status;
4423
+ hasObservedStatus.current = true;
4424
+ if (connection.status === "live" || connection.status === "reconnecting") hasBeenLive.current = true;
4425
+ }, [connection.status, props.onJoined, props.onLeft]);
4426
+ if (connection.status === "idle" && entrance) {
4427
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(Entrance, { defaultDisplayName: props.displayName, defaults: props.defaults, error: joinError ?? void 0, logoUrl: props.logoUrl, onJoin: join, spaceName }) });
4428
+ }
4429
+ if (connection.status === "idle") {
4430
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(SpaceStatus, { message: joinError ?? `Entering ${spaceName}\u2026`, onRetry: joinError ? retryAutomaticJoin : void 0 }) });
4431
+ }
4432
+ if (connection.status === "joining") {
4433
+ if (!entrance)
4434
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(SpaceStatus, { message: `Entering ${spaceName}\u2026` }) });
4435
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(Entrance, { defaultDisplayName: props.displayName, defaults: props.defaults, joining: true, logoUrl: props.logoUrl, onJoin: join, spaceName }) });
4436
+ }
4437
+ if (connection.status === "failed") {
4438
+ if (!hasBeenLive.current && entrance) {
4439
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(Entrance, { defaultDisplayName: props.displayName, defaults: props.defaults, error: connection.lastError?.message ?? "Unable to enter this Space.", logoUrl: props.logoUrl, onJoin: join, spaceName }) });
4440
+ }
4441
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(SpaceStatus, { message: connection.lastError?.message ?? "This Space is unavailable.", onRetry: () => void join(defaultJoinOptions(props)) }) });
4442
+ }
4443
+ if (connection.status === "leaving")
4444
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(SpaceStatus, { message: `Leaving ${spaceName}\u2026` }) });
4445
+ if (connection.status === "left")
4446
+ return /* @__PURE__ */ jsx31(AppearanceLayer, { children: /* @__PURE__ */ jsx31(SpaceStatus, { message: "You have left this Space.", onRetry: () => void join(defaultJoinOptions(props)) }) });
4447
+ return /* @__PURE__ */ jsx31(NativeSpaceView, { features: props.features, inviteLink: props.inviteLink, layout: props.layout, logoUrl: props.logoUrl, onLayoutChange: props.onLayoutChange, pickChatFiles: props.pickChatFiles, reconnecting: connection.status === "reconnecting", spaceName });
4448
+ }
4449
+ function defaultJoinOptions(props) {
4450
+ const displayName = props.displayName?.trim();
4451
+ return {
4452
+ ...displayName ? { displayName } : {},
4453
+ microphone: props.defaults?.microphone ?? true,
4454
+ camera: props.defaults?.camera ?? true
4455
+ };
4456
+ }
4457
+ function NativeSpaceView({ features, inviteLink, layout, logoUrl, onLayoutChange, pickChatFiles, reconnecting, spaceName }) {
4458
+ const client = useSpaceClient();
4459
+ const theme = useNativeTheme();
4460
+ return /* @__PURE__ */ jsxs22(View24, { style: [styles24.space, { backgroundColor: theme.colors.background }], children: [
4461
+ /* @__PURE__ */ jsx31(SpaceView, { features, inviteLink, layout, logoUrl, onEndEpisode: () => client.endEpisode(), onLayoutChange, onLeave: () => client.leave(), pickChatFiles, reconnecting, spaceName }),
4462
+ /* @__PURE__ */ jsx31(NativeTextureOverlay, {})
4463
+ ] });
4464
+ }
4465
+ function AppearanceLayer({ children }) {
4466
+ const theme = useNativeTheme();
4467
+ return /* @__PURE__ */ jsxs22(View24, { style: [styles24.appearanceLayer, { backgroundColor: theme.colors.background }], children: [
4468
+ children,
4469
+ /* @__PURE__ */ jsx31(NativeTextureOverlay, {})
4470
+ ] });
4471
+ }
4472
+ function SpaceStatus({ message, onRetry }) {
4473
+ const theme = useNativeTheme();
4474
+ return /* @__PURE__ */ jsxs22(View24, { accessibilityLiveRegion: "polite", style: [styles24.status, { backgroundColor: theme.colors.background }], children: [
4475
+ /* @__PURE__ */ jsx31(Text19, { style: [styles24.statusText, { color: theme.colors.foreground }], children: message }),
4476
+ onRetry ? /* @__PURE__ */ jsx31(Pressable16, { accessibilityRole: "button", onPress: onRetry, style: [styles24.retry, { backgroundColor: theme.colors.primary }], children: /* @__PURE__ */ jsx31(Text19, { style: [styles24.retryText, { color: theme.colors.primaryForeground }], children: "Try again" }) }) : null
4477
+ ] });
4478
+ }
4479
+ var styles24 = StyleSheet25.create({
4480
+ space: { flex: 1 },
4481
+ appearanceLayer: { flex: 1 },
4482
+ status: { flex: 1, alignItems: "center", justifyContent: "center", gap: 16, padding: 24 },
4483
+ statusText: { fontSize: 16, textAlign: "center" },
4484
+ retry: { borderRadius: 12, paddingHorizontal: 18, paddingVertical: 12 },
4485
+ retryText: { fontWeight: "800" }
4486
+ });
4487
+
4488
+ export {
4489
+ ChalkProvider,
4490
+ useSpaceClient,
4491
+ useConnection,
4492
+ useSelf,
4493
+ useParticipants,
4494
+ useMedia,
4495
+ useChat,
4496
+ useReactions,
4497
+ useWhiteboard,
4498
+ useCan,
4499
+ Entrance,
4500
+ Chalk
4501
+ };