Skip to content

Commit ae59273

Browse files
committed
feat: prop mapping
1 parent 151719b commit ae59273

2 files changed

Lines changed: 100 additions & 32 deletions

File tree

cpp/StyledComputedFactory.cpp

Lines changed: 98 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace margelo::nitro::cssnitro {
3939
* So we use an unordered_map and convert it to AnyMap at the end.
4040
*/
4141
std::unordered_map<std::string, AnyValue> mergedStyles;
42+
std::unordered_map<std::string, AnyValue> mergedProps;
4243

4344
// Collect all style rules from all classNames
4445
std::vector<HybridStyleRule> allStyleRules;
@@ -81,34 +82,89 @@ namespace margelo::nitro::cssnitro {
8182
}
8283

8384
if (styleRule.d.has_value()) {
84-
const auto declarations = styleRule.d.value();
85-
const auto &dStyles = std::get<0>(std::get<0>(declarations));
86-
for (const auto &kv: dStyles->getMap()) {
87-
// Only set if key doesn't already exist
88-
if (mergedStyles.count(kv.first) == 0) {
89-
// if kv.second is an array with "fn" as the first key, resolve it
90-
if (dStyles->isArray(kv.first)) {
91-
const auto &arr = dStyles->getArray(kv.first);
92-
if (!arr.empty() &&
93-
std::holds_alternative<std::string>(arr[0]) &&
94-
std::get<std::string>(arr[0]) == "fn") {
95-
auto result = StyleFunction::resolveStyleFn(
96-
arr, get, variableScope);
97-
98-
// Skip if resolveStyleFn returns nullptr
99-
if (std::holds_alternative<std::monostate>(
100-
result)) {
101-
continue;
85+
const auto &declarations = styleRule.d.value();
86+
87+
// declarations is a variant that can hold either:
88+
// - tuple with 1 item (single declaration)
89+
// - tuple with 2 items (multiple declarations)
90+
// We use std::visit to safely access it
91+
std::visit([&mergedStyles, &mergedProps, &get, &variableScope](
92+
const auto &decl) {
93+
// decl is a tuple, get the first element (the styles)
94+
const auto &dStyles = std::get<0>(decl);
95+
96+
// Check if dStyles is valid before accessing
97+
if (dStyles) {
98+
for (const auto &kv: dStyles->getMap()) {
99+
// Only set if key doesn't already exist
100+
if (mergedStyles.count(kv.first) == 0) {
101+
// if kv.second is an array with "fn" as the first key, resolve it
102+
if (dStyles->isArray(kv.first)) {
103+
const auto &arr = dStyles->getArray(kv.first);
104+
if (!arr.empty() &&
105+
std::holds_alternative<std::string>(
106+
arr[0]) &&
107+
std::get<std::string>(arr[0]) == "fn") {
108+
auto result = StyleFunction::resolveStyleFn(
109+
arr, get, variableScope);
110+
111+
// Skip if resolveStyleFn returns nullptr
112+
if (std::holds_alternative<std::monostate>(
113+
result)) {
114+
return;
115+
}
116+
117+
mergedStyles[kv.first] = result;
118+
return;
119+
}
102120
}
121+
mergedStyles[kv.first] = kv.second;
122+
}
123+
}
124+
}
103125

104-
mergedStyles[kv.first] = result;
105-
continue;
126+
// Check if there's a second element in the tuple (props)
127+
if constexpr (std::tuple_size<std::decay_t<decltype(decl)>>::value >
128+
1) {
129+
const auto &dPropsOpt = std::get<1>(decl);
130+
131+
// dPropsOpt is optional, check if it has a value
132+
if (dPropsOpt.has_value()) {
133+
const auto &dProps = dPropsOpt.value();
134+
135+
// Check if dProps is valid before accessing
136+
if (dProps) {
137+
for (const auto &kv: dProps->getMap()) {
138+
// Only set if key doesn't already exist
139+
if (mergedProps.count(kv.first) == 0) {
140+
// if kv.second is an array with "fn" as the first key, resolve it
141+
if (dProps->isArray(kv.first)) {
142+
const auto &arr = dProps->getArray(
143+
kv.first);
144+
if (!arr.empty() &&
145+
std::holds_alternative<std::string>(
146+
arr[0]) &&
147+
std::get<std::string>(arr[0]) == "fn") {
148+
auto result = StyleFunction::resolveStyleFn(
149+
arr, get, variableScope);
150+
151+
// Skip if resolveStyleFn returns nullptr
152+
if (std::holds_alternative<std::monostate>(
153+
result)) {
154+
continue;
155+
}
156+
157+
mergedProps[kv.first] = result;
158+
continue;
159+
}
160+
}
161+
mergedProps[kv.first] = kv.second;
162+
}
163+
}
106164
}
107165
}
108-
mergedStyles[kv.first] = kv.second;
109166
}
110-
}
111-
// Ignore the other entries for now
167+
}, declarations);
112168
}
113169
}
114170

@@ -126,19 +182,21 @@ namespace margelo::nitro::cssnitro {
126182

127183
for (const auto &kv: mergedStyles) {
128184
if (transformProps.count(kv.first) > 0) {
129-
if (!anyMap->contains("transform")) {
130-
anyMap->setArray("transform", AnyArray{});
131-
}
185+
AnyArray transformArray;
132186

133-
auto transformArray = anyMap->getArray("transform");
187+
// Get existing transform array if it exists
188+
if (anyMap->contains("transform")) {
189+
transformArray = anyMap->getArray("transform");
190+
}
134191

135192
// find the value in the array with the key matching kv.first and set it to kv.second
136193
bool foundTransform = false;
137-
for (auto &item: transformArray) {
138-
if (std::holds_alternative<AnyObject>(item)) {
139-
auto &obj = std::get<AnyObject>(item);
194+
for (size_t i = 0; i < transformArray.size(); i++) {
195+
if (std::holds_alternative<AnyObject>(transformArray[i])) {
196+
auto obj = std::get<AnyObject>(transformArray[i]);
140197
if (obj.count(kv.first) > 0) {
141198
obj[kv.first] = kv.second;
199+
transformArray[i] = obj;
142200
foundTransform = true;
143201
break;
144202
}
@@ -161,6 +219,16 @@ namespace margelo::nitro::cssnitro {
161219
next.style = anyMap;
162220
}
163221

222+
// Convert mergedProps to AnyMap and set next.props
223+
if (!mergedProps.empty()) {
224+
auto anyMap = AnyMap::make(mergedProps.size());
225+
226+
for (const auto &kv: mergedProps) {
227+
anyMap->setAny(kv.first, kv.second);
228+
}
229+
next.props = anyMap;
230+
}
231+
164232
if (shouldRerender(next)) {
165233
(void) rerender();
166234
}

example/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ StyleRegistry.addStyleSheet({
1717
// transitionDuration: "5s",
1818
},
1919
{
20-
selectionColor: "green",
20+
selectionColor: "blue",
2121
},
2222
],
2323
},
@@ -39,7 +39,7 @@ StyleRegistry.addStyleSheet({
3939
export default function App() {
4040
return (
4141
<View style={styles.container}>
42-
<Text className="text-red-500" style={{ fontSize: 30 }} disabled>
42+
<Text className="text-red-500" style={{ fontSize: 30 }} selectable>
4343
Multiply: {multiply(3, 7)}
4444
</Text>
4545
</View>

0 commit comments

Comments
 (0)