diff --git a/packages/pigment-react/package.json b/packages/pigment-react/package.json index fef627f124a6ba..56c0d0d2773044 100644 --- a/packages/pigment-react/package.json +++ b/packages/pigment-react/package.json @@ -132,6 +132,12 @@ }, "./exports/createUseThemeProps": { "default": "./exports/createUseThemeProps.js" + }, + "./Box": { + "types": "./build/Box.d.ts", + "import": "./build/Box.mjs", + "require": "./build/Box.js", + "default": "./build/Box.js" } }, "nx": { diff --git a/packages/pigment-react/src/Box.d.ts b/packages/pigment-react/src/Box.d.ts new file mode 100644 index 00000000000000..e627538de4c6ee --- /dev/null +++ b/packages/pigment-react/src/Box.d.ts @@ -0,0 +1,6 @@ +import type { PolymorphicComponent } from './base'; +import type { SxProp } from './sx'; + +declare const Box: PolymorphicComponent; + +export { Box }; diff --git a/packages/pigment-react/src/Box.jsx b/packages/pigment-react/src/Box.jsx new file mode 100644 index 00000000000000..c1c4325980125c --- /dev/null +++ b/packages/pigment-react/src/Box.jsx @@ -0,0 +1,27 @@ +import * as React from 'react'; + +// eslint-disable-next-line react/prop-types +export const Box = React.forwardRef(({ as = 'div', sx, className, style, ...rest }, ref) => { + const Component = as; + // eslint-disable-next-line react/prop-types + const sxClass = typeof sx === 'string' ? sx : sx?.className; + const classes = [className, sxClass].filter(Boolean).join(' '); + // eslint-disable-next-line react/prop-types + const sxVars = sx && typeof sx !== 'string' ? sx?.vars : {}; + const varStyles = {}; + + if (sxVars) { + Object.entries(sxVars).forEach(([cssVariable, [value, isUnitLess]]) => { + if (typeof value === 'string' || isUnitLess) { + varStyles[`--${cssVariable}`] = value; + } else { + varStyles[`--${cssVariable}`] = `${value}px`; + } + }); + } + const styles = { + ...style, + ...varStyles, + }; + return ; +}); diff --git a/packages/pigment-react/src/base.d.ts b/packages/pigment-react/src/base.d.ts index 0aae8b1e5adf86..3a93c988de082e 100644 --- a/packages/pigment-react/src/base.d.ts +++ b/packages/pigment-react/src/base.d.ts @@ -35,3 +35,31 @@ export type CSSObjectNoCallback = | CSSPropertiesMultiValue | CSSPseudosNoCallback | CSSOthersObjectNoCallback; + +export type BaseDefaultProps = object; + +export type NoInfer = [T][T extends any ? 0 : never]; +type FastOmit = { + [K in keyof T as K extends U ? never : K]: T[K]; +}; + +export type Substitute = FastOmit & B; + +export type PolymorphicComponentProps< + SxProp, + BaseProps extends object, + AsTarget extends React.ElementType | undefined, + AsTargetProps extends object = AsTarget extends React.ElementType + ? React.ComponentPropsWithRef + : BaseDefaultProps, +> = NoInfer, 'as'>> & { + as?: AsTarget; + sx?: SxProp; +}; + +export interface PolymorphicComponent + extends React.ForwardRefExoticComponent { + ( + props: PolymorphicComponentProps, + ): JSX.Element; +} diff --git a/packages/pigment-react/src/processors/sx.ts b/packages/pigment-react/src/processors/sx.ts index 86cf7a58d72ffa..b0293aa8c58f93 100644 --- a/packages/pigment-react/src/processors/sx.ts +++ b/packages/pigment-react/src/processors/sx.ts @@ -94,7 +94,7 @@ export class SxProcessor extends BaseProcessor { doRuntimeReplacement() { const t = this.astService; - // do not replace if sx prop is not on zero-runtime styled component + // do not replace if sx prop is not a Pigment styled component if (!this.elementClassName) { return; } diff --git a/packages/pigment-react/src/styled.d.ts b/packages/pigment-react/src/styled.d.ts index b518a903161460..d0fd15efb7351a 100644 --- a/packages/pigment-react/src/styled.d.ts +++ b/packages/pigment-react/src/styled.d.ts @@ -1,19 +1,11 @@ import type * as React from 'react'; -import type { CSSObject } from './base'; +import type { BaseDefaultProps, CSSObject, PolymorphicComponent, Substitute } from './base'; import type { ThemeArgs } from './theme'; import type { SxProp } from './sx'; import { Primitve } from './keyframes'; type Falsy = false | 0 | '' | null | undefined; -type BaseDefaultProps = object; - -export type NoInfer = [T][T extends any ? 0 : never]; -type FastOmit = { - [K in keyof T as K extends U ? never : K]: T[K]; -}; -export type Substitute = FastOmit & B; - export interface StyledVariants { props: Partial | ((props: Props) => boolean); style: CSSObject; @@ -31,26 +23,8 @@ export type StyledArgument = | StyledCssArgument | StyledCallback; -export type PolymorphicComponentProps< - BaseProps extends object, - AsTarget extends React.ElementType | undefined, - AsTargetProps extends object = AsTarget extends React.ElementType - ? React.ComponentPropsWithRef - : BaseDefaultProps, -> = NoInfer, 'as'>> & { - as?: AsTarget; - sx?: SxProp; -}; - -export interface PolymorphicComponent - extends React.ForwardRefExoticComponent { - ( - props: PolymorphicComponentProps, - ): JSX.Element; -} - export interface StyledComponent - extends PolymorphicComponent { + extends PolymorphicComponent { defaultProps?: Partial | undefined; toString: () => string; } diff --git a/packages/pigment-react/tests/Box.spec.tsx b/packages/pigment-react/tests/Box.spec.tsx new file mode 100644 index 00000000000000..8fdada9e9c48e1 --- /dev/null +++ b/packages/pigment-react/tests/Box.spec.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { Box } from '@pigment-css/react/Box'; + +export function App() { + return ( + + ({ color: 'primary' })}> + Hello{' '} + + Link + + + + ); +} diff --git a/packages/pigment-react/tsup.config.ts b/packages/pigment-react/tsup.config.ts index 635ac6fa9b2f64..da480fc714f4ff 100644 --- a/packages/pigment-react/tsup.config.ts +++ b/packages/pigment-react/tsup.config.ts @@ -17,7 +17,7 @@ const baseConfig: Options = { export default defineConfig([ { ...baseConfig, - entry: ['./src/index.ts', './src/theme.ts'], + entry: ['./src/index.ts', './src/theme.ts', './src/Box.jsx'], }, { ...baseConfig,