react-native-unistyles 2.8.0-beta.1 → 2.8.0-beta.3

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 (33) hide show
  1. package/android/CMakeLists.txt +8 -1
  2. package/android/build.gradle +4 -1
  3. package/android/src/main/cxx/cpp-adapter.cpp +10 -100
  4. package/android/src/main/cxx/helpers.h +2 -0
  5. package/android/src/main/cxx/platform.cpp +126 -0
  6. package/android/src/main/cxx/platform.h +15 -0
  7. package/android/src/main/java/com/unistyles/Models.kt +14 -35
  8. package/android/src/main/java/com/unistyles/Platform.kt +91 -10
  9. package/android/src/main/java/com/unistyles/UnistylesModule.kt +84 -139
  10. package/cxx/Macros.h +11 -0
  11. package/cxx/UnistylesImpl.cpp +241 -0
  12. package/cxx/UnistylesModel.cpp +234 -0
  13. package/cxx/UnistylesModel.h +112 -0
  14. package/cxx/UnistylesRuntime.cpp +17 -388
  15. package/cxx/UnistylesRuntime.h +56 -95
  16. package/ios/UnistylesModule.h +8 -0
  17. package/ios/UnistylesModule.mm +12 -89
  18. package/ios/platform/Platform_Shared.h +5 -0
  19. package/ios/platform/Platform_Shared.mm +69 -0
  20. package/ios/platform/Platform_iOS.h +2 -9
  21. package/ios/platform/Platform_iOS.mm +47 -94
  22. package/ios/platform/Platform_macOS.h +1 -6
  23. package/ios/platform/Platform_macOS.mm +29 -29
  24. package/ios/platform/Platform_tvOS.h +2 -9
  25. package/ios/platform/Platform_tvOS.mm +30 -92
  26. package/ios/platform/Platform_visionOS.h +2 -8
  27. package/ios/platform/Platform_visionOS.mm +28 -83
  28. package/package.json +1 -1
  29. package/react-native-unistyles.podspec +3 -0
  30. package/android/src/main/java/com/unistyles/Config.kt +0 -116
  31. package/android/src/main/java/com/unistyles/Insets.kt +0 -141
  32. package/ios/UnistylesHelpers.h +0 -3
  33. package/ios/UnistylesHelpers.mm +0 -5
@@ -0,0 +1,234 @@
1
+ #include "UnistylesModel.h"
2
+
3
+ std::string UnistylesModel::getBreakpointFromScreenWidth(int width, const std::vector<std::pair<std::string, double>>& sortedBreakpointPairs) {
4
+ for (size_t i = 0; i < sortedBreakpointPairs.size(); ++i) {
5
+ const auto& [key, value] = sortedBreakpointPairs[i];
6
+ const double maxVal = (i + 1 < sortedBreakpointPairs.size()) ? sortedBreakpointPairs[i + 1].second : std::numeric_limits<double>::infinity();
7
+
8
+ if (width >= value && width < maxVal) {
9
+ return key;
10
+ }
11
+ }
12
+
13
+ return sortedBreakpointPairs.empty() ? "" : sortedBreakpointPairs.back().first;
14
+ }
15
+
16
+ void UnistylesModel::handleScreenSizeChange(Dimensions& screen, std::optional<Insets> insets, std::optional<Dimensions> statusBar, std::optional<Dimensions> navigationBar) {
17
+ std::string breakpoint = this->getBreakpointFromScreenWidth(screen.width, this->sortedBreakpointPairs);
18
+ bool hasDifferentBreakpoint = this->breakpoint != breakpoint;
19
+ bool hasDifferentScreenDimensions = this->screen.width != screen.width || this->screen.height != screen.height;
20
+ bool hasDifferentInsets = insets.has_value()
21
+ ? this->insets.top != insets->top || this->insets.bottom != insets->bottom || this->insets.left != insets->left || this->insets.right != insets->right
22
+ : false;
23
+
24
+ // we don't need to check statusBar/navigationBar as they will only change on orientation change witch is equal to hasDifferentScreenDimensions
25
+ bool shouldNotify = hasDifferentBreakpoint || hasDifferentScreenDimensions || hasDifferentInsets;
26
+
27
+ this->breakpoint = breakpoint;
28
+ this->screen = {screen.width, screen.height};
29
+
30
+ if (insets.has_value()) {
31
+ this->insets = {insets->top, insets->bottom, insets->left, insets->right};
32
+ }
33
+
34
+ if (statusBar.has_value()) {
35
+ this->statusBar = {statusBar->width, statusBar->height};
36
+ }
37
+
38
+ if (navigationBar.has_value()) {
39
+ this->navigationBar = {navigationBar->width, navigationBar->height};
40
+ }
41
+
42
+ if (shouldNotify) {
43
+ this->onLayoutChange();
44
+ }
45
+ }
46
+
47
+ void UnistylesModel::handleAppearanceChange(std::string colorScheme) {
48
+ this->colorScheme = colorScheme;
49
+
50
+ if (!this->supportsAutomaticColorScheme || !this->hasAdaptiveThemes) {
51
+ return;
52
+ }
53
+
54
+ if (this->themeName != this->colorScheme) {
55
+ this->onThemeChange(this->colorScheme);
56
+ this->themeName = this->colorScheme;
57
+ }
58
+ }
59
+
60
+ void UnistylesModel::handleContentSizeCategoryChange(std::string contentSizeCategory) {
61
+ if (this->contentSizeCategory == contentSizeCategory) {
62
+ return;
63
+ }
64
+
65
+ this->contentSizeCategory = contentSizeCategory;
66
+ this->onContentSizeCategoryChange(contentSizeCategory);
67
+ }
68
+
69
+ jsi::Value UnistylesModel::getThemeOrFail(jsi::Runtime& runtime) {
70
+ if (this->themes.size() == 1) {
71
+ std::string themeName = this->themes.at(0);
72
+
73
+ this->themeName = themeName;
74
+
75
+ return jsi::String::createFromUtf8(runtime, themeName);
76
+ }
77
+
78
+ return jsi::Value().undefined();
79
+ }
80
+
81
+ std::vector<std::pair<std::string, double>> UnistylesModel::toSortedBreakpointPairs(jsi::Runtime& rt, jsi::Object& breakpointsObj) {
82
+ jsi::Array propertyNames = breakpointsObj.getPropertyNames(rt);
83
+ std::vector<std::pair<std::string, double>> sortedBreakpointEntriesVec;
84
+
85
+ for (size_t i = 0; i < propertyNames.size(rt); ++i) {
86
+ jsi::Value propNameValue = propertyNames.getValueAtIndex(rt, i);
87
+ std::string name = propNameValue.asString(rt).utf8(rt);
88
+ jsi::PropNameID propNameID = jsi::PropNameID::forUtf8(rt, name);
89
+ jsi::Value value = breakpointsObj.getProperty(rt, propNameID);
90
+
91
+ if (value.isNumber()) {
92
+ double breakpointValue = value.asNumber();
93
+
94
+ sortedBreakpointEntriesVec.push_back(std::make_pair(name, breakpointValue));
95
+ }
96
+ }
97
+
98
+ std::sort(sortedBreakpointEntriesVec.begin(), sortedBreakpointEntriesVec.end(), [](const std::pair<std::string, double>& a, const std::pair<std::string, double>& b) {
99
+ return a.second < b.second;
100
+ });
101
+
102
+ return sortedBreakpointEntriesVec;
103
+ }
104
+
105
+ // a little bit hacky, but works like Turbo Module emitDeviceEvent
106
+ // it will be super easy to refactor for Unistyles 3.0
107
+ // ref: https://github.com/facebook/react-native/pull/43375
108
+ // ref: https://github.com/facebook/react-native/blob/b5fd041917d197f256433a41a126f0dff767c429/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp#L42
109
+ void UnistylesModel::emitDeviceEvent(const std::string eventType, EventPayload payload) {
110
+ this->callInvoker->invokeAsync([eventType, payload, this](){
111
+ jsi::Value emitter = this->runtime.global().getProperty(this->runtime, "__rctDeviceEventEmitter");
112
+
113
+ if (emitter.isUndefined()) {
114
+ return;
115
+ }
116
+
117
+ jsi::Object emitterObject = emitter.asObject(runtime);
118
+ jsi::Function emitFunction = emitterObject.getPropertyAsFunction(runtime, "emit");
119
+
120
+ std::vector<jsi::Value> arguments;
121
+ jsi::Object event = jsi::Object(this->runtime);
122
+
123
+ event.setProperty(this->runtime, "type", jsi::String::createFromUtf8(this->runtime, eventType));
124
+
125
+ jsi::Object eventPayload = this->parseEventPayload(payload);
126
+
127
+ event.setProperty(this->runtime, "payload", eventPayload);
128
+
129
+ arguments.emplace_back(jsi::String::createFromAscii(runtime, "__unistylesOnChange"));
130
+ arguments.emplace_back(std::move(event));
131
+
132
+ emitFunction.callWithThis(runtime, emitterObject, (const jsi::Value*)arguments.data(), arguments.size());
133
+ });
134
+ }
135
+
136
+ void UnistylesModel::onThemeChange(std::string themeName) {
137
+ EventPayload payload;
138
+ payload["themeName"] = themeName;
139
+
140
+ this->emitDeviceEvent("theme", payload);
141
+ }
142
+
143
+ void UnistylesModel::onContentSizeCategoryChange(std::string contentSizeCategory) {
144
+ EventPayload payload;
145
+ payload["contentSizeCategory"] = contentSizeCategory;
146
+
147
+ this->emitDeviceEvent("dynamicTypeSize", payload);
148
+ }
149
+
150
+ void UnistylesModel::onPluginChange() {
151
+ this->emitDeviceEvent("plugin", {});
152
+ }
153
+
154
+ void UnistylesModel::onLayoutChange() {
155
+ EventPayload payload;
156
+ std::string orientation = screen.width > screen.height
157
+ ? UnistylesOrientationLandscape
158
+ : UnistylesOrientationPortrait;
159
+
160
+ payload["breakpoint"] = this->breakpoint;
161
+ payload["orientation"] = orientation;
162
+
163
+ EventNestedValue screenPayload;
164
+ auto screen = this->screen;
165
+
166
+ screenPayload["width"] = screen.width;
167
+ screenPayload["height"] = screen.height;
168
+
169
+ payload["screen"] = screenPayload;
170
+
171
+ EventNestedValue statusBarPayload;
172
+ auto statusBar = this->statusBar;
173
+
174
+ statusBarPayload["width"] = statusBar.width;
175
+ statusBarPayload["height"] = statusBar.height;
176
+
177
+ payload["statusBar"] = statusBarPayload;
178
+
179
+ EventNestedValue navigationBarPayload;
180
+ auto navigationBar = this->navigationBar;
181
+
182
+ navigationBarPayload["width"] = navigationBar.width;
183
+ navigationBarPayload["height"] = navigationBar.height;
184
+
185
+ payload["navigationBar"] = navigationBarPayload;
186
+
187
+ EventNestedValue insetsPayload;
188
+ auto insets = this->insets;
189
+
190
+ insetsPayload["top"] = insets.top;
191
+ insetsPayload["bottom"] = insets.bottom;
192
+ insetsPayload["left"] = insets.left;
193
+ insetsPayload["right"] = insets.right;
194
+
195
+ payload["insets"] = insetsPayload;
196
+
197
+ this->emitDeviceEvent("layout", payload);
198
+ }
199
+
200
+ jsi::Object UnistylesModel::parseEventPayload(EventPayload payload) {
201
+ jsi::Object eventPayload = jsi::Object(this->runtime);
202
+
203
+ for (const auto& [key, value] : payload) {
204
+ if (std::holds_alternative<std::string>(value)) {
205
+ eventPayload.setProperty(this->runtime, key.c_str(), jsi::String::createFromUtf8(this->runtime, std::get<std::string>(value)));
206
+ }
207
+
208
+ if (std::holds_alternative<int>(value)) {
209
+ eventPayload.setProperty(this->runtime, key.c_str(), std::get<int>(value));
210
+ }
211
+
212
+ if (std::holds_alternative<EventNestedValue>(value)) {
213
+ eventPayload.setProperty(this->runtime, key.c_str(), this->parseEventNestedPayload(std::get<EventNestedValue>(value)));
214
+ }
215
+ }
216
+
217
+ return eventPayload;
218
+ }
219
+
220
+ jsi::Object UnistylesModel::parseEventNestedPayload(EventNestedValue payload) {
221
+ jsi::Object eventPayload = jsi::Object(this->runtime);
222
+
223
+ for (const auto& [key, value] : payload) {
224
+ if (std::holds_alternative<std::string>(value)) {
225
+ eventPayload.setProperty(this->runtime, key.c_str(), jsi::String::createFromUtf8(this->runtime, std::get<std::string>(value)));
226
+ }
227
+
228
+ if (std::holds_alternative<int>(value)) {
229
+ eventPayload.setProperty(this->runtime, key.c_str(), std::get<int>(value));
230
+ }
231
+ }
232
+
233
+ return eventPayload;
234
+ }
@@ -0,0 +1,112 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <ReactCommon/CallInvoker.h>
5
+ #include <vector>
6
+ #include <map>
7
+ #include <optional>
8
+ #include <variant>
9
+
10
+ using namespace facebook;
11
+
12
+ const std::string UnistylesOrientationPortrait = "portrait";
13
+ const std::string UnistylesOrientationLandscape = "landscape";
14
+
15
+ const std::string UnistylesDarkScheme = "dark";
16
+ const std::string UnistylesLightScheme = "light";
17
+ const std::string UnistylesUnspecifiedScheme = "unspecified";
18
+
19
+ const std::string UnistylesErrorBreakpointsCannotBeEmpty = "You are trying to register empty breakpoints object";
20
+ const std::string UnistylesErrorBreakpointsMustStartFromZero = "You are trying to register breakpoints that don't start from 0";
21
+ const std::string UnistylesErrorThemesCannotBeEmpty = "You are trying to register empty themes object";
22
+ const std::string UnistylesErrorAdaptiveThemesNotSupported = "Your platform doesn't support adaptive themes";
23
+
24
+ struct Dimensions {
25
+ int width;
26
+ int height;
27
+ };
28
+
29
+ struct Insets {
30
+ int top;
31
+ int bottom;
32
+ int left;
33
+ int right;
34
+ };
35
+
36
+ using EventNestedValue = std::map<std::string, std::variant<std::string, int>>;
37
+ using EventValue = std::variant<std::string, int>;
38
+ using EventPayload = std::map<std::string, std::variant<std::string, int, EventNestedValue>>;
39
+
40
+ struct UnistylesModel {
41
+ void emitDeviceEvent(const std::string eventType, EventPayload payload);
42
+ void onThemeChange(std::string themeName);
43
+ void onPluginChange();
44
+ void onContentSizeCategoryChange(std::string contentSizeCategory);
45
+ void onLayoutChange();
46
+ jsi::Object parseEventPayload(EventPayload payload);
47
+ jsi::Object parseEventNestedPayload(EventNestedValue payload);
48
+
49
+ std::function<Dimensions()> getScreenDimensions;
50
+ std::function<std::string()> getContentSizeCategory;
51
+ std::function<std::string()> getColorScheme;
52
+ std::function<Dimensions()> getStatusBarDimensions;
53
+ std::function<Dimensions()> getNavigationBarDimensions;
54
+ std::function<Insets()> getInsets;
55
+ std::optional<std::function<void(std::string)>> setStatusBarColor;
56
+ std::optional<std::function<void(std::string)>> setNavigationBarColor;
57
+
58
+ void setScreenDimensionsCallback(std::function<Dimensions()> callback) {
59
+ this->getScreenDimensions = callback;
60
+ }
61
+ void setContentSizeCategoryCallback(std::function<std::string()> callback) {
62
+ this->getContentSizeCategory = callback;
63
+ }
64
+ void setColorSchemeCallback(std::function<std::string()> callback) {
65
+ this->getColorScheme = callback;
66
+ }
67
+ void setStatusBarDimensionsCallback(std::function<Dimensions()> callback) {
68
+ this->getStatusBarDimensions = callback;
69
+ }
70
+ void setNavigationBarDimensionsCallback(std::function<Dimensions()> callback) {
71
+ this->getNavigationBarDimensions = callback;
72
+ }
73
+ void setInsetsCallback(std::function<Insets()> callback) {
74
+ this->getInsets = callback;
75
+ }
76
+ void setStatusBarColorCallback(std::function<void(std::string color)> callback) {
77
+ this->setStatusBarColor = callback;
78
+ }
79
+ void setNavigationBarColorCallback(std::function<void(std::string color)> callback) {
80
+ this->setNavigationBarColor = callback;
81
+ }
82
+
83
+ Dimensions screen = {0, 0};
84
+ Dimensions statusBar = {0, 0};
85
+ Dimensions navigationBar = {0, 0};
86
+ Insets insets = {0, 0, 0, 0};
87
+ std::string colorScheme = UnistylesUnspecifiedScheme;
88
+ std::string contentSizeCategory = UnistylesUnspecifiedScheme;
89
+
90
+ UnistylesModel(jsi::Runtime& rt, std::shared_ptr<react::CallInvoker> callInvoker): runtime(rt), callInvoker(callInvoker) {}
91
+
92
+ bool hasAdaptiveThemes;
93
+ bool supportsAutomaticColorScheme;
94
+
95
+ std::string themeName;
96
+ std::string breakpoint;
97
+ std::vector<std::string> pluginNames;
98
+ std::vector<std::string> themes;
99
+ std::vector<std::pair<std::string, double>> sortedBreakpointPairs;
100
+
101
+ void handleScreenSizeChange(Dimensions& screen, std::optional<Insets> insets, std::optional<Dimensions> statusBar, std::optional<Dimensions> navigationBar);
102
+ void handleAppearanceChange(std::string colorScheme);
103
+ void handleContentSizeCategoryChange(std::string contentSizeCategory);
104
+
105
+ jsi::Value getThemeOrFail(jsi::Runtime&);
106
+ std::string getBreakpointFromScreenWidth(int width, const std::vector<std::pair<std::string, double>>& sortedBreakpointEntries);
107
+ std::vector<std::pair<std::string, double>> toSortedBreakpointPairs(jsi::Runtime&, jsi::Object&);
108
+
109
+ private:
110
+ jsi::Runtime& runtime;
111
+ std::shared_ptr<react::CallInvoker> callInvoker;
112
+ };