From 09c86983ed0c73a99b01d69a6eaa207f43e2fb2b Mon Sep 17 00:00:00 2001 From: Mark Lawlor Date: Wed, 11 May 2022 15:31:55 +1000 Subject: [PATCH] feat: add component --- __tests__/custom-tailwindcss/component.ts | 12 ++++++++++++ src/context.ts | 12 ++++++++++++ src/styled.tsx | 17 +++++++++++++++-- src/tailwind/native/component.ts | 7 +++++++ src/tailwind/native/index.ts | 2 ++ src/use-tailwind.native.ts | 10 +++++++++- 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 __tests__/custom-tailwindcss/component.ts create mode 100644 src/tailwind/native/component.ts diff --git a/__tests__/custom-tailwindcss/component.ts b/__tests__/custom-tailwindcss/component.ts new file mode 100644 index 0000000..4682036 --- /dev/null +++ b/__tests__/custom-tailwindcss/component.ts @@ -0,0 +1,12 @@ +import { tailwindRunner } from "../tailwindcss/runner"; + +tailwindRunner("Custom Tailwind CSS - component", [ + [ + "component-hover:text-green-500", + { + "component-hover_text-green-500": [ + { atRules: [["component", "hover"]], color: "#22c55e" }, + ], + }, + ], +]); diff --git a/src/context.ts b/src/context.ts index 0b11b2e..61ac400 100644 --- a/src/context.ts +++ b/src/context.ts @@ -37,3 +37,15 @@ export const TailwindContext = createContext({ orientation: "portrait", preview: false, }); + +export interface ComponentContext { + hover: boolean; + focus: boolean; + active: boolean; +} + +export const ComponentContext = createContext({ + hover: false, + focus: false, + active: false, +}); diff --git a/src/styled.tsx b/src/styled.tsx index 9acd85c..3084193 100644 --- a/src/styled.tsx +++ b/src/styled.tsx @@ -11,6 +11,7 @@ import { useTailwind } from "./use-tailwind"; import { ChildClassNameSymbol } from "./utils/child-styles"; import { isFragment } from "react-is"; import { useInteraction } from "./use-interaction"; +import { ComponentContext } from "./context"; type StyledProps

= PropsWithChildren< P & { @@ -38,13 +39,15 @@ export function styled

( }: StyledProps

) { const { hover, focus, active, ...handlers } = useInteraction(props); + const classes = tw ?? className ?? ""; + const tailwindStyles = useTailwind({ nthChild, hover, focus, active, [ChildClassNameSymbol]: inheritedClassName, - })(tw ?? className); + })(classes); const style = styleProperty ? [tailwindStyles, styleProperty] @@ -64,12 +67,22 @@ export function styled

( }); } - return createElement(Component, { + const element = createElement(Component, { ...props, ...handlers, style, children, } as unknown as P); + + return !classes.includes("container") + ? element + : createElement>( + ComponentContext.Provider, + { + children: element, + value: { hover, focus, active }, + } + ); } if (typeof Component !== "string") { diff --git a/src/tailwind/native/component.ts b/src/tailwind/native/component.ts new file mode 100644 index 0000000..5bd74c7 --- /dev/null +++ b/src/tailwind/native/component.ts @@ -0,0 +1,7 @@ +import { CustomPluginFunction } from "./types"; + +export const component: CustomPluginFunction = ({ addVariant }) => { + addVariant("component-hover", "@component hover"); + addVariant("component-focus", "@component focus"); + addVariant("component-active", "@component active"); +}; diff --git a/src/tailwind/native/index.ts b/src/tailwind/native/index.ts index fb2a916..551fe03 100644 --- a/src/tailwind/native/index.ts +++ b/src/tailwind/native/index.ts @@ -5,6 +5,7 @@ import { } from "tailwindcss/tailwind-config"; import { StyleError } from "../../types/common"; import { boxShadow } from "./box-shadow"; +import { component } from "./component"; import { divide } from "./divide"; import { elevation } from "./elevation"; import { fontSize } from "./font-size"; @@ -48,6 +49,7 @@ export const nativePlugin = plugin.withOptions( skew(helpers, notSupported); boxShadow(helpers, notSupported); pseudoClasses(helpers, notSupported); + component(helpers, notSupported); }; }, function ({ rem = 16 } = {}) { diff --git a/src/use-tailwind.native.ts b/src/use-tailwind.native.ts index ee7736c..8d4b610 100644 --- a/src/use-tailwind.native.ts +++ b/src/use-tailwind.native.ts @@ -9,7 +9,7 @@ import { /* eslint-disable @typescript-eslint/no-explicit-any */ import { match } from "css-mediaquery"; import { normaliseSelector } from "./shared/selector"; -import { TailwindContext } from "./context"; +import { ComponentContext, TailwindContext } from "./context"; import { RWNCssStyle, UseTailwindCallback, @@ -48,6 +48,8 @@ export function useTailwind

({ const { platform, styles, media, width, height, orientation, colorScheme } = useContext(TailwindContext); + const componentInteraction = useContext(ComponentContext); + // useState ensure this 'resets' every render let [nthChild] = useState(initialNthChild); @@ -99,6 +101,12 @@ export function useTailwind

({ return focus; } else if (rule === "pseudo-class" && params === "active") { return active; + } else if (rule === "component" && params === "hover") { + return componentInteraction.hover; + } else if (rule === "component" && params === "focus") { + return componentInteraction.focus; + } else if (rule === "component" && params === "active") { + return componentInteraction.active; } else if (rule === "media") { return match(params, { "aspect-ratio": width / height,