diff --git a/src/__tests__/native/variables.test.tsx b/src/__tests__/native/variables.test.tsx index a824f800..6a4a7d23 100644 --- a/src/__tests__/native/variables.test.tsx +++ b/src/__tests__/native/variables.test.tsx @@ -4,7 +4,7 @@ import type { ViewProps } from "react-native"; import { render, screen } from "@testing-library/react-native"; import { View } from "react-native-css/components/View"; import { registerCSS, testID } from "react-native-css/jest"; -import { styled } from "react-native-css/runtime"; +import { styled, VariableContextProvider } from "react-native-css/runtime"; test("inline variable", () => { registerCSS(`.my-class { width: var(--my-var); --my-var: 10px; }`); @@ -230,3 +230,18 @@ test("ratio values", () => { expect(component.props.style).toStrictEqual({ aspectRatio: "16 / 9" }); }); + +test("VariableContextProvider", () => { + registerCSS(` + .test { color: var(--my-var); } + `); + + render( + + + , + ); + + const component = screen.getByTestId(testID); + expect(component.props.style).toStrictEqual({ color: "red" }); +}); diff --git a/src/__tests__/native/vars.test.tsx b/src/__tests__/native/vars.test.tsx index 19df5490..d87eb7c4 100644 --- a/src/__tests__/native/vars.test.tsx +++ b/src/__tests__/native/vars.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-deprecated */ import { render, screen } from "@testing-library/react-native"; import { View } from "react-native-css/components/View"; import { registerCSS, testID } from "react-native-css/jest"; diff --git a/src/runtime/native/api.ts b/src/runtime/native/api.tsx similarity index 74% rename from src/runtime/native/api.ts rename to src/runtime/native/api.tsx index 2c877204..689d49f8 100644 --- a/src/runtime/native/api.ts +++ b/src/runtime/native/api.tsx @@ -1,8 +1,8 @@ /* eslint-disable */ -import { useContext, useState } from "react"; +import { useContext, useMemo, useState, type PropsWithChildren } from "react"; import { Appearance } from "react-native"; -import type { InlineVariable, StyleDescriptor } from "../../compiler"; +import type { StyleDescriptor } from "../../compiler"; import type { ColorScheme, Props, @@ -18,6 +18,7 @@ import { VariableContext, type Effect, type Getter, + type VariableContextValue, } from "./reactivity"; import { resolveValue } from "./styles/resolve"; @@ -102,7 +103,33 @@ export function useNativeVariable(name: string) { return resolveValue([{}, "var", [name]], effect.get, { inheritedVariables }); } +/** + * @deprecated Use `` instead. + */ export function vars(variables: Record) { - (variables as InlineVariable)[VAR_SYMBOL] = "inline"; - return variables; + return Object.assign( + { [VAR_SYMBOL]: "inline" }, + Object.fromEntries( + Object.entries(variables).map(([k, v]) => [k.replace(/^--/, ""), v]), + ), + ); +} + +export function VariableContextProvider( + props: PropsWithChildren<{ value: Record<`--${string}`, StyleDescriptor> }>, +) { + const inheritedVariables = useContext(VariableContext); + + const value: VariableContextValue = useMemo( + () => ({ + ...inheritedVariables, + ...Object.fromEntries( + Object.entries(props.value).map(([k, v]) => [k.replace(/^--/, ""), v]), + ), + [VAR_SYMBOL]: true, + }), + [inheritedVariables, props.value], + ); + + return {props.children}; } diff --git a/src/runtime/web/api.ts b/src/runtime/web/api.tsx similarity index 74% rename from src/runtime/web/api.ts rename to src/runtime/web/api.tsx index 65935ac5..189c249c 100644 --- a/src/runtime/web/api.ts +++ b/src/runtime/web/api.tsx @@ -1,4 +1,9 @@ -import { createElement, type ComponentProps } from "react"; +import { + createElement, + useMemo, + type ComponentProps, + type PropsWithChildren, +} from "react"; import { Appearance } from "react-native"; import type { @@ -24,7 +29,7 @@ export const styled = < }; }; -export const useCssElement = ( +export const useCssElement = ( component: C, incomingProps: Props, mapping: StyledConfiguration, @@ -66,6 +71,9 @@ export const colorScheme: ColorScheme = { }, }; +/** + * @deprecated Use `` instead. + */ export function vars(variables: Record) { const $variables: Record = {}; @@ -79,6 +87,24 @@ export function vars(variables: Record) { return $variables; } +export function VariableContextProvider( + props: PropsWithChildren<{ value: Record<`--${string}`, string> }>, +) { + const style = useMemo(() => { + return { + display: "content", + ...Object.fromEntries( + Object.entries(props.value).map(([key, value]) => [ + key.startsWith("--") ? key : `--${key}`, + value, + ]), + ), + }; + }, [props.value]); + + return
{props.children}
; +} + export const useNativeVariable = () => { throw new Error("useNativeVariable is not supported in web"); };