fix: tw getComputedStyle

This commit is contained in:
Mark Lawlor
2022-05-09 10:18:32 +10:00
parent 62d18efb5c
commit b322373a34
6 changed files with 1887 additions and 18 deletions

View File

@@ -9,12 +9,14 @@ const useWindowDimensions = RNuseWindowDimensions as jest.Mock<
>;
jest.mock("react-native", () => {
const { Appearance, Dimensions } = jest.requireActual("react-native");
const { Appearance, Dimensions, StyleSheet } =
jest.requireActual("react-native");
return {
__esModule: true,
Appearance,
Dimensions,
StyleSheet,
useWindowDimensions: jest.fn(() => ({
width: 0,
height: 0,
@@ -73,6 +75,25 @@ describe("native", () => {
expect(result.current).toEqual([{ fontWeight: "700" }]);
});
test("can flatten properties", () => {
const { result } = renderHook(() => useTailwind()("font-bold"), {
wrapper,
initialProps: {
platform: "native",
styles: {
"font-bold": {
fontWeight: "700",
},
"font-extrabold": {
fontWeight: "800",
},
},
},
});
expect(result.current.fontWeight).toEqual("700");
});
test("media - width", () => {
useWindowDimensions.mockReturnValue({
width: 1000,

View File

@@ -0,0 +1,37 @@
import { PropsWithChildren } from "react";
import { renderHook } from "@testing-library/react-hooks";
import { useTailwind } from "../src/use-tailwind.web";
import { TailwindProvider, TailwindProviderProps } from "../src/provider";
import { RWNCssStyle } from "../src/use-tailwind";
const wrapper = ({
children,
...props
}: PropsWithChildren<TailwindProviderProps>) => (
<TailwindProvider {...props}>{children}</TailwindProvider>
);
describe("web", () => {
test("can accept no arguments", () => {
const { result } = renderHook(() => useTailwind<RWNCssStyle>()(), {
wrapper,
initialProps: { platform: "web", preview: true },
});
expect(result.current.$$css).toBe(true);
expect(result.current.tailwindClassName).toBe("");
});
test("will pass-through any arguments", () => {
const { result } = renderHook(
() => useTailwind<RWNCssStyle>()("hello-world"),
{
wrapper,
initialProps: { platform: "web", preview: true },
}
);
expect(result.current.$$css).toBe(true);
expect(result.current.tailwindClassName).toBe("hello-world");
});
});

View File

@@ -1,8 +1,15 @@
import {
TextStyle,
useWindowDimensions as RNuseWindowDimensions,
} from "react-native";
import { PropsWithChildren } from "react";
import { renderHook } from "@testing-library/react-hooks";
import { useTailwind } from "../src/use-tailwind.web";
import { TailwindProvider, TailwindProviderProps } from "../src/provider";
import { RWNCssStyle } from "../src/use-tailwind";
const useWindowDimensions = RNuseWindowDimensions as jest.Mock<
Partial<ReturnType<typeof RNuseWindowDimensions>>
>;
const wrapper = ({
children,
@@ -11,27 +18,134 @@ const wrapper = ({
<TailwindProvider {...props}>{children}</TailwindProvider>
);
jest.mock("react-native", () => {
/**
* Run this test with react-native-web instead of react-native
*/
const { Appearance, Dimensions, StyleSheet, Platform } =
jest.requireActual("react-native-web");
return {
__esModule: true,
Appearance,
Dimensions,
StyleSheet,
Platform,
useWindowDimensions: jest.fn(() => ({
width: 0,
height: 0,
scale: 1,
fontScale: 1,
})),
};
});
afterEach(() => {
jest.clearAllMocks();
});
describe("web", () => {
test("can accept no arguments", () => {
const { result } = renderHook(() => useTailwind<RWNCssStyle>()(), {
const { result } = renderHook(() => useTailwind()(), {
wrapper,
initialProps: { platform: "web", preview: true },
initialProps: { platform: "native" },
});
expect(result.current.$$css).toBe(true);
expect(result.current.tailwindClassName).toBe("");
expect(result.current).toEqual([]);
});
test("will pass-through any arguments", () => {
const { result } = renderHook(
() => useTailwind<RWNCssStyle>()("hello-world"),
{
wrapper,
initialProps: { platform: "web", preview: true },
}
);
test("will return nothing is no styles match", () => {
const { result } = renderHook(() => useTailwind()("hello-world"), {
wrapper,
initialProps: { platform: "native" },
});
expect(result.current.$$css).toBe(true);
expect(result.current.tailwindClassName).toBe("hello-world");
expect(result.current).toEqual([]);
});
test("will return matched styles", () => {
const { result } = renderHook(() => useTailwind()("font-bold"), {
wrapper,
initialProps: {
platform: "native",
styles: {
"font-bold": {
fontWeight: "700",
},
"font-extrabold": {
fontWeight: "800",
},
},
},
});
expect(result.current).toEqual([{ fontWeight: "700" }]);
});
test("can flatten properties", () => {
const { result } = renderHook(() => useTailwind<TextStyle>()("font-bold"), {
wrapper,
initialProps: {
platform: "native",
styles: {
"font-bold": {
fontWeight: "700",
},
"font-extrabold": {
fontWeight: "800",
},
},
},
});
expect(result.current.fontWeight).toEqual("700");
});
test("media - width", () => {
useWindowDimensions.mockReturnValue({
width: 1000,
});
const { result } = renderHook(() => useTailwind()("container"), {
wrapper,
initialProps: {
platform: "native",
styles: {
container: {
width: "100%",
},
"container.0": {
maxWidth: 640,
},
"container.1": {
maxWidth: 768,
},
"container.2": {
maxWidth: 1024,
},
"container.3": {
maxWidth: 1280,
},
"container.4": {
maxWidth: 1536,
},
},
media: {
container: [
"(min-width: 640px)",
"(min-width: 768px)",
"(min-width: 1024px)",
"(min-width: 1280px)",
"(min-width: 1536px)",
],
},
},
});
expect(result.current).toEqual([
{ width: "100%" },
{ maxWidth: 640 },
{ maxWidth: 768 },
]);
});
});

1670
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -79,11 +79,14 @@
"eslint-plugin-unicorn": "42.0.0",
"husky": "7.0.4",
"jest": "28.1.0",
"jest-environment-jsdom": "^28.1.0",
"metro-react-native-babel-preset": "0.70.3",
"moti": "0.17.1",
"prettier": "2.6.2",
"react": "18.1.0",
"react-dom": "^18.1.0",
"react-native": "0.68.1",
"react-native-web": "^0.17.7",
"react-test-renderer": "18.1.0",
"tailwindcss": "3.0.24",
"ts-jest": "28.0.2",

View File

@@ -1,5 +1,10 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useWindowDimensions, StyleProp } from "react-native";
import {
useWindowDimensions,
StyleProp,
StyleSheet,
TextStyle,
} from "react-native";
import { useContext } from "react";
import { useDeviceOrientation } from "@react-native-community/hooks";
@@ -13,6 +18,8 @@ import {
TailwindStyleContext,
} from "./context";
const computedStyles = new WeakMap();
export function useTailwind<P>({ siblingClassName = "" } = {}) {
const platform = useContext(TailwindPlatformContext);
const styles = useContext(TailwindStyleContext);
@@ -63,6 +70,23 @@ export function useTailwind<P>({ siblingClassName = "" } = {}) {
}
}
return tailwindStyleIds;
const proxy = new Proxy(tailwindStyleIds, {
get(target, property: string | number | symbol) {
if (property in tailwindStyleIds) {
return tailwindStyleIds[property as keyof typeof tailwindStyleIds];
}
if (!computedStyles.has(tailwindStyleIds)) {
computedStyles.set(
tailwindStyleIds,
StyleSheet.flatten(tailwindStyleIds)
);
}
return computedStyles.get(target)[property];
},
});
return proxy as StyleProp<P> & TextStyle;
};
}