Skip to content

Commit f25aaa3

Browse files
committed
feat: style functions
1 parent df6e6d7 commit f25aaa3

6 files changed

Lines changed: 102 additions & 11 deletions

File tree

cpp/HybridStyleRegistry.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,18 @@ namespace margelo::nitro::cssnitro {
168168
}
169169

170170
void HybridStyleRegistry::Impl::set(const std::string &className,
171-
const std::vector<HybridStyleRule> &styleRule) {
171+
const std::vector<HybridStyleRule> &styleRules) {
172+
// Reverse the style rules, this way later on we can bail early if values are already set
173+
auto reversedRules = styleRules;
174+
std::reverse(reversedRules.begin(), reversedRules.end());
175+
172176
auto it = styleRuleMap_.find(className);
173177
if (it == styleRuleMap_.end()) {
174178
auto observable = reactnativecss::Observable<std::vector<HybridStyleRule>>::create(
175-
styleRule);
179+
reversedRules);
176180
styleRuleMap_.emplace(className, std::move(observable));
177181
} else if (it->second) {
178-
it->second->set(styleRule);
182+
it->second->set(reversedRules);
179183
}
180184
}
181185

cpp/StyleFunction.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// Created on October 15, 2025.
3+
//
4+
5+
#include "StyleFunction.hpp"
6+
#include <NitroModules/AnyMap.hpp>
7+
8+
namespace margelo::nitro::cssnitro {
9+
10+
AnyValue StyleFunction::resolveStyleFn(
11+
const std::string &fnName,
12+
const AnyArray &fnArgs,
13+
typename reactnativecss::Effect::GetProxy &get
14+
) {
15+
(void) fnName;
16+
(void) fnArgs;
17+
(void) get;
18+
19+
20+
return AnyValue("purple");
21+
}
22+
23+
} // namespace margelo::nitro::cssnitro

cpp/StyleFunction.hpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// Created on October 15, 2025.
3+
//
4+
5+
#pragma once
6+
7+
#include <string>
8+
#include <unordered_map>
9+
#include <vector>
10+
#include <variant>
11+
#include "Effect.hpp"
12+
13+
namespace margelo::nitro {
14+
struct AnyValue;
15+
using AnyArray = std::vector<AnyValue>;
16+
using AnyObject = std::unordered_map<std::string, AnyValue>;
17+
}
18+
19+
namespace margelo::nitro::cssnitro {
20+
21+
using AnyValue = ::margelo::nitro::AnyValue;
22+
using AnyArray = ::margelo::nitro::AnyArray;
23+
24+
class StyleFunction {
25+
public:
26+
/**
27+
* Resolve a style function by name with the given arguments.
28+
*
29+
* @param fnName The name of the function to resolve
30+
* @param fnArgs The arguments to pass to the function
31+
* @param get The Effect::GetProxy for reactive dependencies
32+
* @return The resolved style value
33+
*/
34+
static AnyValue resolveStyleFn(
35+
const std::string &fnName,
36+
const AnyArray &fnArgs,
37+
typename reactnativecss::Effect::GetProxy &get
38+
);
39+
};
40+
41+
} // namespace margelo::nitro::cssnitro

cpp/StyledComputedFactory.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "ShadowTreeUpdateManager.hpp"
44
#include "Rules.hpp"
55
#include "Helpers.hpp"
6+
#include "StyleFunction.hpp"
67

78
#include <regex>
89
#include <variant>
@@ -57,13 +58,34 @@ namespace margelo::nitro::cssnitro {
5758
}
5859

5960
if (styleRule.d.has_value()) {
60-
// Get the tuple from styleRule.d
61-
const auto &dTuple = styleRule.d.value();
62-
63-
// Merge styleRule.d[0] into mergedStyles
64-
const auto &firstMap = std::get<0>(std::get<0>(dTuple));
65-
for (const auto &kv: firstMap->getMap()) {
66-
mergedStyles[kv.first] = kv.second;
61+
const auto declarations = styleRule.d.value();
62+
const auto &dStyles = std::get<0>(std::get<0>(declarations));
63+
for (const auto &kv: dStyles->getMap()) {
64+
// Only set if key doesn't already exist
65+
if (mergedStyles.count(kv.first) == 0) {
66+
// if kv.second is an array with "fn" as the first key, resolve it
67+
if (dStyles->isArray(kv.first)) {
68+
const auto &arr = dStyles->getArray(kv.first);
69+
if (!arr.empty() &&
70+
std::holds_alternative<std::string>(arr[0]) &&
71+
std::get<std::string>(arr[0]) == "fn") {
72+
// arr[1] is the function name, arr[2] is the arguments array
73+
if (arr.size() == 3 &&
74+
std::holds_alternative<std::string>(
75+
arr[1]) &&
76+
std::holds_alternative<AnyArray>(arr[2])) {
77+
const auto &fnName = std::get<std::string>(
78+
arr[1]);
79+
const auto &fnArgs = std::get<AnyArray>(
80+
arr[2]);
81+
mergedStyles[kv.first] = StyleFunction::resolveStyleFn(
82+
fnName, fnArgs, get);
83+
continue;
84+
}
85+
}
86+
}
87+
mergedStyles[kv.first] = kv.second;
88+
}
6789
}
6890
// Ignore the other entries for now
6991

example/src/App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Text } from "react-native-css-nitro/components/Text";
66
StyleRegistry.set("text-red-500", [
77
{ s: [], d: [{ color: "red" }] },
88
{ s: [], d: [{ color: "green" }], m: { orientation: ["=", "landscape"] } },
9+
{ s: [], d: [{ color: ["fn", "test", []] }] },
910
]);
1011

1112
export default function App() {

src/specs/StyleRegistry/HybridStyleRegistry.nitro.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ interface HybridStyleRule {
107107
v?: HybridVariableDescriptor[];
108108

109109
/** Declarations */
110-
d?: [AnyMap] | [AnyMap, AnyMap] | [AnyMap, AnyMap | undefined, AnyMap];
110+
d?: [AnyMap] | [AnyMap, AnyMap?];
111111

112112
/** MediaQuery */
113113
m?: AnyMap;

0 commit comments

Comments
 (0)