react-native-unistyles 3.1.0 → 3.2.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 (57) hide show
  1. package/README.md +180 -0
  2. package/android/src/main/cxx/NativeUnistylesModule.cpp +2 -5
  3. package/android/src/main/cxx/NativeUnistylesModule.h +1 -7
  4. package/android/src/main/java/com/unistyles/Equatable.kt +5 -1
  5. package/android/src/main/java/com/unistyles/NativePlatform+android.kt +6 -1
  6. package/android/src/main/java/com/unistyles/NativePlatform+listener.kt +21 -3
  7. package/cxx/core/UnistyleWrapper.h +2 -2
  8. package/cxx/core/UnistylesRegistry.cpp +57 -48
  9. package/cxx/core/UnistylesRegistry.h +16 -14
  10. package/cxx/core/UnistylesState.cpp +22 -20
  11. package/cxx/core/UnistylesState.h +5 -6
  12. package/cxx/hybridObjects/HybridShadowRegistry.cpp +14 -3
  13. package/cxx/hybridObjects/HybridShadowRegistry.h +5 -0
  14. package/cxx/hybridObjects/HybridStyleSheet.cpp +71 -45
  15. package/cxx/hybridObjects/HybridUnistylesRuntime.cpp +22 -32
  16. package/cxx/hybridObjects/HybridUnistylesRuntime.h +3 -4
  17. package/cxx/parser/Parser.cpp +14 -14
  18. package/ios/UnistylesModuleOnLoad.mm +3 -10
  19. package/lib/commonjs/core/useProxifiedUnistyles/useProxifiedUnistyles.js +4 -1
  20. package/lib/commonjs/core/useProxifiedUnistyles/useProxifiedUnistyles.js.map +1 -1
  21. package/lib/commonjs/specs/ShadowRegistry/index.js +20 -1
  22. package/lib/commonjs/specs/ShadowRegistry/index.js.map +1 -1
  23. package/lib/commonjs/web/convert/style.js +6 -6
  24. package/lib/commonjs/web/convert/style.js.map +1 -1
  25. package/lib/commonjs/web/listener.js +6 -0
  26. package/lib/commonjs/web/listener.js.map +1 -1
  27. package/lib/commonjs/web/utils/createUnistylesRef.js +1 -1
  28. package/lib/commonjs/web/utils/createUnistylesRef.js.map +1 -1
  29. package/lib/module/core/useProxifiedUnistyles/useProxifiedUnistyles.js +4 -1
  30. package/lib/module/core/useProxifiedUnistyles/useProxifiedUnistyles.js.map +1 -1
  31. package/lib/module/specs/ShadowRegistry/index.js +20 -1
  32. package/lib/module/specs/ShadowRegistry/index.js.map +1 -1
  33. package/lib/module/web/convert/style.js +6 -6
  34. package/lib/module/web/convert/style.js.map +1 -1
  35. package/lib/module/web/listener.js +6 -0
  36. package/lib/module/web/listener.js.map +1 -1
  37. package/lib/module/web/utils/createUnistylesRef.js +1 -1
  38. package/lib/module/web/utils/createUnistylesRef.js.map +1 -1
  39. package/lib/typescript/src/core/useProxifiedUnistyles/useProxifiedUnistyles.d.ts.map +1 -1
  40. package/lib/typescript/src/specs/ShadowRegistry/index.d.ts +2 -1
  41. package/lib/typescript/src/specs/ShadowRegistry/index.d.ts.map +1 -1
  42. package/lib/typescript/src/web/listener.d.ts.map +1 -1
  43. package/nitrogen/generated/android/c++/JColorScheme.hpp +1 -1
  44. package/nitrogen/generated/android/c++/JDimensions.hpp +1 -1
  45. package/nitrogen/generated/android/c++/JFunc_void_UnistylesNativeMiniRuntime.hpp +2 -2
  46. package/nitrogen/generated/android/c++/JFunc_void_std__vector_UnistyleDependency__UnistylesNativeMiniRuntime.hpp +2 -2
  47. package/nitrogen/generated/android/c++/JHybridNativePlatformSpec.hpp +2 -2
  48. package/nitrogen/generated/android/c++/JInsets.hpp +1 -1
  49. package/nitrogen/generated/android/c++/JOrientation.hpp +1 -1
  50. package/nitrogen/generated/android/c++/JUnistyleDependency.hpp +1 -1
  51. package/nitrogen/generated/android/c++/JUnistylesNativeMiniRuntime.hpp +1 -1
  52. package/package.json +3 -3
  53. package/src/core/useProxifiedUnistyles/useProxifiedUnistyles.ts +4 -1
  54. package/src/specs/ShadowRegistry/index.ts +36 -2
  55. package/src/web/convert/style.ts +6 -6
  56. package/src/web/listener.ts +6 -0
  57. package/src/web/utils/createUnistylesRef.ts +1 -1
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ [<img alt="react-native-unistyles" src="assets/banner3.png">](https://unistyl.es/)
2
+
3
+ [![npm version](https://img.shields.io/npm/v/react-native-unistyles?style=for-the-badge)](https://www.npmjs.com/package/react-native-unistyles)
4
+ [![npm downloads](https://img.shields.io/npm/dm/react-native-unistyles?style=for-the-badge)](https://www.npmjs.com/package/react-native-unistyles)
5
+ [![npm downloads](https://img.shields.io/npm/dt/react-native-unistyles?style=for-the-badge)](https://www.npmjs.com/package/react-native-unistyles)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-44CD11.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)
7
+ <br />
8
+ [![platform - expo](https://img.shields.io/badge/Expo-fff?style=for-the-badge&logo=expo&logoColor=black)](https://docs.expo.dev/)
9
+ [![platform - web](https://img.shields.io/badge/Web-white?logo=react&logoColor=57BDDA&style=for-the-badge)](https://www.w3.org/)
10
+ [![platform - ios](https://img.shields.io/badge/iOS-000?logo=apple&style=for-the-badge)](https://developer.apple.com/ios/)
11
+ [![platform - android](https://img.shields.io/badge/Android-44CD11?style=for-the-badge&logo=android&logoColor=white)](https://developer.android.com/)
12
+ [![platform - ssr](https://img.shields.io/badge/SSR-black?style=for-the-badge&logo=next.js&logoColor=white)](https://nextjs.org/)
13
+
14
+
15
+ ## Installation
16
+
17
+ ```shell
18
+ yarn add react-native-unistyles
19
+ ```
20
+
21
+ Install dependencies:
22
+
23
+ ```shell
24
+ yarn add react-native-nitro-modules
25
+ ```
26
+
27
+ | react-native-unistyles | Minimum react-native-nitro-modules |
28
+ |------------------------|----------------------------------------|
29
+ | >= 3.0.0 | >= 0.33.9 |
30
+ | >= 3.1.0 | >= 0.35.0 |
31
+ | >= 3.2.0 | >= 0.35.2 |
32
+
33
+ > **Note:** Since v3.1.0, `react-native-edge-to-edge` is an **optional** dependency. We strongly recommend setting `edgeToEdgeEnabled=true` in your `android/gradle.properties` — it enforces translucent system bars on modals, disables legacy StatusBar hacks, and enables additional React Native core fixes. **Expo SDK 54+** enables this automatically. You can still install `react-native-edge-to-edge` for ecosystem compatibility with libraries like `react-native-bootsplash` or `react-native-permissions`.
34
+
35
+ Then follow [installation guides](https://unistyl.es/v3/start/getting-started) for your platform.
36
+
37
+ ## [Documentation](https://unistyl.es/)
38
+ - [Start here](https://unistyl.es/v3/start/introduction)
39
+ - [Migration from Unistyles 2.0](https://unistyl.es/v3/start/migration-guide)
40
+ - [Learn how Unistyles 3.0 works](https://unistyl.es/v3/start/how-unistyles-works)
41
+ - [API](https://unistyl.es/v3/references/stylesheet)
42
+ - [Examples](https://unistyl.es/v3/examples/examples)
43
+
44
+ ## Features
45
+ - 🚀 Shared core with C++ and JSI bindings
46
+ - 🏎️ Powered by Nitro Modules
47
+ - 🦸🏼‍♂️ No re-renders
48
+ - 🦄 Custom web parser, classes and pseudo classes
49
+ - ⚛️ Tightly integrated with Fabric and Shadow Tree
50
+ - 🔥 Crazy performance, adds under 0.1 ms to your StyleSheet
51
+ - 🎳 Share up to 100% of your styles across platforms in monorepo
52
+ - 🎯 Doesn't introduce new components, your view hierarchy is always clean
53
+ - 🎨 Register multiple themes and change them with single function call
54
+ - and [much much more](https://unistyl.es/v3/start/new-features)!
55
+
56
+ ## Sponsors
57
+
58
+ <a href="https://codemask.com">
59
+ <img src="https://avatars.githubusercontent.com/u/51229884?s=200&v=4" height="70px" width="70px" alt="codemask" />
60
+ </a>
61
+ <a href="https://galaxies.dev">
62
+ <img src="https://avatars.githubusercontent.com/u/118431096?s=200&v=4" height="70px" width="70px" alt="galaxies-dev" />
63
+ </a>
64
+ <a href="https://github.com/ryanlanciaux">
65
+ <img src="https://avatars.githubusercontent.com/u/85041?v=4" height="70px" width="70px" alt="ryanlanciaux" />
66
+ </a>
67
+ <a href="https://github.com/jordmccord">
68
+ <img src="https://avatars.githubusercontent.com/u/7591840?v=4" height="70px" width="70px" alt="jordmccord" />
69
+ </a>
70
+ <a href="https://github.com/kerwanp">
71
+ <img src="https://avatars.githubusercontent.com/u/36955373?v=4" height="70px" width="70px" alt="kerwanp" />
72
+ </a>
73
+ <a href="https://github.com/andkindness">
74
+ <img src="https://avatars.githubusercontent.com/u/143941782?v=4" height="70px" width="70px" alt="andkindness" />
75
+ </a>
76
+ <a href="https://github.com/AdiRishi">
77
+ <img src="https://avatars.githubusercontent.com/u/8351234?v=4" height="70px" width="70px" alt="AdiRishi" />
78
+ </a>
79
+ <a href="https://github.com/cybercarrot">
80
+ <img src="https://avatars.githubusercontent.com/u/6837094?v=4" height="70px" width="70px" alt="cybercarrot" />
81
+ </a>
82
+
83
+
84
+ ## Past sponsors
85
+
86
+ <a href="https://github.com/kmartinezmedia">
87
+ <img src="https://avatars.githubusercontent.com/u/6308123?s=200&v=4" height="60px" width="60px" alt="kmartinezmedia" />
88
+ </a>
89
+ <a href="https://github.com/levibuzolic">
90
+ <img src="https://avatars.githubusercontent.com/u/721323?v=4" height="60px" width="60px" alt="levibuzolic" />
91
+ </a>
92
+ <a href="https://github.com/claudesortwell">
93
+ <img src="https://avatars.githubusercontent.com/u/41422239?v=4" height="60px" width="60px" alt="claudesortwell" />
94
+ </a>
95
+ <a href="https://github.com/luoxuhai">
96
+ <img src="https://avatars.githubusercontent.com/u/37284154?v=4" height="60px" width="60px" alt="luoxuhai" />
97
+ </a>
98
+ <a href="https://github.com">
99
+ <img src="https://avatars.githubusercontent.com/u/113348625?v=4" height="60px" width="60px" alt="anonymous" />
100
+ </a>
101
+ <a href="https://github.com/abanobboles">
102
+ <img src="https://avatars.githubusercontent.com/u/9078953?v=4" height="60px" width="60px" alt="abanobboles" />
103
+ </a>
104
+ <a href="https://github.com/hyoban">
105
+ <img src="https://avatars.githubusercontent.com/u/38493346?v=4" height="60px" width="60px" alt="hyoban" />
106
+ </a>
107
+ <a href="https://github.com/giovannilondero">
108
+ <img src="https://avatars.githubusercontent.com/u/10998991?v=4" height="60px" width="60px" alt="giovannilondero" />
109
+ </a>
110
+ <a href="https://github.com/4cc3ssX">
111
+ <img src="https://avatars.githubusercontent.com/u/57473799?v=4" height="60px" width="60px" alt="4cc3ssX" />
112
+ </a>
113
+ <a href="https://github.com/FilipiRafael">
114
+ <img src="https://avatars.githubusercontent.com/u/61629642?v=4" height="60px" width="60px" alt="FilipiRafael" />
115
+ </a>
116
+ <a href="https://github.com/dacoto97">
117
+ <img src="https://avatars.githubusercontent.com/u/16915053?v=4" height="60px" width="60px" alt="dacoto97" />
118
+ </a>
119
+ <a href="https://github.com/chinamcafee">
120
+ <img src="https://avatars.githubusercontent.com/u/3439961?v=4" height="60px" width="60px" alt="chinamcafee" />
121
+ </a>
122
+ <a href="https://github.com/guillaumehcht">
123
+ <img src="https://avatars.githubusercontent.com/u/80776475?v=4" height="60px" width="60px" alt="guillaumehcht" />
124
+ </a>
125
+ <a href="https://github.com/FTCHD">
126
+ <img src="https://avatars.githubusercontent.com/u/144691102?v=4" height="60px" width="60px" alt="FTCHD" />
127
+ </a>
128
+ <a href="https://github.com/avega99">
129
+ <img src="https://avatars.githubusercontent.com/u/177598670?v=4" height="60px" width="60px" alt="avega99" />
130
+ </a>
131
+ <a href="https://github.com/oscklm">
132
+ <img src="https://avatars.githubusercontent.com/u/22825865?v=4" height="60px" width="60px" alt="oscklm" />
133
+ </a>
134
+ <a href="https://github.com/loopsware">
135
+ <img src="https://avatars.githubusercontent.com/u/161434039?s=200&v=4" height="60px" width="60px" alt="loopsware" />
136
+ </a>
137
+ <a href="https://github.com/mobily">
138
+ <img src="https://avatars.githubusercontent.com/u/1467712?v=4" height="60px" width="60px" alt="mobily" />
139
+ </a>
140
+ <a href="https://github.com/mwarger">
141
+ <img src="https://avatars.githubusercontent.com/u/686823?v=4" height="60px" width="60px" alt="mwarger" />
142
+ </a>
143
+ <a href="https://github.com/happyfloat">
144
+ <img src="https://avatars.githubusercontent.com/u/186333704?s=200&v=4" height="60px" width="60px" alt="happyfloat" />
145
+ </a>
146
+ <a href="https://github.com/cargurus-oss-fund">
147
+ <img src="https://avatars.githubusercontent.com/u/108300759?v=4" height="60px" width="60px" alt="cargurus-oss-fund" />
148
+ </a>
149
+ <a href="https://github.com/rauchg">
150
+ <img src="https://avatars.githubusercontent.com/u/13041?v=4" height="60px" width="60px" alt="rauchg" />
151
+ </a>
152
+ <a href="https://github.com/oliverloops">
153
+ <img src="https://avatars.githubusercontent.com/u/33361399?v=4" height="60px" width="60px" alt="oliverloops" />
154
+ </a>
155
+ <a href="https://github.com/biw">
156
+ <img src="https://avatars.githubusercontent.com/u/6139501?v=4" height="60px" width="60px" alt="biw" />
157
+ </a>
158
+
159
+ ## Sponsor my work
160
+
161
+ [How to become a sponsor?](https://unistyl.es/v3/other/for-sponsors)
162
+
163
+ If you found the `react-native-unistyles` time-saving and valuable, please consider sponsoring my work. Your support enables me to continue creating libraries with a fresh approach.
164
+
165
+ Github: https://github.com/sponsors/jpudysz
166
+
167
+ Ko-fi: https://ko-fi.com/jpudysz
168
+
169
+ Your support is greatly appreciated and helps me dedicate more time and resources to creating quality libraries. Thank you for all the support!
170
+
171
+
172
+ ## Discord
173
+ Looking for help or you want to chat with me?
174
+
175
+ [Join Discord](https://discord.gg/akGHf27P4C)
176
+
177
+
178
+ ## License
179
+
180
+ MIT
@@ -33,11 +33,8 @@ void UnistylesModule::registerNatives() {
33
33
  jni::local_ref<BindingsInstallerHolder::javaobject> UnistylesModule::getBindingsInstaller(jni::alias_ref<UnistylesModule::javaobject> jobj) {
34
34
  auto& runtimeExecutor = jobj->cthis()->_runtimeExecutor;
35
35
  auto& nativePlatform = jobj->cthis()->_nativePlatform;
36
- auto* self = jobj->cthis();
37
-
38
- return BindingsInstallerHolder::newObjectCxxArgs([&runtimeExecutor, &nativePlatform, self](jsi::Runtime& rt) {
39
- self->_runtime = &rt;
40
36
 
37
+ return BindingsInstallerHolder::newObjectCxxArgs([&runtimeExecutor, &nativePlatform](jsi::Runtime& rt) {
41
38
  // function is called on: first init and every live reload
42
39
  // check if this is live reload, if so let's replace UnistylesRuntime with new runtime
43
40
  auto hasUnistylesRuntime = HybridObjectRegistry::hasHybridObject("UnistylesRuntime");
@@ -55,7 +52,7 @@ jni::local_ref<BindingsInstallerHolder::javaobject> UnistylesModule::getBindings
55
52
  };
56
53
 
57
54
  // init hybrids
58
- auto unistylesRuntime = std::make_shared<HybridUnistylesRuntime>(nativePlatform, rt, runOnJSThread);
55
+ auto unistylesRuntime = std::make_shared<HybridUnistylesRuntime>(nativePlatform, runOnJSThread);
59
56
  auto styleSheet = std::make_shared<HybridStyleSheet>(unistylesRuntime);
60
57
 
61
58
  HybridObjectRegistry::registerHybridObjectConstructor("UnistylesRuntime", [unistylesRuntime]() -> std::shared_ptr<HybridObject>{
@@ -29,12 +29,7 @@ struct UnistylesModule : public jni::HybridClass<UnistylesModule> {
29
29
  jni::alias_ref<JHybridNativePlatformSpec::JavaPart> nativePlatform
30
30
  );
31
31
  static void invalidateNative(jni::alias_ref<jhybridobject> jThis) {
32
- auto* self = jThis->cthis();
33
-
34
- if (self->_runtime) {
35
- core::UnistylesRegistry::get().destroyState(self->_runtime);
36
- self->_runtime = nullptr;
37
- }
32
+ core::UnistylesRegistry::get().destroy();
38
33
  }
39
34
 
40
35
  static jni::local_ref<BindingsInstallerHolder::javaobject> getBindingsInstaller(jni::alias_ref<UnistylesModule::javaobject> jThis);
@@ -42,7 +37,6 @@ struct UnistylesModule : public jni::HybridClass<UnistylesModule> {
42
37
  private:
43
38
  RuntimeExecutor _runtimeExecutor;
44
39
  std::shared_ptr<HybridNativePlatformSpec> _nativePlatform;
45
- jsi::Runtime* _runtime = nullptr;
46
40
  };
47
41
 
48
42
  }
@@ -54,7 +54,11 @@ fun NativePlatformAndroid.diffMiniRuntimes(lhs: UnistylesNativeMiniRuntime, rhs:
54
54
  dependencies.add(UnistyleDependency.NAVIGATIONBAR)
55
55
  }
56
56
 
57
- // rtl and pixel ratio are not dynamic
57
+ if (lhs.rtl != rhs.rtl) {
58
+ dependencies.add(UnistyleDependency.RTL)
59
+ }
60
+
61
+ // pixel ratio is not dynamic
58
62
 
59
63
  return dependencies.toTypedArray()
60
64
  }
@@ -37,6 +37,8 @@ class NativePlatformAndroid(private val reactContext: ReactApplicationContext):
37
37
  }
38
38
 
39
39
  fun onDestroy() {
40
+ _listener.onDestroy()
41
+ _insets.onDestroy()
40
42
  reactContext.removeLifecycleEventListener(this)
41
43
  }
42
44
 
@@ -155,11 +157,14 @@ class NativePlatformAndroid(private val reactContext: ReactApplicationContext):
155
157
  "com.facebook.react.modules.i18nmanager.I18nUtil",
156
158
  Context.MODE_PRIVATE
157
159
  )
160
+ val resourcesLocale = reactContext.resources.configuration.locales[0]
158
161
  val hasForcedRtl = sharedPrefs.getBoolean("RCTI18nUtil_forceRTL", false)
159
162
  // user preferences
160
163
  val isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
164
+ val isResourcesRtl = TextUtilsCompat.getLayoutDirectionFromLocale(resourcesLocale) == ViewCompat.LAYOUT_DIRECTION_RTL
161
165
 
162
- return hasForcedRtl || isRtl
166
+
167
+ return hasForcedRtl || isRtl || isResourcesRtl
163
168
  }
164
169
 
165
170
  override fun setRootViewBackgroundColor(color: Double) {
@@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
4
4
  import android.content.Context
5
5
  import android.content.Intent
6
6
  import android.content.IntentFilter
7
+ import android.content.SharedPreferences
7
8
  import android.os.Handler
8
9
  import android.os.Looper
9
10
  import androidx.annotation.Keep
@@ -23,21 +24,38 @@ class NativePlatformListener(
23
24
  ) {
24
25
  private val _dependencyListeners: MutableList<CxxDependencyListener> = mutableListOf()
25
26
 
27
+ private fun notifyConfigChangedWithDelay() {
28
+ Handler(Looper.getMainLooper()).postDelayed({
29
+ this@NativePlatformListener.onConfigChange()
30
+ }, 25)
31
+ }
32
+
26
33
  private val configurationChangeReceiver = object : BroadcastReceiver() {
27
34
  override fun onReceive(context: Context, intent: Intent) {
28
- Handler(Looper.getMainLooper()).postDelayed({
29
- this@NativePlatformListener.onConfigChange()
30
- }, 25)
35
+ notifyConfigChangedWithDelay()
36
+ }
37
+ }
38
+
39
+ private val rtlPreferenceListener = SharedPreferences.OnSharedPreferenceChangeListener { prefs, key ->
40
+ if (key == "RCTI18nUtil_forceRTL") {
41
+ notifyConfigChangedWithDelay()
31
42
  }
32
43
  }
33
44
 
45
+ private val i18nUtilSharedPrefs = reactContext.getSharedPreferences(
46
+ "com.facebook.react.modules.i18nmanager.I18nUtil",
47
+ Context.MODE_PRIVATE
48
+ )
49
+
34
50
  init {
35
51
  reactContext.registerReceiver(configurationChangeReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED))
52
+ i18nUtilSharedPrefs.registerOnSharedPreferenceChangeListener(rtlPreferenceListener)
36
53
  }
37
54
 
38
55
  fun onDestroy() {
39
56
  this.removePlatformListeners()
40
57
  reactContext.unregisterReceiver(configurationChangeReceiver)
58
+ i18nUtilSharedPrefs.unregisterOnSharedPreferenceChangeListener(rtlPreferenceListener)
41
59
  }
42
60
 
43
61
  fun addPlatformListener(listener: CxxDependencyListener) {
@@ -57,7 +57,7 @@ inline static std::vector<Unistyle::Shared> unistylesFromHashKeys(jsi::Runtime&
57
57
  auto& registry = UnistylesRegistry::get();
58
58
 
59
59
  for (auto& key: keys) {
60
- unistyles.emplace_back(registry.getUnistyleById(rt, key));
60
+ unistyles.emplace_back(registry.getUnistyleById(key));
61
61
  }
62
62
 
63
63
  return unistyles;
@@ -157,7 +157,7 @@ inline static jsi::Value objectFromUnistyle(jsi::Runtime& rt, std::shared_ptr<Hy
157
157
  [unistyleID = unistyle->unid, unistylesRuntime, variants, parsedArguments](jsi::Runtime &rt, const jsi::Value &thisValue, const jsi::Value *args, size_t count
158
158
  ) {
159
159
  auto& registry = UnistylesRegistry::get();
160
- auto unistyle = registry.getUnistyleById(rt, unistyleID);
160
+ auto unistyle = registry.getUnistyleById(unistyleID);
161
161
 
162
162
  parser::Parser(unistylesRuntime).rebuildUnistyle(rt, unistyle, variants, parsedArguments);
163
163
 
@@ -9,50 +9,44 @@ using namespace facebook::react;
9
9
  std::atomic<int> core::UnistylesRegistry::_nextStyleSheetTag{0};
10
10
 
11
11
  void core::UnistylesRegistry::registerTheme(jsi::Runtime& rt, std::string name, jsi::Value& theme) {
12
- auto& state = this->getState(rt);
12
+ auto& state = this->getState();
13
13
 
14
14
  state._jsThemes.emplace(name, std::move(theme));
15
15
  state._registeredThemeNames.push_back(name);
16
16
  }
17
17
 
18
- void core::UnistylesRegistry::registerBreakpoints(jsi::Runtime& rt, std::vector<std::pair<std::string, double>>& sortedBreakpoints) {
19
- auto& state = this->getState(rt);
18
+ void core::UnistylesRegistry::registerBreakpoints(std::vector<std::pair<std::string, double>>& sortedBreakpoints) {
19
+ auto& state = this->getState();
20
20
 
21
21
  state._sortedBreakpointPairs = std::move(sortedBreakpoints);
22
22
  }
23
23
 
24
- void core::UnistylesRegistry::setPrefersAdaptiveThemes(jsi::Runtime& rt, bool prefersAdaptiveThemes) {
25
- auto& state = this->getState(rt);
24
+ void core::UnistylesRegistry::setPrefersAdaptiveThemes(bool prefersAdaptiveThemes) {
25
+ auto& state = this->getState();
26
26
 
27
27
  state._prefersAdaptiveThemes = prefersAdaptiveThemes;
28
28
  }
29
29
 
30
- void core::UnistylesRegistry::setInitialThemeName(jsi::Runtime& rt, std::string themeName) {
31
- auto& state = this->getState(rt);
30
+ void core::UnistylesRegistry::setInitialThemeName(std::string themeName) {
31
+ auto& state = this->getState();
32
32
 
33
33
  state._initialThemeName = themeName;
34
34
  }
35
35
 
36
- core::UnistylesState& core::UnistylesRegistry::getState(jsi::Runtime& rt) {
37
- auto it = this->_states.find(&rt);
38
-
39
- helpers::assertThat(rt, it != this->_states.end(), "Unistyles was loaded, but it's not configured. Did you forget to call StyleSheet.configure? If you don't want to use any themes or breakpoints, simply call it with an empty object {}.");
36
+ core::UnistylesState& core::UnistylesRegistry::getState() {
37
+ if (!this->_state) {
38
+ throw std::runtime_error("Unistyles was loaded, but it's not configured. Did you forget to call StyleSheet.configure? If you don't want to use any themes or breakpoints, simply call it with an empty object {}.");
39
+ }
40
40
 
41
- return it->second;
41
+ return *this->_state;
42
42
  }
43
43
 
44
- void core::UnistylesRegistry::createState(jsi::Runtime& rt) {
45
- auto it = this->_states.find(&rt);
46
-
47
- this->_states.emplace(
48
- std::piecewise_construct,
49
- std::forward_as_tuple(&rt),
50
- std::forward_as_tuple(rt)
51
- );
44
+ void core::UnistylesRegistry::createState() {
45
+ this->_state = std::make_unique<UnistylesState>();
52
46
  }
53
47
 
54
48
  void core::UnistylesRegistry::updateTheme(jsi::Runtime& rt, std::string& themeName, jsi::Function&& callback) {
55
- auto& state = this->getState(rt);
49
+ auto& state = this->getState();
56
50
  auto it = state._jsThemes.find(themeName);
57
51
 
58
52
  helpers::assertThat(rt, it != state._jsThemes.end(), "Unistyles: You're trying to update theme '" + themeName + "' but it wasn't registered.");
@@ -70,22 +64,36 @@ void core::UnistylesRegistry::linkShadowNodeWithUnistyle(
70
64
  std::vector<std::shared_ptr<UnistyleData>>& unistylesData
71
65
  ) {
72
66
  this->trafficController.withLock([this, &rt, &unistylesData, shadowNodeFamily](){
67
+ // Clear suspension state if this family was previously suspended
68
+ if (_suspendedFamilies.erase(shadowNodeFamily) > 0) {
69
+ auto* mutableFamily = const_cast<ShadowNodeFamily*>(shadowNodeFamily);
70
+ mutableFamily->nativeProps_DEPRECATED.reset();
71
+ }
72
+
73
73
  shadow::ShadowLeafUpdates updates;
74
74
  auto parser = parser::Parser(nullptr);
75
75
 
76
- std::for_each(unistylesData.begin(), unistylesData.end(), [this, &rt, shadowNodeFamily](std::shared_ptr<UnistyleData> unistyleData){
77
- this->_shadowRegistry[&rt][shadowNodeFamily].emplace_back(unistyleData);
76
+ std::for_each(unistylesData.begin(), unistylesData.end(), [this, shadowNodeFamily](std::shared_ptr<UnistyleData> unistyleData){
77
+ this->_shadowRegistry[shadowNodeFamily].emplace_back(unistyleData);
78
78
  });
79
79
 
80
80
  updates[shadowNodeFamily] = parser.parseStylesToShadowTreeStyles(rt, unistylesData);
81
81
 
82
+ auto* mutableFamily = const_cast<ShadowNodeFamily*>(shadowNodeFamily);
83
+
84
+ if (mutableFamily->nativeProps_DEPRECATED) {
85
+ mutableFamily->nativeProps_DEPRECATED->update(updates[shadowNodeFamily]);
86
+ } else {
87
+ mutableFamily->nativeProps_DEPRECATED = std::make_unique<folly::dynamic>(updates[shadowNodeFamily]);
88
+ }
89
+
82
90
  this->trafficController.setUpdates(updates);
83
91
  this->trafficController.resumeUnistylesTraffic();
84
92
  });
85
93
  }
86
94
 
87
- void core::UnistylesRegistry::removeDuplicatedUnistyles(jsi::Runtime& rt, const ShadowNodeFamily *shadowNodeFamily, std::vector<core::Unistyle::Shared>& unistyles) {
88
- auto targetFamilyUnistyles = this->_shadowRegistry[&rt][shadowNodeFamily];
95
+ void core::UnistylesRegistry::removeDuplicatedUnistyles(const ShadowNodeFamily *shadowNodeFamily, std::vector<core::Unistyle::Shared>& unistyles) {
96
+ auto targetFamilyUnistyles = this->_shadowRegistry[shadowNodeFamily];
89
97
 
90
98
  unistyles.erase(
91
99
  std::remove_if(
@@ -105,32 +113,41 @@ void core::UnistylesRegistry::removeDuplicatedUnistyles(jsi::Runtime& rt, const
105
113
  );
106
114
  }
107
115
 
108
- void core::UnistylesRegistry::unlinkShadowNodeWithUnistyles(jsi::Runtime& rt, const ShadowNodeFamily* shadowNodeFamily) {
109
- this->trafficController.withLock([this, &rt, shadowNodeFamily](){
110
- this->_shadowRegistry[&rt].erase(shadowNodeFamily);
116
+ void core::UnistylesRegistry::unlinkShadowNodeWithUnistyles(const ShadowNodeFamily* shadowNodeFamily) {
117
+ this->trafficController.withLock([this, shadowNodeFamily](){
118
+ this->_shadowRegistry.erase(shadowNodeFamily);
119
+ this->_suspendedFamilies.erase(shadowNodeFamily);
111
120
  this->trafficController.removeShadowNode(shadowNodeFamily);
121
+ });
122
+ }
112
123
 
113
- if (this->_shadowRegistry[&rt].empty()) {
114
- this->_shadowRegistry.erase(&rt);
124
+ void core::UnistylesRegistry::suspendShadowNode(const ShadowNodeFamily* shadowNodeFamily) {
125
+ this->trafficController.withLock([this, shadowNodeFamily](){
126
+ if (this->_shadowRegistry.contains(shadowNodeFamily)) {
127
+ this->_suspendedFamilies.insert(shadowNodeFamily);
115
128
  }
116
129
  });
117
130
  }
118
131
 
132
+ bool core::UnistylesRegistry::isSuspended(const ShadowNodeFamily* family) const noexcept {
133
+ return _suspendedFamilies.count(family) > 0;
134
+ }
135
+
119
136
  std::shared_ptr<core::StyleSheet> core::UnistylesRegistry::addStyleSheet(jsi::Runtime& rt, core::StyleSheetType type, jsi::Object&& rawValue) {
120
137
  int tag = _nextStyleSheetTag.fetch_add(1);
121
138
 
122
139
  auto sheet = std::make_shared<core::StyleSheet>(tag, type, std::move(rawValue));
123
- this->_styleSheetRegistry[&rt][tag] = sheet;
140
+ this->_styleSheetRegistry[tag] = sheet;
124
141
 
125
142
  return sheet;
126
143
  }
127
144
 
128
- core::DependencyMap core::UnistylesRegistry::buildDependencyMap(jsi::Runtime& rt, std::vector<UnistyleDependency>& deps) {
145
+ core::DependencyMap core::UnistylesRegistry::buildDependencyMap(std::vector<UnistyleDependency>& deps) {
129
146
  core::DependencyMap dependencyMap;
130
147
 
131
148
  std::unordered_set<UnistyleDependency> uniqueDependencies(deps.begin(), deps.end());
132
149
 
133
- for (const auto& [family, unistyles] : this->_shadowRegistry[&rt]) {
150
+ for (const auto& [family, unistyles] : this->_shadowRegistry) {
134
151
  bool hasAnyOfDependencies = false;
135
152
 
136
153
  // Check if any dependency matches
@@ -171,7 +188,7 @@ void core::UnistylesRegistry::shadowLeafUpdateFromUnistyle(jsi::Runtime& rt, Uni
171
188
  ? std::make_optional(maybePressableId.asString(rt).utf8(rt))
172
189
  : std::nullopt;
173
190
 
174
- for (const auto& [family, unistyles] : this->_shadowRegistry[&rt]) {
191
+ for (const auto& [family, unistyles] : this->_shadowRegistry) {
175
192
  for (const auto& unistyleData : unistyles) {
176
193
  if (unistyleData->unistyle == unistyle) {
177
194
  updates[family] = parser.parseStylesToShadowTreeStyles(rt, { unistyleData });
@@ -183,7 +200,7 @@ void core::UnistylesRegistry::shadowLeafUpdateFromUnistyle(jsi::Runtime& rt, Uni
183
200
  });
184
201
  }
185
202
 
186
- std::vector<std::shared_ptr<core::StyleSheet>>core::UnistylesRegistry::getStyleSheetsToRefresh(jsi::Runtime& rt, std::vector<UnistyleDependency>& unistylesDependencies) {
203
+ std::vector<std::shared_ptr<core::StyleSheet>>core::UnistylesRegistry::getStyleSheetsToRefresh(std::vector<UnistyleDependency>& unistylesDependencies) {
187
204
  std::vector<std::shared_ptr<core::StyleSheet>> stylesheetsToRefresh;
188
205
  std::unordered_set<UnistyleDependency> depSet(
189
206
  unistylesDependencies.begin(),
@@ -197,8 +214,6 @@ std::vector<std::shared_ptr<core::StyleSheet>>core::UnistylesRegistry::getStyleS
197
214
  return stylesheetsToRefresh;
198
215
  }
199
216
 
200
- auto& styleSheets = this->_styleSheetRegistry[&rt];
201
-
202
217
  auto hasMatchingDependency = [&depSet](const auto& unistyles) {
203
218
  for (const auto& [_, unistyle] : unistyles) {
204
219
  for (const auto& dep : unistyle->dependencies) {
@@ -211,7 +226,7 @@ std::vector<std::shared_ptr<core::StyleSheet>>core::UnistylesRegistry::getStyleS
211
226
  return false;
212
227
  };
213
228
 
214
- for (const auto& [_, styleSheet] : styleSheets) {
229
+ for (const auto& [_, styleSheet] : this->_styleSheetRegistry) {
215
230
  if (styleSheet->type == StyleSheetType::ThemableWithMiniRuntime || styleSheet->type == StyleSheetType::Static) {
216
231
  if (hasMatchingDependency(styleSheet->unistyles)) {
217
232
  stylesheetsToRefresh.emplace_back(styleSheet);
@@ -226,8 +241,8 @@ std::vector<std::shared_ptr<core::StyleSheet>>core::UnistylesRegistry::getStyleS
226
241
  return stylesheetsToRefresh;
227
242
  }
228
243
 
229
- core::Unistyle::Shared core::UnistylesRegistry::getUnistyleById(jsi::Runtime& rt, std::string unistyleID) {
230
- for (auto& pair: this->_styleSheetRegistry[&rt]) {
244
+ core::Unistyle::Shared core::UnistylesRegistry::getUnistyleById(std::string unistyleID) {
245
+ for (auto& pair: this->_styleSheetRegistry) {
231
246
  auto [_, stylesheet] = pair;
232
247
 
233
248
  for (auto unistylePair: stylesheet->unistyles) {
@@ -251,16 +266,10 @@ void core::UnistylesRegistry::setScopedTheme(std::optional<std::string> themeNam
251
266
  }
252
267
 
253
268
  void core::UnistylesRegistry::destroy() {
254
- this->_states.clear();
269
+ this->_state.reset();
255
270
  this->_styleSheetRegistry.clear();
256
271
  this->_shadowRegistry.clear();
272
+ this->_suspendedFamilies.clear();
257
273
  this->_scopedTheme = std::nullopt;
258
274
  _nextStyleSheetTag.store(0);
259
275
  }
260
-
261
- void core::UnistylesRegistry::destroyState(jsi::Runtime* rt) {
262
- this->_states.erase(rt);
263
- this->_styleSheetRegistry.erase(rt);
264
- this->_shadowRegistry.erase(rt);
265
- this->_scopedTheme = std::nullopt;
266
- }
@@ -32,35 +32,37 @@ struct UnistylesRegistry: public StyleSheetRegistry {
32
32
  bool shouldUsePointsForBreakpoints = false;
33
33
 
34
34
  void registerTheme(jsi::Runtime& rt, std::string name, jsi::Value& theme);
35
- void registerBreakpoints(jsi::Runtime& rt, std::vector<std::pair<std::string, double>>& sortedBreakpoints);
36
- void setPrefersAdaptiveThemes(jsi::Runtime& rt, bool prefersAdaptiveThemes);
37
- void setInitialThemeName(jsi::Runtime& rt, std::string themeName);
35
+ void registerBreakpoints(std::vector<std::pair<std::string, double>>& sortedBreakpoints);
36
+ void setPrefersAdaptiveThemes(bool prefersAdaptiveThemes);
37
+ void setInitialThemeName(std::string themeName);
38
38
  void updateTheme(jsi::Runtime& rt, std::string& themeName, jsi::Function&& callback);
39
39
 
40
- UnistylesState& getState(jsi::Runtime& rt);
41
- void createState(jsi::Runtime& rt);
42
- std::vector<std::shared_ptr<core::StyleSheet>> getStyleSheetsToRefresh(jsi::Runtime& rt, std::vector<UnistyleDependency>& unistylesDependencies);
40
+ UnistylesState& getState();
41
+ void createState();
42
+ std::vector<std::shared_ptr<core::StyleSheet>> getStyleSheetsToRefresh(std::vector<UnistyleDependency>& unistylesDependencies);
43
43
  void linkShadowNodeWithUnistyle(jsi::Runtime& rt, const ShadowNodeFamily*, std::vector<std::shared_ptr<UnistyleData>>& unistylesData);
44
- void unlinkShadowNodeWithUnistyles(jsi::Runtime& rt, const ShadowNodeFamily*);
44
+ void unlinkShadowNodeWithUnistyles(const ShadowNodeFamily*);
45
+ void suspendShadowNode(const ShadowNodeFamily*);
46
+ bool isSuspended(const ShadowNodeFamily*) const noexcept;
45
47
  std::shared_ptr<core::StyleSheet> addStyleSheet(jsi::Runtime& rt, core::StyleSheetType type, jsi::Object&& rawValue);
46
- DependencyMap buildDependencyMap(jsi::Runtime& rt, std::vector<UnistyleDependency>& deps);
48
+ DependencyMap buildDependencyMap(std::vector<UnistyleDependency>& deps);
47
49
  void shadowLeafUpdateFromUnistyle(jsi::Runtime& rt, Unistyle::Shared unistyle, jsi::Value& maybePressableId);
48
50
  shadow::ShadowTrafficController trafficController{};
49
51
  const std::optional<std::string> getScopedTheme();
50
- void removeDuplicatedUnistyles(jsi::Runtime& rt, const ShadowNodeFamily* shadowNodeFamily, std::vector<core::Unistyle::Shared>& unistyles);
52
+ void removeDuplicatedUnistyles(const ShadowNodeFamily* shadowNodeFamily, std::vector<core::Unistyle::Shared>& unistyles);
51
53
  void setScopedTheme(std::optional<std::string> themeName);
52
- core::Unistyle::Shared getUnistyleById(jsi::Runtime& rt, std::string unistyleID);
54
+ core::Unistyle::Shared getUnistyleById(std::string unistyleID);
53
55
  void destroy();
54
- void destroyState(jsi::Runtime* rt);
55
56
 
56
57
  private:
57
58
  UnistylesRegistry() = default;
58
59
 
59
60
  static std::atomic<int> _nextStyleSheetTag;
60
61
  std::optional<std::string> _scopedTheme{};
61
- std::unordered_map<jsi::Runtime*, UnistylesState> _states{};
62
- std::unordered_map<jsi::Runtime*, std::unordered_map<int, std::shared_ptr<core::StyleSheet>>> _styleSheetRegistry{};
63
- std::unordered_map<jsi::Runtime*, std::unordered_map<const ShadowNodeFamily*, std::vector<std::shared_ptr<UnistyleData>>>> _shadowRegistry{};
62
+ std::unique_ptr<UnistylesState> _state{};
63
+ std::unordered_map<int, std::shared_ptr<core::StyleSheet>> _styleSheetRegistry{};
64
+ std::unordered_map<const ShadowNodeFamily*, std::vector<std::shared_ptr<UnistyleData>>> _shadowRegistry{};
65
+ std::unordered_set<const ShadowNodeFamily*> _suspendedFamilies{};
64
66
  };
65
67
 
66
68
  inline UnistylesRegistry& UnistylesRegistry::get() {