diff --git a/__tests__/tailwindcss/rotate.ts b/__tests__/tailwindcss/rotate.ts index d534ca4..99c8cb3 100644 --- a/__tests__/tailwindcss/rotate.ts +++ b/__tests__/tailwindcss/rotate.ts @@ -6,15 +6,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "rotate-0": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ rotate: "0deg" }], }, }, }, @@ -24,15 +16,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "rotate-45": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "45deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ rotate: "45deg" }], }, }, }, diff --git a/__tests__/tailwindcss/scale.ts b/__tests__/tailwindcss/scale.ts index 14401d6..180d425 100644 --- a/__tests__/tailwindcss/scale.ts +++ b/__tests__/tailwindcss/scale.ts @@ -6,15 +6,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "scale-0": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ scaleY: 0 }, { scaleX: 0 }], }, }, }, @@ -24,15 +16,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "scale-50": { - transform: [ - { scaleY: 0.5 }, - { scaleX: 0.5 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ scaleY: 0.5 }, { scaleX: 0.5 }], }, }, }, @@ -42,15 +26,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "scale-x-50": { - transform: [ - { scaleY: 0 }, - { scaleX: 0.5 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ scaleX: 0.5 }], }, }, }, @@ -60,15 +36,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "scale-y-50": { - transform: [ - { scaleY: 0.5 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ scaleY: 0.5 }], }, }, }, diff --git a/__tests__/tailwindcss/skew.ts b/__tests__/tailwindcss/skew.ts index dab3005..6e3da7e 100644 --- a/__tests__/tailwindcss/skew.ts +++ b/__tests__/tailwindcss/skew.ts @@ -6,15 +6,7 @@ tailwindRunner("Layout - Skew", [ { styles: { "skew-x-0": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ skewX: "0deg" }], }, }, }, @@ -24,15 +16,7 @@ tailwindRunner("Layout - Skew", [ { styles: { "skew-y-0": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ skewY: "0deg" }], }, }, }, @@ -42,15 +26,7 @@ tailwindRunner("Layout - Skew", [ { styles: { "skew-x-1": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "1deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ skewX: "1deg" }], }, }, }, @@ -60,15 +36,7 @@ tailwindRunner("Layout - Skew", [ { styles: { "skew-y-1": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "1deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ skewY: "1deg" }], }, }, }, diff --git a/__tests__/tailwindcss/translate.ts b/__tests__/tailwindcss/translate.ts index 1c2b62c..41cbf94 100644 --- a/__tests__/tailwindcss/translate.ts +++ b/__tests__/tailwindcss/translate.ts @@ -6,15 +6,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "translate-x-0": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ translateY: 0 }, { translateX: 0 }], }, }, }, @@ -24,15 +16,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "translate-y-0": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 0 }, - ], + transform: [{ translateY: 0 }, { translateX: 0 }], }, }, }, @@ -42,15 +26,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "translate-x-px": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 1 }, - ], + transform: [{ translateY: 0 }, { translateX: 1 }], }, }, }, @@ -60,15 +36,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "translate-y-px": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 1 }, - { translateX: 0 }, - ], + transform: [{ translateY: 1 }, { translateX: 0 }], }, }, }, @@ -78,15 +46,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "translate-x-1": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 0 }, - { translateX: 4 }, - ], + transform: [{ translateY: 0 }, { translateX: 4 }], }, }, }, @@ -96,15 +56,7 @@ tailwindRunner("Layout - Scale", [ { styles: { "translate-y-1": { - transform: [ - { scaleY: 0 }, - { scaleX: 0 }, - { skewY: "0deg" }, - { skewX: "0deg" }, - { rotate: "0deg" }, - { translateY: 4 }, - { translateX: 0 }, - ], + transform: [{ translateY: 4 }, { translateX: 0 }], }, }, }, diff --git a/__tests__/use-tailwind.native.tsx b/__tests__/use-tailwind.native.tsx index aa5b81d..29bb120 100644 --- a/__tests__/use-tailwind.native.tsx +++ b/__tests__/use-tailwind.native.tsx @@ -145,6 +145,27 @@ describe("native", () => { }); }); + test("transform - merges transforms", () => { + const { result } = renderHook(() => useTailwind()("scale-50 rotate-45"), { + wrapper, + initialProps: { + platform: "ios", + styles: { + "rotate-45": { + transform: [{ rotate: "45deg" }], + }, + "scale-50": { + transform: [{ scaleY: 0.5 }, { scaleX: 0.5 }], + }, + }, + }, + }); + + expect(result.current).toEqual({ + transform: [{ scaleY: 0.5 }, { scaleX: 0.5 }, { rotate: "45deg" }], + }); + }); + test("media - platform prefix", () => { const { result } = renderHook(() => useTailwind()("w-px"), { wrapper, diff --git a/src/plugin/native/index.ts b/src/plugin/native/index.ts index 2dd9889..5b07686 100644 --- a/src/plugin/native/index.ts +++ b/src/plugin/native/index.ts @@ -8,7 +8,11 @@ import { divide } from "./divide"; import { elevation } from "./elevation"; import { fontSize } from "./font-size"; import { lineHeight } from "./line-height"; +import { rotate } from "./rotate"; +import { scale } from "./scale"; +import { skew } from "./skew"; import { space } from "./space"; +import { translate } from "./translate"; export interface NativePluginOptions { rem?: number; @@ -34,6 +38,10 @@ export const nativePlugin = plugin.withOptions( fontSize(helpers); lineHeight(helpers, notSupported); elevation(helpers, notSupported); + scale(helpers, notSupported); + rotate(helpers, notSupported); + translate(helpers, notSupported); + skew(helpers, notSupported); }; }, function ({ rem = 16 } = {}) { @@ -171,6 +179,11 @@ export const nativePlugin = plugin.withOptions( divideColor: false, divideStyle: false, divideOpacity: false, + scale: false, + transform: false, + rotate: false, + skew: false, + translate: false, }, }; diff --git a/src/plugin/native/rotate.ts b/src/plugin/native/rotate.ts new file mode 100644 index 0000000..c327ac3 --- /dev/null +++ b/src/plugin/native/rotate.ts @@ -0,0 +1,17 @@ +import { CustomPluginFunction } from "./types"; + +export const rotate: CustomPluginFunction = ({ matchUtilities, theme }) => { + matchUtilities( + { + rotate(value: string) { + return { + transform: `rotate(${value})`, + }; + }, + }, + { + values: theme("rotate"), + supportsNegativeValues: true, + } + ); +}; diff --git a/src/plugin/native/scale.ts b/src/plugin/native/scale.ts new file mode 100644 index 0000000..d9ed0bf --- /dev/null +++ b/src/plugin/native/scale.ts @@ -0,0 +1,27 @@ +import { CustomPluginFunction } from "./types"; + +export const scale: CustomPluginFunction = ({ matchUtilities, theme }) => { + matchUtilities( + { + scale(value: string) { + return { + transform: `scale(${value}, ${value})`, + }; + }, + "scale-x"(value: string) { + return { + transform: `scaleX(${value})`, + }; + }, + "scale-y"(value: string) { + return { + transform: `scaleY(${value})`, + }; + }, + }, + { + values: theme("scale"), + supportsNegativeValues: true, + } + ); +}; diff --git a/src/plugin/native/skew.ts b/src/plugin/native/skew.ts new file mode 100644 index 0000000..2549990 --- /dev/null +++ b/src/plugin/native/skew.ts @@ -0,0 +1,22 @@ +import { CustomPluginFunction } from "./types"; + +export const skew: CustomPluginFunction = ({ matchUtilities, theme }) => { + matchUtilities( + { + "skew-x"(value: string) { + return { + transform: `skewX(${value})`, + }; + }, + "skew-y"(value: string) { + return { + transform: `skewY(${value})`, + }; + }, + }, + { + values: theme("skew"), + supportsNegativeValues: true, + } + ); +}; diff --git a/src/plugin/native/translate.ts b/src/plugin/native/translate.ts new file mode 100644 index 0000000..47933ef --- /dev/null +++ b/src/plugin/native/translate.ts @@ -0,0 +1,27 @@ +import { CustomPluginFunction } from "./types"; + +export const translate: CustomPluginFunction = ({ matchUtilities, theme }) => { + matchUtilities( + { + translate(value: string) { + return { + transform: `translate(${value}, ${value})`, + }; + }, + "translate-x"(value: string) { + return { + transform: `translate(${value})`, + }; + }, + "translate-y"(value: string) { + return { + transform: `translate(0, ${value})`, + }; + }, + }, + { + values: theme("translate"), + supportsNegativeValues: true, + } + ); +}; diff --git a/src/use-tailwind.native.ts b/src/use-tailwind.native.ts index 13cc00c..c4433cc 100644 --- a/src/use-tailwind.native.ts +++ b/src/use-tailwind.native.ts @@ -56,15 +56,21 @@ export function useTailwind

({ siblingClassName = "" } = {}) { return (className = "") => { let tailwindStyles = {} as P; + const transforms: ViewStyle["transform"] = []; for (const name of `${siblingClassName} ${className}`.trim().split(" ")) { const selector = normaliseSelector(name); if (styles[selector]) { + const { transform, ...rest } = styles[selector]; tailwindStyles = { ...tailwindStyles, - ...styles[selector], + ...rest, }; + + if (transform) { + transforms.push(...transform); + } } const rules = mediaRules[selector]; @@ -84,15 +90,26 @@ export function useTailwind

({ siblingClassName = "" } = {}) { "prefers-color-scheme": colorScheme, }); + const { transform, ...rest } = styles[`${selector}.${index}`]; + if (isMatch) { tailwindStyles = { ...tailwindStyles, - ...styles[`${selector}.${index}`], + ...rest, }; } + + if (transform) { + transforms.push(...transform); + } } } + if (transforms.length > 0) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (tailwindStyles as any).transform = transforms; + } + return Platform.OS === "web" ? StyleSheet.flatten(tailwindStyles) // RNW <=0.17 still uses ReactNativePropRegistry : tailwindStyles;