basalt-core 0.0.0-rc5

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 (325) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/basalt.d.ts +3 -0
  3. package/dist/cli/basalt.d.ts.map +1 -0
  4. package/dist/cli/basalt.js +47 -0
  5. package/dist/cli/basalt.js.map +1 -0
  6. package/dist/cli/bundle-cli.d.ts +12 -0
  7. package/dist/cli/bundle-cli.d.ts.map +1 -0
  8. package/dist/cli/bundle-cli.js +124 -0
  9. package/dist/cli/bundle-cli.js.map +1 -0
  10. package/dist/cli/bundleWithAssets.d.ts +79 -0
  11. package/dist/cli/bundleWithAssets.d.ts.map +1 -0
  12. package/dist/cli/bundleWithAssets.js +198 -0
  13. package/dist/cli/bundleWithAssets.js.map +1 -0
  14. package/dist/cli/desktop.d.ts +339 -0
  15. package/dist/cli/desktop.d.ts.map +1 -0
  16. package/dist/cli/desktop.js +1029 -0
  17. package/dist/cli/desktop.js.map +1 -0
  18. package/dist/cli/doctor.d.ts +31 -0
  19. package/dist/cli/doctor.d.ts.map +1 -0
  20. package/dist/cli/doctor.js +283 -0
  21. package/dist/cli/doctor.js.map +1 -0
  22. package/dist/cli/init.d.ts +77 -0
  23. package/dist/cli/init.d.ts.map +1 -0
  24. package/dist/cli/init.js +442 -0
  25. package/dist/cli/init.js.map +1 -0
  26. package/dist/cli/metro.d.ts +49 -0
  27. package/dist/cli/metro.d.ts.map +1 -0
  28. package/dist/cli/metro.js +148 -0
  29. package/dist/cli/metro.js.map +1 -0
  30. package/dist/cli/packageApp.d.ts +102 -0
  31. package/dist/cli/packageApp.d.ts.map +1 -0
  32. package/dist/cli/packageApp.js +319 -0
  33. package/dist/cli/packageApp.js.map +1 -0
  34. package/dist/cli/steps.d.ts +34 -0
  35. package/dist/cli/steps.d.ts.map +1 -0
  36. package/dist/cli/steps.js +53 -0
  37. package/dist/cli/steps.js.map +1 -0
  38. package/dist/metro-config.d.ts +168 -0
  39. package/dist/metro-config.d.ts.map +1 -0
  40. package/dist/metro-config.js +671 -0
  41. package/dist/metro-config.js.map +1 -0
  42. package/dist/react-native.config.d.ts +7 -0
  43. package/dist/react-native.config.d.ts.map +1 -0
  44. package/dist/react-native.config.js +80 -0
  45. package/dist/react-native.config.js.map +1 -0
  46. package/dist/src/DragSource.d.ts +52 -0
  47. package/dist/src/DragSource.d.ts.map +1 -0
  48. package/dist/src/DragSource.js +97 -0
  49. package/dist/src/DragSource.js.map +1 -0
  50. package/dist/src/DropTarget.d.ts +58 -0
  51. package/dist/src/DropTarget.d.ts.map +1 -0
  52. package/dist/src/DropTarget.js +131 -0
  53. package/dist/src/DropTarget.js.map +1 -0
  54. package/dist/src/KeyHandler.d.ts +57 -0
  55. package/dist/src/KeyHandler.d.ts.map +1 -0
  56. package/dist/src/KeyHandler.js +48 -0
  57. package/dist/src/KeyHandler.js.map +1 -0
  58. package/dist/src/Menu.d.ts +72 -0
  59. package/dist/src/Menu.d.ts.map +1 -0
  60. package/dist/src/Menu.js +179 -0
  61. package/dist/src/Menu.js.map +1 -0
  62. package/dist/src/TitleBar.d.ts +75 -0
  63. package/dist/src/TitleBar.d.ts.map +1 -0
  64. package/dist/src/TitleBar.js +236 -0
  65. package/dist/src/TitleBar.js.map +1 -0
  66. package/dist/src/Window.d.ts +87 -0
  67. package/dist/src/Window.d.ts.map +1 -0
  68. package/dist/src/Window.js +248 -0
  69. package/dist/src/Window.js.map +1 -0
  70. package/dist/src/closeRequest.d.ts +55 -0
  71. package/dist/src/closeRequest.d.ts.map +1 -0
  72. package/dist/src/closeRequest.js +134 -0
  73. package/dist/src/closeRequest.js.map +1 -0
  74. package/dist/src/index.d.ts +45 -0
  75. package/dist/src/index.d.ts.map +1 -0
  76. package/dist/src/index.js +92 -0
  77. package/dist/src/index.js.map +1 -0
  78. package/dist/src/overrides/Alert.d.ts +69 -0
  79. package/dist/src/overrides/Alert.d.ts.map +1 -0
  80. package/dist/src/overrides/Alert.js +112 -0
  81. package/dist/src/overrides/Alert.js.map +1 -0
  82. package/dist/src/overrides/BaseViewConfig.d.ts +28 -0
  83. package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -0
  84. package/dist/src/overrides/BaseViewConfig.js +72 -0
  85. package/dist/src/overrides/BaseViewConfig.js.map +1 -0
  86. package/dist/src/overrides/Platform.linux.d.ts +10 -0
  87. package/dist/src/overrides/Platform.linux.d.ts.map +1 -0
  88. package/dist/src/overrides/Platform.linux.js +15 -0
  89. package/dist/src/overrides/Platform.linux.js.map +1 -0
  90. package/dist/src/overrides/Platform.macos.d.ts +10 -0
  91. package/dist/src/overrides/Platform.macos.d.ts.map +1 -0
  92. package/dist/src/overrides/Platform.macos.js +15 -0
  93. package/dist/src/overrides/Platform.macos.js.map +1 -0
  94. package/dist/src/overrides/Platform.windows.d.ts +10 -0
  95. package/dist/src/overrides/Platform.windows.d.ts.map +1 -0
  96. package/dist/src/overrides/Platform.windows.js +15 -0
  97. package/dist/src/overrides/Platform.windows.js.map +1 -0
  98. package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts +24 -0
  99. package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts.map +1 -0
  100. package/dist/src/overrides/ReactDevToolsSettingsManager.js +30 -0
  101. package/dist/src/overrides/ReactDevToolsSettingsManager.js.map +1 -0
  102. package/dist/src/overrides/RefreshControl.d.ts +52 -0
  103. package/dist/src/overrides/RefreshControl.d.ts.map +1 -0
  104. package/dist/src/overrides/RefreshControl.js +92 -0
  105. package/dist/src/overrides/RefreshControl.js.map +1 -0
  106. package/dist/src/overrides/ScrollView.d.ts +39 -0
  107. package/dist/src/overrides/ScrollView.d.ts.map +1 -0
  108. package/dist/src/overrides/ScrollView.js +59 -0
  109. package/dist/src/overrides/ScrollView.js.map +1 -0
  110. package/dist/src/overrides/Share.d.ts +96 -0
  111. package/dist/src/overrides/Share.d.ts.map +1 -0
  112. package/dist/src/overrides/Share.js +97 -0
  113. package/dist/src/overrides/Share.js.map +1 -0
  114. package/dist/src/overrides/TextInput.d.ts +81 -0
  115. package/dist/src/overrides/TextInput.d.ts.map +1 -0
  116. package/dist/src/overrides/TextInput.js +213 -0
  117. package/dist/src/overrides/TextInput.js.map +1 -0
  118. package/dist/src/overrides/View.d.ts +36 -0
  119. package/dist/src/overrides/View.d.ts.map +1 -0
  120. package/dist/src/overrides/View.js +99 -0
  121. package/dist/src/overrides/View.js.map +1 -0
  122. package/dist/src/overrides/createPlatform.d.ts +32 -0
  123. package/dist/src/overrides/createPlatform.d.ts.map +1 -0
  124. package/dist/src/overrides/createPlatform.js +84 -0
  125. package/dist/src/overrides/createPlatform.js.map +1 -0
  126. package/dist/src/overrides/setUpDeveloperTools.d.ts +28 -0
  127. package/dist/src/overrides/setUpDeveloperTools.d.ts.map +1 -0
  128. package/dist/src/overrides/setUpDeveloperTools.js +84 -0
  129. package/dist/src/overrides/setUpDeveloperTools.js.map +1 -0
  130. package/dist/src/overrides/setUpXHR.d.ts +46 -0
  131. package/dist/src/overrides/setUpXHR.d.ts.map +1 -0
  132. package/dist/src/overrides/setUpXHR.js +236 -0
  133. package/dist/src/overrides/setUpXHR.js.map +1 -0
  134. package/dist/src/quitRequest.d.ts +55 -0
  135. package/dist/src/quitRequest.d.ts.map +1 -0
  136. package/dist/src/quitRequest.js +121 -0
  137. package/dist/src/quitRequest.js.map +1 -0
  138. package/dist/src/resourcePath.d.ts +18 -0
  139. package/dist/src/resourcePath.d.ts.map +1 -0
  140. package/dist/src/resourcePath.js +31 -0
  141. package/dist/src/resourcePath.js.map +1 -0
  142. package/dist/src/responseBody.d.ts +76 -0
  143. package/dist/src/responseBody.d.ts.map +1 -0
  144. package/dist/src/responseBody.js +94 -0
  145. package/dist/src/responseBody.js.map +1 -0
  146. package/dist/src/responseHeaders.d.ts +40 -0
  147. package/dist/src/responseHeaders.d.ts.map +1 -0
  148. package/dist/src/responseHeaders.js +75 -0
  149. package/dist/src/responseHeaders.js.map +1 -0
  150. package/dist/src/titleBarState.d.ts +43 -0
  151. package/dist/src/titleBarState.d.ts.map +1 -0
  152. package/dist/src/titleBarState.js +77 -0
  153. package/dist/src/titleBarState.js.map +1 -0
  154. package/dist/src/useContextMenu.d.ts +113 -0
  155. package/dist/src/useContextMenu.d.ts.map +1 -0
  156. package/dist/src/useContextMenu.js +109 -0
  157. package/dist/src/useContextMenu.js.map +1 -0
  158. package/dist/src/useDialog.d.ts +98 -0
  159. package/dist/src/useDialog.d.ts.map +1 -0
  160. package/dist/src/useDialog.js +112 -0
  161. package/dist/src/useDialog.js.map +1 -0
  162. package/dist/src/useDisplays.d.ts +70 -0
  163. package/dist/src/useDisplays.d.ts.map +1 -0
  164. package/dist/src/useDisplays.js +118 -0
  165. package/dist/src/useDisplays.js.map +1 -0
  166. package/dist/src/useHandledKeys.d.ts +38 -0
  167. package/dist/src/useHandledKeys.d.ts.map +1 -0
  168. package/dist/src/useHandledKeys.js +70 -0
  169. package/dist/src/useHandledKeys.js.map +1 -0
  170. package/dist/src/useWindow.d.ts +140 -0
  171. package/dist/src/useWindow.d.ts.map +1 -0
  172. package/dist/src/useWindow.js +233 -0
  173. package/dist/src/useWindow.js.map +1 -0
  174. package/dist/tsconfig.tsbuildinfo +1 -0
  175. package/native/CMakeLists.txt +355 -0
  176. package/native/bootstrap.sh +613 -0
  177. package/native/cmake/CompilerFlags.cmake +49 -0
  178. package/native/cmake/Expo.cmake +125 -0
  179. package/native/cmake/ReactNativeCore.cmake +612 -0
  180. package/native/cmake/Reanimated.cmake +108 -0
  181. package/native/cmake/Skia.cmake +379 -0
  182. package/native/cmake/ThirdParty.cmake +290 -0
  183. package/native/cmake/Worklets.cmake +67 -0
  184. package/native/cmake/codegen/CMakeLists.txt +32 -0
  185. package/native/core/AppIdentity.cpp +85 -0
  186. package/native/core/AppIdentity.h +59 -0
  187. package/native/core/AppPaths.cpp +96 -0
  188. package/native/core/AppPaths.h +53 -0
  189. package/native/core/AppearanceModule.cpp +60 -0
  190. package/native/core/AppearanceModule.h +40 -0
  191. package/native/core/Backface.h +59 -0
  192. package/native/core/BlobModule.cpp +283 -0
  193. package/native/core/BlobModule.h +76 -0
  194. package/native/core/BlobRegistry.cpp +75 -0
  195. package/native/core/BlobRegistry.h +44 -0
  196. package/native/core/ColorScheme.cpp +105 -0
  197. package/native/core/ColorScheme.h +59 -0
  198. package/native/core/ComponentRegistry.h +30 -0
  199. package/native/core/ControlMetrics.h +37 -0
  200. package/native/core/CoreModules.cpp +592 -0
  201. package/native/core/CoreModules.h +308 -0
  202. package/native/core/DebuggingOverlay.cpp +106 -0
  203. package/native/core/DebuggingOverlay.h +65 -0
  204. package/native/core/DesktopControls.cpp +232 -0
  205. package/native/core/DesktopControls.h +170 -0
  206. package/native/core/DevBundle.cpp +108 -0
  207. package/native/core/DevBundle.h +69 -0
  208. package/native/core/DevMenu.cpp +99 -0
  209. package/native/core/DevMenu.h +75 -0
  210. package/native/core/DialogModule.cpp +150 -0
  211. package/native/core/DialogModule.h +51 -0
  212. package/native/core/DragAndDrop.cpp +45 -0
  213. package/native/core/DragAndDrop.h +225 -0
  214. package/native/core/ExpoImageComponent.cpp +79 -0
  215. package/native/core/ExpoImageComponent.h +80 -0
  216. package/native/core/ExpoModules.cpp +415 -0
  217. package/native/core/ExpoModules.h +115 -0
  218. package/native/core/ExpoRuntime.cpp +366 -0
  219. package/native/core/ExpoRuntime.h +42 -0
  220. package/native/core/FocusRing.h +36 -0
  221. package/native/core/FontRegistry.h +51 -0
  222. package/native/core/GestureHandlerModule.cpp +136 -0
  223. package/native/core/GestureHandlerModule.h +71 -0
  224. package/native/core/Gestures.cpp +533 -0
  225. package/native/core/Gestures.h +145 -0
  226. package/native/core/HoverTracker.cpp +69 -0
  227. package/native/core/HoverTracker.h +109 -0
  228. package/native/core/HttpClient.cpp +282 -0
  229. package/native/core/ImageBytes.cpp +205 -0
  230. package/native/core/ImageBytes.h +29 -0
  231. package/native/core/ImageCache.cpp +51 -0
  232. package/native/core/ImageCache.h +89 -0
  233. package/native/core/JsRuntimeAccess.cpp +70 -0
  234. package/native/core/JsRuntimeAccess.h +60 -0
  235. package/native/core/JsiPromise.h +51 -0
  236. package/native/core/KeyEvents.cpp +116 -0
  237. package/native/core/KeyEvents.h +144 -0
  238. package/native/core/LogBoxSurface.cpp +46 -0
  239. package/native/core/LogBoxSurface.h +68 -0
  240. package/native/core/MenuModel.h +117 -0
  241. package/native/core/MenuModule.cpp +209 -0
  242. package/native/core/MenuModule.h +66 -0
  243. package/native/core/MountingWalk.h +524 -0
  244. package/native/core/PackageModules.cpp.in +25 -0
  245. package/native/core/PackageModules.h +50 -0
  246. package/native/core/PlatformConstantsModule.cpp +63 -0
  247. package/native/core/PlatformConstantsModule.h +64 -0
  248. package/native/core/PlatformServices.h +213 -0
  249. package/native/core/PointerButtons.h +63 -0
  250. package/native/core/PullToRefresh.cpp +57 -0
  251. package/native/core/PullToRefresh.h +73 -0
  252. package/native/core/ReanimatedCompat.h +47 -0
  253. package/native/core/ReanimatedModule.cpp +203 -0
  254. package/native/core/ReanimatedModule.h +55 -0
  255. package/native/core/ScrollAnimation.cpp +59 -0
  256. package/native/core/ScrollAnimation.h +70 -0
  257. package/native/core/ScrollBounds.cpp +26 -0
  258. package/native/core/ScrollBounds.h +68 -0
  259. package/native/core/ScrollIndicator.cpp +50 -0
  260. package/native/core/ScrollIndicator.h +69 -0
  261. package/native/core/ScrollMomentum.cpp +71 -0
  262. package/native/core/ScrollMomentum.h +73 -0
  263. package/native/core/ScrollSnap.cpp +123 -0
  264. package/native/core/ScrollSnap.h +80 -0
  265. package/native/core/ShareFallback.cpp +101 -0
  266. package/native/core/ShareFallback.h +45 -0
  267. package/native/core/SkiaPictureViewComponent.cpp +11 -0
  268. package/native/core/SkiaPictureViewComponent.h +47 -0
  269. package/native/core/SourceCodeModule.cpp +55 -0
  270. package/native/core/SourceCodeModule.h +53 -0
  271. package/native/core/StatusBarModule.cpp +23 -0
  272. package/native/core/StatusBarModule.h +42 -0
  273. package/native/core/TestDialog.cpp +148 -0
  274. package/native/core/TestDialog.h +96 -0
  275. package/native/core/TestKeys.cpp +78 -0
  276. package/native/core/TestKeys.h +50 -0
  277. package/native/core/TestQuitFile.cpp +33 -0
  278. package/native/core/TestQuitFile.h +60 -0
  279. package/native/core/TestSettle.h +192 -0
  280. package/native/core/TitleBarRegions.h +31 -0
  281. package/native/core/TurboModuleProxy.cpp +51 -0
  282. package/native/core/TurboModuleProxy.h +46 -0
  283. package/native/core/UIManagerAccess.cpp +43 -0
  284. package/native/core/UIManagerAccess.h +43 -0
  285. package/native/core/WindowBoundsCache.cpp +319 -0
  286. package/native/core/WindowControl.h +235 -0
  287. package/native/core/WindowHost.h +158 -0
  288. package/native/core/WindowMethods.cpp +167 -0
  289. package/native/core/WindowMethods.h +84 -0
  290. package/native/core/WindowsModule.cpp +448 -0
  291. package/native/core/WindowsModule.h +133 -0
  292. package/native/core/WorkletsModule.cpp +199 -0
  293. package/native/core/WorkletsModule.h +57 -0
  294. package/native/core/portability_probe.cpp +210 -0
  295. package/native/tests/EventRecorder.h +124 -0
  296. package/native/tests/TestHarness.cpp +109 -0
  297. package/native/tests/TestHarness.h +89 -0
  298. package/native/tests/TreeDump.h +49 -0
  299. package/native/tests/test_app_identity.cpp +114 -0
  300. package/native/tests/test_app_paths.cpp +48 -0
  301. package/native/tests/test_appearance.cpp +107 -0
  302. package/native/tests/test_backface.cpp +79 -0
  303. package/native/tests/test_blobs.cpp +157 -0
  304. package/native/tests/test_controls.cpp +185 -0
  305. package/native/tests/test_devbundle.cpp +103 -0
  306. package/native/tests/test_drag_and_drop.cpp +143 -0
  307. package/native/tests/test_gestures.cpp +331 -0
  308. package/native/tests/test_hover.cpp +92 -0
  309. package/native/tests/test_image_cache.cpp +109 -0
  310. package/native/tests/test_js_runtime_access.cpp +137 -0
  311. package/native/tests/test_key_events.cpp +235 -0
  312. package/native/tests/test_momentum.cpp +138 -0
  313. package/native/tests/test_quit_file.cpp +104 -0
  314. package/native/tests/test_scroll_animation.cpp +120 -0
  315. package/native/tests/test_scroll_bounds.cpp +66 -0
  316. package/native/tests/test_scroll_indicator.cpp +149 -0
  317. package/native/tests/test_scroll_snap.cpp +112 -0
  318. package/native/tests/test_settle.cpp +115 -0
  319. package/native/tests/test_share.cpp +75 -0
  320. package/native/tests/test_sourcecode.cpp +62 -0
  321. package/native/tests/test_window_close.cpp +119 -0
  322. package/native/tests/test_window_limits.cpp +123 -0
  323. package/package.json +43 -0
  324. package/react-native.config.js +86 -0
  325. package/supported-versions.json +66 -0
@@ -0,0 +1,73 @@
1
+ // A fling, after the fingers have gone.
2
+ //
3
+ // The two desktops divide this differently, and the split is the whole reason
4
+ // this file exists rather than one platform's private helper.
5
+ //
6
+ // macOS does the deceleration itself. An `NSEvent` carries a `momentumPhase`
7
+ // alongside its ordinary phase, and the system keeps delivering scroll deltas
8
+ // after the fingers lift, tapering off on its own. So the AppKit host models
9
+ // nothing: it reports what it is handed, and `onMomentumScrollBegin` and
10
+ // `onMomentumScrollEnd` are that report.
11
+ //
12
+ // GTK does not. `GtkEventControllerScroll` with the kinetic flag emits one
13
+ // `decelerate` signal carrying the velocity the gesture ended at, and then
14
+ // stops -- the coasting is the application's to run. So there has to be a
15
+ // model, and this is it.
16
+ //
17
+ // ## The model
18
+ //
19
+ // Exponential friction, which is what UIScrollView, Android's OverScroller and
20
+ // every browser use: velocity is multiplied by a constant per millisecond, so
21
+ // distance falls off smoothly and the fling has no fixed duration. React Native
22
+ // already names the constant -- `decelerationRate`, 0.998 for `'normal'` and
23
+ // 0.99 for `'fast'` -- and it is a per-millisecond factor, so the two
24
+ // implementations agree on what a fling feels like without either quoting a
25
+ // number the other does not have.
26
+ //
27
+ // It is deliberately not a spring or a fixed-duration curve. Both would need a
28
+ // target offset up front, and a fling does not have one: where it lands is a
29
+ // consequence of how hard it was thrown.
30
+
31
+ #pragma once
32
+
33
+ namespace basalt {
34
+
35
+ class ScrollMomentum {
36
+ public:
37
+ // React Native's own two, as its `decelerationRate` prop resolves them. The
38
+ // prop is a float, so an app can pass anything between; these are the values
39
+ // `'normal'` and `'fast'` mean.
40
+ static constexpr double kNormalDeceleration = 0.998;
41
+ static constexpr double kFastDeceleration = 0.99;
42
+
43
+ // Begins a fling at a velocity in pixels per second, with the same sign
44
+ // convention as a scroll offset: positive moves the content offset up.
45
+ //
46
+ // Returns false, and starts nothing, for a fling too slow to be worth
47
+ // animating. That check is here rather than in a caller because the threshold
48
+ // and the stopping condition are the same number, and a fling that stops on
49
+ // its first frame is worse than one that never started -- it would report a
50
+ // momentum scroll beginning and ending with nothing in between.
51
+ bool start(double velocityX, double velocityY, double decelerationRate);
52
+
53
+ // Advances the fling by `seconds` and reports how far the offset should move.
54
+ // Returns false once it has stopped, in which case the deltas are the last
55
+ // step and the caller should apply them and finish.
56
+ bool advance(double seconds, double &dx, double &dy);
57
+
58
+ // Stops without reporting a final step. For a fling interrupted by a new
59
+ // gesture, or by the view going away.
60
+ void stop();
61
+
62
+ bool isRunning() const {
63
+ return running_;
64
+ }
65
+
66
+ private:
67
+ bool running_{false};
68
+ double velocityX_{0};
69
+ double velocityY_{0};
70
+ double decelerationRate_{kNormalDeceleration};
71
+ };
72
+
73
+ } // namespace basalt
@@ -0,0 +1,123 @@
1
+ #include "ScrollSnap.h"
2
+
3
+ #include <algorithm>
4
+ #include <cmath>
5
+
6
+ namespace basalt {
7
+
8
+ namespace {
9
+
10
+ // What the alignment shifts by: a centred snap lines the middle of the
11
+ // container up with a point, an end-aligned one lines up its trailing edge.
12
+ double alignmentShift(ScrollSnapAlignment alignment, double containerLength) {
13
+ switch (alignment) {
14
+ case ScrollSnapAlignment::Start:
15
+ return 0.0;
16
+ case ScrollSnapAlignment::Center:
17
+ return containerLength / 2.0;
18
+ case ScrollSnapAlignment::End:
19
+ return containerLength;
20
+ }
21
+ return 0.0;
22
+ }
23
+
24
+ double clampToContent(double offset, double containerLength, double contentLength) {
25
+ const double furthest = std::max(0.0, contentLength - containerLength);
26
+ return std::clamp(offset, 0.0, furthest);
27
+ }
28
+
29
+ // The nearest of an explicit list, with a flick moving at least one entry.
30
+ std::optional<double> nearestOffset(const std::vector<double> &offsets,
31
+ double offset,
32
+ double velocity) {
33
+ if (offsets.empty()) {
34
+ return std::nullopt;
35
+ }
36
+ std::vector<double> sorted = offsets;
37
+ std::sort(sorted.begin(), sorted.end());
38
+
39
+ auto nearest = sorted.begin();
40
+ double best = std::abs(sorted.front() - offset);
41
+ for (auto it = sorted.begin(); it != sorted.end(); ++it) {
42
+ const double distance = std::abs(*it - offset);
43
+ if (distance < best) {
44
+ best = distance;
45
+ nearest = it;
46
+ }
47
+ }
48
+
49
+ if (velocity > kScrollSnapFlickVelocity) {
50
+ // The first entry strictly past where we are. A flick forwards must not
51
+ // settle back on the point it started from.
52
+ for (auto it = sorted.begin(); it != sorted.end(); ++it) {
53
+ if (*it > offset) {
54
+ return *it;
55
+ }
56
+ }
57
+ return sorted.back();
58
+ }
59
+ if (velocity < -kScrollSnapFlickVelocity) {
60
+ for (auto it = sorted.rbegin(); it != sorted.rend(); ++it) {
61
+ if (*it < offset) {
62
+ return *it;
63
+ }
64
+ }
65
+ return sorted.front();
66
+ }
67
+ return *nearest;
68
+ }
69
+
70
+ } // namespace
71
+
72
+ std::optional<double> scrollSnapTarget(const ScrollSnapConfig &config,
73
+ double offset,
74
+ double velocity,
75
+ double containerLength,
76
+ double contentLength) {
77
+ if (!config.enabled()) {
78
+ return std::nullopt;
79
+ }
80
+
81
+ // An explicit list wins over a spacing, and a spacing over paging only when
82
+ // paging is off: `pagingEnabled` is the coarsest statement and iOS lets it
83
+ // take precedence.
84
+ if (!config.paging && !config.offsets.empty()) {
85
+ const auto target = nearestOffset(config.offsets, offset, velocity);
86
+ if (!target) {
87
+ return std::nullopt;
88
+ }
89
+ return clampToContent(*target, containerLength, contentLength);
90
+ }
91
+
92
+ const double interval = config.paging ? containerLength : config.interval;
93
+ if (interval <= 0.0) {
94
+ return std::nullopt;
95
+ }
96
+
97
+ // Aligned snapping is the same arithmetic about a shifted point: what lines
98
+ // up with a multiple is the container's leading edge, its middle, or its
99
+ // trailing edge.
100
+ const double shift = alignmentShift(config.alignment, containerLength);
101
+ const double aligned = offset + shift;
102
+
103
+ double index = std::floor(aligned / interval);
104
+ const double within = aligned - index * interval;
105
+
106
+ if (velocity > kScrollSnapFlickVelocity) {
107
+ index += 1.0;
108
+ } else if (velocity < -kScrollSnapFlickVelocity) {
109
+ // Already past a boundary by less than half means the flick backwards is
110
+ // to the boundary itself rather than the one before it.
111
+ if (within > 0.0) {
112
+ // index already floors to the boundary behind us.
113
+ } else {
114
+ index -= 1.0;
115
+ }
116
+ } else if (within > interval / 2.0) {
117
+ index += 1.0;
118
+ }
119
+
120
+ return clampToContent(index * interval - shift, containerLength, contentLength);
121
+ }
122
+
123
+ } // namespace basalt
@@ -0,0 +1,80 @@
1
+ // Where a scroll should come to rest.
2
+ //
3
+ // `pagingEnabled`, `snapToInterval` and `snapToOffsets` are how a carousel, a
4
+ // paged list and a stop-at-each-card list are written in React Native, and none
5
+ // of them did anything here: a drag ended wherever the fingers left it.
6
+ //
7
+ // ## Why this is arithmetic and not a host's business
8
+ //
9
+ // Choosing the resting point needs the offset, the velocity, the container, the
10
+ // content and the props -- and nothing from a toolkit. So it is decided here,
11
+ // once, and each host does the same two things with the answer: stop the fling
12
+ // and animate to it, which is what `core/ScrollAnimation.h` is for.
13
+ //
14
+ // That also makes it testable. Almost nothing about a scroll view on these
15
+ // hosts can be asserted without a display; this can.
16
+ //
17
+ // ## The rules
18
+ //
19
+ // A flick settles on the next point in the direction it was flicked, even when
20
+ // the finger left nearer the point behind. That is what makes a carousel feel
21
+ // like a carousel rather than a list that sometimes changes page -- and it is
22
+ // why velocity is a parameter rather than the caller simply passing the offset
23
+ // it landed on.
24
+ //
25
+ // "Next in that direction" rather than "a whole page on": twenty pixels into a
26
+ // page, flicked back, the answer is that page's start and not the one before
27
+ // it. The rule is symmetric -- forwards from the same place is the page ahead --
28
+ // and a small flick must not be able to travel further than a large one.
29
+ //
30
+ // Below that threshold the nearest point wins, which is the behaviour of
31
+ // letting go without meaning anything by it.
32
+
33
+ #pragma once
34
+
35
+ #include <optional>
36
+ #include <vector>
37
+
38
+ namespace basalt {
39
+
40
+ // Where in the container a snap point should line up, as React Native's
41
+ // `snapToAlignment` names it.
42
+ enum class ScrollSnapAlignment {
43
+ Start,
44
+ Center,
45
+ End,
46
+ };
47
+
48
+ struct ScrollSnapConfig {
49
+ // `pagingEnabled`: the interval is the container's own length, so a page is a
50
+ // screenful. Takes precedence over the two below, as it does on iOS.
51
+ bool paging{false};
52
+ // `snapToInterval`, in points. Zero means unused.
53
+ double interval{0.0};
54
+ // `snapToOffsets`. Empty means unused; when set it wins over `interval`,
55
+ // because a list of explicit points is a more specific statement than a
56
+ // spacing.
57
+ std::vector<double> offsets;
58
+ ScrollSnapAlignment alignment{ScrollSnapAlignment::Start};
59
+
60
+ bool enabled() const {
61
+ return paging || interval > 0.0 || !offsets.empty();
62
+ }
63
+ };
64
+
65
+ // Pixels per second past which a gesture counts as a flick rather than a
66
+ // release. Low enough that a deliberate flick always carries, high enough that
67
+ // the wobble of letting go does not.
68
+ inline constexpr double kScrollSnapFlickVelocity = 250.0;
69
+
70
+ // The offset to settle at, or nothing when no snapping is configured.
71
+ //
72
+ // `velocity` is in pixels per second, positive meaning the content offset is
73
+ // growing -- the same sign convention as everything else here.
74
+ std::optional<double> scrollSnapTarget(const ScrollSnapConfig &config,
75
+ double offset,
76
+ double velocity,
77
+ double containerLength,
78
+ double contentLength);
79
+
80
+ } // namespace basalt
@@ -0,0 +1,101 @@
1
+ #include "ShareFallback.h"
2
+
3
+ #include "TestDialog.h"
4
+
5
+ #include <array>
6
+ #include <string>
7
+
8
+ namespace basalt {
9
+
10
+ namespace {
11
+
12
+ // RFC 3986's unreserved set, plus nothing. A `mailto:` is built by
13
+ // concatenation, so anything else has to be encoded or it changes the meaning
14
+ // of the URL rather than appearing in it -- an `&` in a message being the case
15
+ // that actually bites, because it ends the body and starts a header.
16
+ bool isUnreserved(unsigned char c) {
17
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' ||
18
+ c == '_' || c == '.' || c == '~';
19
+ }
20
+
21
+ std::string percentEncode(const std::string &text) {
22
+ static constexpr std::array<char, 16> kHex{
23
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
24
+ std::string out;
25
+ out.reserve(text.size());
26
+ for (const char raw : text) {
27
+ const auto c = static_cast<unsigned char>(raw);
28
+ if (isUnreserved(c)) {
29
+ out.push_back(raw);
30
+ continue;
31
+ }
32
+ out.push_back('%');
33
+ out.push_back(kHex[c >> 4U]);
34
+ out.push_back(kHex[c & 0x0FU]);
35
+ }
36
+ return out;
37
+ }
38
+
39
+ // The two buttons and the way out, in the order the alert shows them. React
40
+ // Native's alerts put the cancelling one last on both desktops, so this does
41
+ // too.
42
+ constexpr int kCopyButton = 0;
43
+ constexpr int kEmailButton = 1;
44
+
45
+ } // namespace
46
+
47
+ std::string shareClipboardText(const ShareRequest &request) {
48
+ // Both, when an app gave both: a link with a sentence explaining it is what
49
+ // most calls to Share are, and dropping either would be dropping half of what
50
+ // was asked for.
51
+ if (request.message.empty()) {
52
+ return request.url;
53
+ }
54
+ if (request.url.empty()) {
55
+ return request.message;
56
+ }
57
+ return request.message + "\n" + request.url;
58
+ }
59
+
60
+ std::string shareMailtoUrl(const ShareRequest &request) {
61
+ std::string url = "mailto:?body=" + percentEncode(shareClipboardText(request));
62
+ if (!request.title.empty()) {
63
+ url += "&subject=" + percentEncode(request.title);
64
+ }
65
+ return url;
66
+ }
67
+
68
+ void shareThroughFallbackPicker(const ShareRequest &request, ShareCallback onDone) {
69
+ AlertRequest alert;
70
+ // The app's own words for the picker when it gave any, which is what
71
+ // `options.dialogTitle` is for.
72
+ alert.title = request.dialogTitle.empty() ? "Share" : request.dialogTitle;
73
+ // The content, so a person can see what they are about to send. A share sheet
74
+ // shows a preview and this is the plainest form of one.
75
+ alert.message = shareClipboardText(request);
76
+ alert.buttons = {"Copy", "Email", "Cancel"};
77
+
78
+ presentAlert(alert, [request, onDone = std::move(onDone)](int button, const std::string &) {
79
+ switch (button) {
80
+ case kCopyButton:
81
+ setClipboardText(shareClipboardText(request));
82
+ onDone(ShareOutcome::Shared, "");
83
+ return;
84
+ case kEmailButton:
85
+ if (openUrl(shareMailtoUrl(request))) {
86
+ onDone(ShareOutcome::Shared, "");
87
+ } else {
88
+ // No mail client, or nothing registered for `mailto:`. A failure
89
+ // rather than a dismissal: the person chose to send it and it did not
90
+ // go, which is not the same as changing their mind.
91
+ onDone(ShareOutcome::Failed, "no application is registered for mailto:");
92
+ }
93
+ return;
94
+ default:
95
+ onDone(ShareOutcome::Dismissed, "");
96
+ return;
97
+ }
98
+ });
99
+ }
100
+
101
+ } // namespace basalt
@@ -0,0 +1,45 @@
1
+ // A share sheet for the desktops that do not have one.
2
+ //
3
+ // `Share.share()` promises a picker. macOS has `NSSharingServicePicker` and
4
+ // means it. Windows has the `DataTransferManager` share UI, reachable through
5
+ // WinRT interop. Linux has neither: there is no share portal, GNOME and KDE
6
+ // expose no such API, and the nearest thing in the freedesktop specifications
7
+ // is `xdg-email`, which is one destination rather than a choice of them.
8
+ //
9
+ // So the options were to reject on the desktops with no service, or to build
10
+ // the smallest honest picker out of what every desktop does have. This is the
11
+ // second. A share sheet is a list of places to send something, and the two
12
+ // entries on it that every desktop can actually perform are *the clipboard* and
13
+ // *an email*. Both already have seams here -- `setClipboardText` and `openUrl`
14
+ // -- so this file is a dialog and a `mailto:` and nothing platform-specific at
15
+ // all.
16
+ //
17
+ // It is deliberately not dressed up as a native share sheet. A person sees a
18
+ // dialog with the message in it and two things they can do with it, which is
19
+ // what is true; pretending to be a service picker that does not exist would be
20
+ // worse than being a plain one that does.
21
+ //
22
+ // An implementation that wants the real thing on Windows should replace its
23
+ // `shareContent` and leave this alone; see docs/BACKLOG.md.
24
+
25
+ #pragma once
26
+
27
+ #include "PlatformServices.h"
28
+
29
+ namespace basalt {
30
+
31
+ // The text a share puts on the clipboard: the message and the URL, whichever of
32
+ // them the app supplied, one per line. Exposed for the tests, because it is the
33
+ // only part of this with an answer that can be wrong.
34
+ std::string shareClipboardText(const ShareRequest &request);
35
+
36
+ // `mailto:` for the same content, with the title as the subject. Percent-encoded
37
+ // as RFC 6068 requires, which matters more than it looks: a message with an
38
+ // ampersand in it silently truncates the body of the draft otherwise.
39
+ std::string shareMailtoUrl(const ShareRequest &request);
40
+
41
+ // Shows the picker and reports what was chosen. The implementation of
42
+ // `shareContent` on every desktop that has no service of its own.
43
+ void shareThroughFallbackPicker(const ShareRequest &request, ShareCallback onDone);
44
+
45
+ } // namespace basalt
@@ -0,0 +1,11 @@
1
+ #include "SkiaPictureViewComponent.h"
2
+
3
+ namespace facebook::react {
4
+
5
+ // The name the package's JavaScript registers, from
6
+ // `codegenNativeComponent<NativeProps>("SkiaPictureView")`. No adapter prefix:
7
+ // this is a codegen component rather than an Expo view manager, so the name is
8
+ // the name.
9
+ extern const char SkiaPictureViewComponentName[] = "SkiaPictureView";
10
+
11
+ } // namespace facebook::react
@@ -0,0 +1,47 @@
1
+ // `SkiaPictureView`, which is what a `<Canvas>` from @shopify/react-native-skia
2
+ // mounts.
3
+ //
4
+ // Plain `ViewProps`, unlike core/ExpoImageComponent.h which needed its own props
5
+ // class -- and for a reason worth stating, because it looks like a shortcut and
6
+ // is not. A `<Canvas>` does not carry its content in props. It renders a
7
+ // `SkPicture` in JavaScript and pushes it through the Skia JSI API keyed by an
8
+ // id, and the only thing the native side needs from props is which id it is:
9
+ //
10
+ // <SkiaPictureViewNativeComponent nativeID={`${nativeId}`} ... />
11
+ //
12
+ // `nativeID` is an ordinary `ViewProps` field, so it arrives on any component
13
+ // whatever its view config says. That sidesteps the trap ExpoImageComponent.h
14
+ // spends a paragraph on: a prop absent from the JavaScript view config is
15
+ // dropped before it is ever diffed, silently. Here there is nothing to drop.
16
+ //
17
+ // What *is* dropped: `debug`, `opaque`, `colorSpace` and `highBitDepth`, the four
18
+ // props the package's spec declares. They are decoration -- an FPS overlay, an
19
+ // opaque backing, P3, ten bits a channel -- and a canvas without them draws the
20
+ // same picture. The same call ExpoImage makes about placeholders and blurhash.
21
+ // When one is wanted, it belongs in a props class here and in the peer.
22
+ //
23
+ // Registered unconditionally, like ExpoImage and for the same reason: it costs a
24
+ // name in a registry, and the alternative is a host that has to be rebuilt to
25
+ // run an app that draws. Without Skia in the build the view mounts and stays
26
+ // empty -- but an app that draws will already have failed at
27
+ // `getEnforcing('RNSkiaModule')` long before, which is the error that says what
28
+ // is actually missing.
29
+
30
+ #pragma once
31
+
32
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
33
+ #include <react/renderer/components/view/ViewEventEmitter.h>
34
+ #include <react/renderer/components/view/ViewProps.h>
35
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
36
+
37
+ namespace facebook::react {
38
+
39
+ extern const char SkiaPictureViewComponentName[];
40
+
41
+ using SkiaPictureViewShadowNode =
42
+ ConcreteViewShadowNode<SkiaPictureViewComponentName, ViewProps, ViewEventEmitter>;
43
+
44
+ using SkiaPictureViewComponentDescriptor =
45
+ ConcreteComponentDescriptor<SkiaPictureViewShadowNode>;
46
+
47
+ } // namespace facebook::react
@@ -0,0 +1,55 @@
1
+ #include "SourceCodeModule.h"
2
+
3
+ #include <filesystem>
4
+
5
+ namespace basalt {
6
+
7
+ facebook::jsi::Object DesktopSourceCodeModule::getConstants(facebook::jsi::Runtime &rt) {
8
+ facebook::jsi::Object constants(rt);
9
+ constants.setProperty(rt, "scriptURL", facebook::jsi::String::createFromUtf8(rt, scriptURL_));
10
+ return constants;
11
+ }
12
+
13
+ std::string scriptURLFor(const std::string &bundlePath,
14
+ bool devMode,
15
+ const std::string &devHost,
16
+ unsigned int devPort,
17
+ const std::string &devEntry,
18
+ const std::string &platform) {
19
+ if (devMode) {
20
+ // Shaped like the URL the dev server actually served, because React Native
21
+ // recovers the server's address by stripping the path off this. Assets then
22
+ // resolve to that server, which is what makes them work in development
23
+ // without anything being copied anywhere. And the platform is the host's
24
+ // own, because HMRClient registers this URL for Fast Refresh; see the
25
+ // header.
26
+ return "http://" + devHost + ":" + std::to_string(devPort) + "/" + devEntry +
27
+ ".bundle?platform=" + platform + "&dev=true";
28
+ }
29
+
30
+ // Absolute and fully formed: React Native tests this with
31
+ // startsWith('file://') and then takes the directory beside it, so a relative
32
+ // path silently produces an asset URL that resolves nowhere.
33
+ std::error_code ignored;
34
+ const std::filesystem::path absolute = std::filesystem::absolute(bundlePath, ignored);
35
+
36
+ // `generic_string`, not `string`: on Windows the native form is
37
+ // `D:\build\x.js`, and `resolveAssetSource` finds the bundle's directory
38
+ // with `scriptURL.lastIndexOf('/')`. With no forward slash in it that is -1,
39
+ // the directory comes out empty, and every `require()`d image resolves to
40
+ // `file://assets/...` -- a URI with an authority and no path, which opens
41
+ // nothing. It cost a green Linux run and a red Windows one to find, and it
42
+ // was never about LogBox: it is every asset on that platform.
43
+ std::string path = absolute.lexically_normal().generic_string();
44
+
45
+ // And the third slash. A POSIX path already starts with one, so `file://` and
46
+ // `/Users/x` make `file:///Users/x`; a Windows path starts at the drive
47
+ // letter and has to be given one, which is what every browser and URI library
48
+ // does with `file:///C:/x`.
49
+ if (path.empty() || path.front() != '/') {
50
+ path.insert(path.begin(), '/');
51
+ }
52
+ return "file://" + path;
53
+ }
54
+
55
+ } // namespace basalt
@@ -0,0 +1,53 @@
1
+ // `SourceCode`, which is how JavaScript learns where the bundle came from.
2
+ //
3
+ // It sounds like diagnostics and is not: React Native's asset resolution is
4
+ // built on it. `AssetSourceResolver` asks whether the script came from a server
5
+ // or from a file, and answers `require('./logo.png')` with either a URL on that
6
+ // server or a path beside that file. With no script URL, every asset resolves
7
+ // to nonsense -- `file://assets/assets/logo.png`, in the case that led here.
8
+ //
9
+ // ReactCxxPlatform ships a SourceCode module, and on React Native 0.86 it is
10
+ // always handed an empty string: `ReactHost` has no `sourceURL_` at all, and
11
+ // 0.87 added one. Rather than support this on the versions that happen to fill
12
+ // it in, the host reports the URL itself, which it has known all along.
13
+
14
+ #pragma once
15
+
16
+ #include <FBReactNativeSpec/FBReactNativeSpecJSI.h>
17
+
18
+ #include <string>
19
+
20
+ namespace basalt {
21
+
22
+ class DesktopSourceCodeModule
23
+ : public facebook::react::NativeSourceCodeCxxSpec<DesktopSourceCodeModule> {
24
+ public:
25
+ DesktopSourceCodeModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker, std::string scriptURL)
26
+ : NativeSourceCodeCxxSpec(std::move(jsInvoker)), scriptURL_(std::move(scriptURL)) {}
27
+
28
+ facebook::jsi::Object getConstants(facebook::jsi::Runtime &rt);
29
+
30
+ private:
31
+ std::string scriptURL_;
32
+ };
33
+
34
+ // The URL to report for a bundle loaded from `bundlePath`, or from a dev server
35
+ // when one is in use.
36
+ //
37
+ // A file URL has to be absolute and fully formed: React Native tests it with
38
+ // `startsWith('file://')` and then takes the directory beside it, so a relative
39
+ // path silently produces an asset URL that resolves nowhere.
40
+ //
41
+ // A dev server URL has to name the host's platform. React Native's HMRClient
42
+ // registers exactly this URL with Metro, and Metro keys the module graph it
43
+ // sends updates for by the platform in it. This used to say `linux` on every
44
+ // host, so on Windows Metro dutifully sent Fast Refresh updates for a Linux
45
+ // graph that the running app did not have, and no edit ever appeared.
46
+ std::string scriptURLFor(const std::string &bundlePath,
47
+ bool devMode,
48
+ const std::string &devHost,
49
+ unsigned int devPort,
50
+ const std::string &devEntry,
51
+ const std::string &platform);
52
+
53
+ } // namespace basalt
@@ -0,0 +1,23 @@
1
+ #include "StatusBarModule.h"
2
+
3
+ namespace basalt {
4
+
5
+ using facebook::jsi::Object;
6
+ using facebook::jsi::Runtime;
7
+
8
+ Object DesktopStatusBarModule::getConstants(Runtime &rt) {
9
+ Object constants(rt);
10
+ // Zero, and meant literally. React Native's own JavaScript lays out around
11
+ // this value, so reporting a plausible-looking phone height would push every
12
+ // app's content down by a status bar that is not there.
13
+ constants.setProperty(rt, "HEIGHT", 0.0);
14
+ constants.setProperty(rt, "DEFAULT_BACKGROUND_COLOR", 0.0);
15
+ return constants;
16
+ }
17
+
18
+ void DesktopStatusBarModule::setColor(Runtime & /*rt*/, double /*color*/, bool /*animated*/) {}
19
+ void DesktopStatusBarModule::setTranslucent(Runtime & /*rt*/, bool /*translucent*/) {}
20
+ void DesktopStatusBarModule::setStyle(Runtime & /*rt*/, std::optional<std::string> /*style*/) {}
21
+ void DesktopStatusBarModule::setHidden(Runtime & /*rt*/, bool /*hidden*/) {}
22
+
23
+ } // namespace basalt
@@ -0,0 +1,42 @@
1
+ // `StatusBarManager`, which a desktop does not have.
2
+ //
3
+ // React Native's <StatusBar> resolves to this module, and `expo-status-bar`
4
+ // wraps it, so the component that a blank Expo app puts on screen by default
5
+ // reaches for it before rendering. It is looked up with getEnforcing, so its
6
+ // absence is not a quiet no-op -- it throws, and takes the app's first render
7
+ // with it.
8
+ //
9
+ // So the module exists and does nothing, which is the truthful implementation
10
+ // rather than a placeholder. There is no status bar on a desktop: its height is
11
+ // zero, and hiding or styling something with no pixels is a no-op in the
12
+ // strongest sense, not a stub waiting to be filled in.
13
+ //
14
+ // The Android spec is the one implemented, for the same reason the platform
15
+ // constants module answers the Android shape: this platform reports Android
16
+ // constants and shares Android's JavaScript. The iOS spec carries methods about
17
+ // network activity indicators that mean even less here.
18
+
19
+ #pragma once
20
+
21
+ #include <FBReactNativeSpec/FBReactNativeSpecJSI.h>
22
+
23
+ #include <optional>
24
+ #include <string>
25
+
26
+ namespace basalt {
27
+
28
+ class DesktopStatusBarModule
29
+ : public facebook::react::NativeStatusBarManagerAndroidCxxSpec<DesktopStatusBarModule> {
30
+ public:
31
+ explicit DesktopStatusBarModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker)
32
+ : NativeStatusBarManagerAndroidCxxSpec(std::move(jsInvoker)) {}
33
+
34
+ facebook::jsi::Object getConstants(facebook::jsi::Runtime &rt);
35
+
36
+ void setColor(facebook::jsi::Runtime &rt, double color, bool animated);
37
+ void setTranslucent(facebook::jsi::Runtime &rt, bool translucent);
38
+ void setStyle(facebook::jsi::Runtime &rt, std::optional<std::string> statusBarStyle);
39
+ void setHidden(facebook::jsi::Runtime &rt, bool hidden);
40
+ };
41
+
42
+ } // namespace basalt