Skip to content

Commit 3dabbf8

Browse files
committed
fix: correctly setting new root variables
1 parent 45a3fbf commit 3dabbf8

File tree

5 files changed

+134
-35
lines changed

5 files changed

+134
-35
lines changed

cpp/HybridStyleRegistry.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ namespace margelo::nitro::cssnitro {
7272
}
7373

7474
void HybridStyleRegistry::setRootVariables(const std::shared_ptr<AnyMap> &variables) {
75-
VariableContext::createContext("root", "root");
7675

7776
// Loop over all entries in the AnyMap
7877
for (const auto &entry: variables->getMap()) {
@@ -85,7 +84,6 @@ namespace margelo::nitro::cssnitro {
8584
}
8685

8786
void HybridStyleRegistry::setUniversalVariables(const std::shared_ptr<AnyMap> &variables) {
88-
VariableContext::createContext("universal", "root");
8987

9088
// Loop over all entries in the AnyMap
9189
for (const auto &entry: variables->getMap()) {

cpp/Rules.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,19 @@ namespace margelo::nitro::cssnitro {
3131
}
3232

3333
auto &mediaMap = *rule.m.value();
34+
return testMediaMap(mediaMap, get);
35+
}
36+
37+
static bool
38+
testRule(const std::shared_ptr<AnyMap> &mediaMap, reactnativecss::Effect::GetProxy &get) {
39+
if (!mediaMap) {
40+
return true;
41+
}
42+
return testMediaMap(*mediaMap, get);
43+
}
3444

45+
private:
46+
static bool testMediaMap(const AnyMap &mediaMap, reactnativecss::Effect::GetProxy &get) {
3547
// Get all keys to check if empty
3648
auto keys = mediaMap.getAllKeys();
3749
if (keys.empty()) {
@@ -117,7 +129,6 @@ namespace margelo::nitro::cssnitro {
117129
return finalResult;
118130
}
119131

120-
private:
121132
static bool
122133
testMediaQuery(const std::string &key, const std::string &op, const AnyValue &value,
123134
reactnativecss::Effect::GetProxy &get) {

cpp/VariableContext.cpp

Lines changed: 113 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#include "VariableContext.hpp"
2+
#include "Rules.hpp"
23

34
namespace margelo::nitro::cssnitro {
45

56
using AnyValue = ::margelo::nitro::AnyValue;
7+
using AnyMap = ::margelo::nitro::AnyMap;
8+
using AnyObject = ::margelo::nitro::AnyObject;
69

710
// Initialize the static contexts map
811
std::unordered_map<std::string, VariableContext::Context> VariableContext::contexts;
@@ -43,6 +46,11 @@ namespace margelo::nitro::cssnitro {
4346
std::optional<AnyValue> VariableContext::checkContext(const std::string &contextKey,
4447
const std::string &name,
4548
reactnativecss::Effect::GetProxy &get) {
49+
// If this is a root or universal context, ensure it exists
50+
if (contextKey == "root" || contextKey == "universal") {
51+
createContext(contextKey, "root");
52+
}
53+
4654
auto contextIt = contexts.find(contextKey);
4755
if (contextIt != contexts.end()) {
4856
auto &valueMap = contextIt->second.values;
@@ -54,12 +62,27 @@ namespace margelo::nitro::cssnitro {
5462
return result;
5563
}
5664
} else {
57-
// Variable doesn't exist in this context, create a new Observable with nullptr
58-
auto observable = reactnativecss::Observable<AnyValue>::create(AnyValue());
59-
valueMap[name] = observable;
65+
// Variable doesn't exist in this context
66+
// Check if this is a root or universal context
67+
if (contextKey == "root" || contextKey == "universal") {
68+
// For root/universal, create a top-level computed
69+
auto &targetMap = (contextKey == "root") ? root_values : universal_values;
70+
auto computed = createTopLevelVariableComputed(targetMap, name);
71+
valueMap[name] = computed;
72+
73+
// Get the initial value from the computed
74+
auto result = get(*computed);
75+
if (!std::holds_alternative<std::monostate>(result)) {
76+
return result;
77+
}
78+
} else {
79+
// For other contexts, create a new Observable with nullptr
80+
auto observable = reactnativecss::Observable<AnyValue>::create(AnyValue());
81+
valueMap[name] = observable;
6082

61-
// Subscribe to the observable by calling get()
62-
get(*observable);
83+
// Subscribe to the observable by calling get()
84+
get(*observable);
85+
}
6386
}
6487
}
6588
return std::nullopt;
@@ -116,7 +139,8 @@ namespace margelo::nitro::cssnitro {
116139
auto contextIt = contexts.find(key);
117140
if (contextIt == contexts.end()) {
118141
// Context doesn't exist, create it with empty parent
119-
createContext(key, "");
142+
// This couldn't happen in normal usage, but just in case
143+
createContext(key, "root");
120144
contextIt = contexts.find(key);
121145
}
122146

@@ -196,25 +220,92 @@ namespace margelo::nitro::cssnitro {
196220
auto varIt = valueMap.find(name);
197221

198222
if (varIt == valueMap.end()) {
199-
// Variable doesn't exist in context, create a Computed that reads from the target map
200-
auto computed = reactnativecss::Computed<AnyValue>::create(
201-
[&targetMap, name](const AnyValue &prev,
202-
reactnativecss::Effect::GetProxy &get) -> AnyValue {
203-
(void) prev;
204-
205-
// Read from the target map
206-
auto it = targetMap.find(name);
207-
if (it != targetMap.end()) {
208-
return get(*it->second);
209-
}
210-
return AnyValue();
211-
},
212-
AnyValue() // Initial value
213-
);
214-
223+
// Variable doesn't exist in context, create a Computed using the factory
224+
auto computed = createTopLevelVariableComputed(targetMap, name);
215225
valueMap[name] = computed;
216226
}
217227
}
218228
}
219229

230+
std::shared_ptr<reactnativecss::Computed<AnyValue>>
231+
VariableContext::createTopLevelVariableComputed(
232+
std::unordered_map<std::string, std::shared_ptr<reactnativecss::Observable<AnyValue>>> &targetMap,
233+
const std::string &name) {
234+
return reactnativecss::Computed<AnyValue>::create(
235+
[&targetMap, name](const AnyValue &prev,
236+
reactnativecss::Effect::GetProxy &get) -> AnyValue {
237+
(void) prev;
238+
239+
// Read from the target map
240+
auto it = targetMap.find(name);
241+
if (it != targetMap.end()) {
242+
auto value = get(*it->second);
243+
244+
// Check if value is an array
245+
if (!std::holds_alternative<AnyArray>(value)) {
246+
return AnyValue();
247+
}
248+
249+
const auto &arr = std::get<AnyArray>(value);
250+
251+
// Loop over the array
252+
for (const auto &item: arr) {
253+
// Each item should be an object with "v" and "m" keys
254+
if (!std::holds_alternative<AnyObject>(item)) {
255+
continue;
256+
}
257+
258+
const auto &obj = std::get<AnyObject>(item);
259+
260+
// Check if "m" is set
261+
auto mIt = obj.find("m");
262+
if (mIt != obj.end() &&
263+
!std::holds_alternative<std::monostate>(mIt->second)) {
264+
// "m" is set, test the media query/condition
265+
const auto &mValue = mIt->second;
266+
267+
// Convert AnyValue to AnyMap if it's an object
268+
if (std::holds_alternative<AnyObject>(mValue)) {
269+
const auto &mediaObj = std::get<AnyObject>(mValue);
270+
auto mediaMap = AnyMap::make(mediaObj.size());
271+
272+
// Copy the object into an AnyMap
273+
for (const auto &kv: mediaObj) {
274+
mediaMap->setAny(kv.first, kv.second);
275+
}
276+
277+
// Test the rule - if it doesn't pass, continue to next item
278+
if (!Rules::testRule(mediaMap, get)) {
279+
continue;
280+
}
281+
// If it passes, fall through to return the "v" value
282+
} else {
283+
// "m" exists but is not an AnyObject, skip this item
284+
continue;
285+
}
286+
}
287+
288+
// "m" is not set or the media query passed, return the value of "v"
289+
auto vIt = obj.find("v");
290+
if (vIt != obj.end()) {
291+
return vIt->second;
292+
}
293+
}
294+
295+
return AnyValue();
296+
} else {
297+
// Observable doesn't exist, create it and subscribe
298+
auto observable = reactnativecss::Observable<AnyValue>::create(AnyValue());
299+
targetMap[name] = observable;
300+
301+
// Subscribe to the observable
302+
get(*observable);
303+
304+
return AnyValue();
305+
}
306+
},
307+
AnyValue() // Initial value
308+
);
309+
}
310+
220311
} // namespace margelo::nitro::cssnitro

cpp/VariableContext.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ namespace margelo::nitro::cssnitro {
6868
static std::optional<AnyValue>
6969
checkContext(const std::string &contextKey, const std::string &name,
7070
reactnativecss::Effect::GetProxy &get);
71+
72+
// Factory function to create a Computed for top-level variables
73+
static std::shared_ptr<reactnativecss::Computed<AnyValue>>
74+
createTopLevelVariableComputed(
75+
std::unordered_map<std::string, std::shared_ptr<reactnativecss::Observable<AnyValue>>> &targetMap,
76+
const std::string &name);
7177
};
7278

7379
} // namespace margelo::nitro::cssnitro

example/src/App.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,16 @@ StyleRegistry.addStyleSheet({
2020
],
2121
});
2222

23-
// StyleRegistry.setRootVariables({
24-
// test: [{ v: "blue" }],
25-
// });
26-
2723
export default function App() {
2824
return (
2925
<View style={styles.container}>
3026
<Text
3127
className="text-red-500"
3228
onPress={() => {
3329
console.log("Pressed!");
34-
StyleRegistry.setClassname("text-red-500", [
35-
{
36-
s: [],
37-
d: [{ color: "blue", fontSize: 40 }],
38-
},
39-
]);
30+
StyleRegistry.setRootVariables({
31+
test: [{ v: "pink", m: { orientation: ["=", "landscape"] } }],
32+
});
4033
}}
4134
>
4235
Multiply: {multiply(3, 7)}

0 commit comments

Comments
 (0)