diff --git a/src/__tests__/native/components.test.tsx b/src/__tests__/native/components.test.tsx index 31fcb84f..3a596038 100644 --- a/src/__tests__/native/components.test.tsx +++ b/src/__tests__/native/components.test.tsx @@ -1,7 +1,13 @@ -import { Button as RNButton, type ButtonProps } from "react-native"; +import { + Button as RNButton, + TextInput as RNTextInput, + type ButtonProps, + type TextInputProps, +} from "react-native"; import { render } from "@testing-library/react-native"; import { copyComponentProperties } from "react-native-css/components/copyComponentProperties"; +import { TextInput } from "react-native-css/components/TextInput"; import { registerCSS, testID } from "react-native-css/jest"; import { useCssElement } from "react-native-css/native"; import type { @@ -54,3 +60,57 @@ test("Component preserves props when mapping specifies 'target: false'", () => { expect(titleElement.props.style).toHaveLength(2); expect(titleElement.props.style[1]).toEqual({ color: "#ffa500" }); }); + +test("nativeStyleMapping with boolean true extracts style prop using key name", () => { + registerCSS(`.text-center { text-align: center; }`); + + const component = render( + , + ).getByTestId(testID); + + // textAlign should be extracted from style and mapped to the textAlign prop + expect(component.props.textAlign).toBe("center"); + expect(component.props.style).not.toHaveProperty("textAlign"); +}); + +test("nativeStyleMapping with boolean true works alongside other styles", () => { + registerCSS(` + .text-center { text-align: center; } + .text-red { color: red; } + `); + + const component = render( + , + ).getByTestId(testID); + + // textAlign extracted to prop, color stays in style + expect(component.props.textAlign).toBe("center"); + expect(component.props.style).toStrictEqual({ color: "#f00" }); +}); + +test("nativeStyleMapping with boolean true on custom component", () => { + registerCSS(`.text-right { text-align: right; }`); + + const mapping: StyledConfiguration = { + className: { + target: "style", + nativeStyleMapping: { + textAlign: true, + }, + }, + }; + + const StyledTextInput = copyComponentProperties( + RNTextInput, + (props: StyledProps) => { + return useCssElement(RNTextInput, props, mapping); + }, + ); + + const component = render( + , + ).getByTestId(testID); + + expect(component.props.textAlign).toBe("right"); + expect(component.props.style).not.toHaveProperty("textAlign"); +}); diff --git a/src/native/react/useNativeCss.ts b/src/native/react/useNativeCss.ts index 43868202..11d3ede8 100644 --- a/src/native/react/useNativeCss.ts +++ b/src/native/react/useNativeCss.ts @@ -181,9 +181,14 @@ export function mappingToConfig(mapping: StyledConfiguration) { } else if (typeof value === "string") { return { source: key, target: value.split(".") }; } else if (typeof value === "object") { - const nativeStyleMapping = value.nativeStyleMapping as - | Record - | undefined; + const nativeStyleMapping = value.nativeStyleMapping + ? Object.fromEntries( + Object.entries(value.nativeStyleMapping).map(([k, v]) => [ + k, + v === true ? k : v, + ]), + ) + : undefined; if (Array.isArray(value)) { return { source: key, target: value, nativeStyleMapping };