diff --git a/apps/web-sandbox/src/components/Box.tsx b/apps/web-sandbox/src/components/Box.tsx index e12bfce3..dd7e31cf 100644 --- a/apps/web-sandbox/src/components/Box.tsx +++ b/apps/web-sandbox/src/components/Box.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from './MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Card.tsx b/apps/web-sandbox/src/components/Card.tsx index 0de6904c..bbeb9e24 100644 --- a/apps/web-sandbox/src/components/Card.tsx +++ b/apps/web-sandbox/src/components/Card.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from './MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Forms/Button.tsx b/apps/web-sandbox/src/components/Forms/Button.tsx index 400cfe25..dd7a502a 100644 --- a/apps/web-sandbox/src/components/Forms/Button.tsx +++ b/apps/web-sandbox/src/components/Forms/Button.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Forms/Input.tsx b/apps/web-sandbox/src/components/Forms/Input.tsx index f7ac9e28..bf560e90 100644 --- a/apps/web-sandbox/src/components/Forms/Input.tsx +++ b/apps/web-sandbox/src/components/Forms/Input.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Forms/InputFeedback.tsx b/apps/web-sandbox/src/components/Forms/InputFeedback.tsx index 82e0e61c..f957c416 100644 --- a/apps/web-sandbox/src/components/Forms/InputFeedback.tsx +++ b/apps/web-sandbox/src/components/Forms/InputFeedback.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Forms/Label.tsx b/apps/web-sandbox/src/components/Forms/Label.tsx index b08b7d7b..3c3cd410 100644 --- a/apps/web-sandbox/src/components/Forms/Label.tsx +++ b/apps/web-sandbox/src/components/Forms/Label.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Forms/index.ts b/apps/web-sandbox/src/components/Forms/index.ts index d3104090..6a6037f8 100644 --- a/apps/web-sandbox/src/components/Forms/index.ts +++ b/apps/web-sandbox/src/components/Forms/index.ts @@ -1,4 +1,4 @@ -export * from './Button'; export * from './Input'; export * from './Label'; +export * from './Button'; export * from './InputFeedback'; diff --git a/apps/web-sandbox/src/components/Grid/Container.tsx b/apps/web-sandbox/src/components/Grid/Container.tsx index 9cf9ed43..4cad2d4c 100644 --- a/apps/web-sandbox/src/components/Grid/Container.tsx +++ b/apps/web-sandbox/src/components/Grid/Container.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Grid/Grid.tsx b/apps/web-sandbox/src/components/Grid/Grid.tsx index 320bac85..a3e20c3b 100644 --- a/apps/web-sandbox/src/components/Grid/Grid.tsx +++ b/apps/web-sandbox/src/components/Grid/Grid.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Grid/index.ts b/apps/web-sandbox/src/components/Grid/index.ts index c95bf3be..4d54484f 100644 --- a/apps/web-sandbox/src/components/Grid/index.ts +++ b/apps/web-sandbox/src/components/Grid/index.ts @@ -1,2 +1,2 @@ -export * from './Container'; export * from './Grid'; +export * from './Container'; diff --git a/apps/web-sandbox/src/components/Hr.tsx b/apps/web-sandbox/src/components/Hr.tsx index 0b0891fe..e6e2e4bd 100644 --- a/apps/web-sandbox/src/components/Hr.tsx +++ b/apps/web-sandbox/src/components/Hr.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from './MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/List.tsx b/apps/web-sandbox/src/components/List.tsx index b0cfbec8..314ac743 100644 --- a/apps/web-sandbox/src/components/List.tsx +++ b/apps/web-sandbox/src/components/List.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from './MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/MorfeoComponent.tsx b/apps/web-sandbox/src/components/MorfeoComponent.tsx deleted file mode 100644 index 20d392af..00000000 --- a/apps/web-sandbox/src/components/MorfeoComponent.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { - Style, - Variant, - useTheme, - Component, - component, - useClassName, -} from '@morfeo/react'; -import React, { ReactNode, HTMLProps, useMemo } from 'react'; - -export type MorfeoComponentProps = { - style?: Style; - variant?: Variant; - children?: ReactNode; - componentName: T; -} & Omit, 'style'>; - -export function MorfeoComponent({ - style, - variant, - children, - componentName, - ...props -}: MorfeoComponentProps) { - const { - tag = 'div', - props: componentProps, - style: componentStyle, - } = component(componentName, variant).get(); - - const theme = useTheme(); - - const className = useClassName({ ...componentStyle, ...style }); - - const render = useMemo(() => { - if (tag && theme) { - return React.createElement( - tag, - { - ...componentProps, - ...props, - className: props.className - ? [className, props.className].join(' ') - : className, - }, - children, - ); - } - - return <>; - }, [children, className, componentProps, props, tag, theme]); - - return render; -} diff --git a/apps/web-sandbox/src/components/Templates/Footer.tsx b/apps/web-sandbox/src/components/Templates/Footer.tsx index 134f2d41..c10640d1 100644 --- a/apps/web-sandbox/src/components/Templates/Footer.tsx +++ b/apps/web-sandbox/src/components/Templates/Footer.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Templates/Header.tsx b/apps/web-sandbox/src/components/Templates/Header.tsx index 58a506e9..8d958f57 100644 --- a/apps/web-sandbox/src/components/Templates/Header.tsx +++ b/apps/web-sandbox/src/components/Templates/Header.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Templates/Main.tsx b/apps/web-sandbox/src/components/Templates/Main.tsx index c9a0a47c..39d55ab4 100644 --- a/apps/web-sandbox/src/components/Templates/Main.tsx +++ b/apps/web-sandbox/src/components/Templates/Main.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Templates/Page.tsx b/apps/web-sandbox/src/components/Templates/Page.tsx index 6e852aa1..00629380 100644 --- a/apps/web-sandbox/src/components/Templates/Page.tsx +++ b/apps/web-sandbox/src/components/Templates/Page.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Templates/Section.tsx b/apps/web-sandbox/src/components/Templates/Section.tsx index 41fa0e32..3fb985dd 100644 --- a/apps/web-sandbox/src/components/Templates/Section.tsx +++ b/apps/web-sandbox/src/components/Templates/Section.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from '../MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/Templates/index.ts b/apps/web-sandbox/src/components/Templates/index.ts index 1effe0c1..637ae22f 100644 --- a/apps/web-sandbox/src/components/Templates/index.ts +++ b/apps/web-sandbox/src/components/Templates/index.ts @@ -1,5 +1,5 @@ -export * from './Footer'; -export * from './Header'; export * from './Main'; export * from './Page'; +export * from './Footer'; +export * from './Header'; export * from './Section'; diff --git a/apps/web-sandbox/src/components/Typography.tsx b/apps/web-sandbox/src/components/Typography.tsx index 8148a525..e1a68c82 100644 --- a/apps/web-sandbox/src/components/Typography.tsx +++ b/apps/web-sandbox/src/components/Typography.tsx @@ -1,4 +1,4 @@ -import { MorfeoComponent, MorfeoComponentProps } from './MorfeoComponent'; +import { MorfeoComponent, MorfeoComponentProps } from '@morfeo/react'; type Props = Omit, 'componentName'>; diff --git a/apps/web-sandbox/src/components/index.ts b/apps/web-sandbox/src/components/index.ts index de343c97..ac64d9a0 100644 --- a/apps/web-sandbox/src/components/index.ts +++ b/apps/web-sandbox/src/components/index.ts @@ -1,8 +1,8 @@ -export * from './Templates'; -export * from './Grid'; -export * from './Forms'; +export * from './Hr'; export * from './Box'; -export * from './Typography'; +export * from './Grid'; export * from './Card'; -export * from './Hr'; export * from './List'; +export * from './Forms'; +export * from './Templates'; +export * from './Typography'; diff --git a/packages/react/src/MorfeoComponent.tsx b/packages/react/src/MorfeoComponent.tsx new file mode 100644 index 00000000..9db32eb5 --- /dev/null +++ b/packages/react/src/MorfeoComponent.tsx @@ -0,0 +1,39 @@ +import { ReactNode, HTMLProps, createElement } from 'react'; +import { Style, Variant, Component, component } from '@morfeo/web'; +import { useClassName } from './useClassName'; + +export type MorfeoComponentProps = { + style?: Style; + variant?: Variant; + children?: ReactNode; + componentName: T; +} & Omit, 'style'>; + +export function MorfeoComponent({ + style, + variant, + children, + componentName, + ...props +}: MorfeoComponentProps) { + const { + tag = 'div', + props: componentProps, + style: componentStyle, + } = component(componentName, variant).get(); + + const baseClassName = useClassName({ ...componentStyle, ...style }); + const className = props.className + ? `${baseClassName} ${props.className}` + : baseClassName; + + return createElement( + tag, + { + ...componentProps, + ...props, + className, + }, + children, + ); +} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index f8736140..94a8e885 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -1,5 +1,6 @@ export * from '@morfeo/web'; export * from '@morfeo/hooks'; export * from './useClassName'; +export * from './MorfeoComponent'; export { useStyle, useStyles } from './hooks'; diff --git a/packages/react/tests/MorfeoComponent.test.tsx b/packages/react/tests/MorfeoComponent.test.tsx new file mode 100644 index 00000000..6cd8a2d9 --- /dev/null +++ b/packages/react/tests/MorfeoComponent.test.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { morfeo } from '@morfeo/web'; +import { render } from '@testing-library/react'; +import { MorfeoComponent } from '../src'; + +const theme = { + colors: { + primary: 'black', + secondary: 'white', + }, + components: { + Box: { + style: {}, + variants: {}, + }, + Button: { + tag: 'button', + style: { + bg: 'secondary', + }, + variants: { + primary: { + style: { bg: 'primary' }, + }, + }, + props: { + type: 'button', + }, + }, + }, +} as any; + +morfeo.setTheme('default', theme); + +describe('MorfeoComponent', () => { + beforeAll(() => { + morfeo.useTheme('default'); + }); + + test('should create a button with initial style and props based on the theme', async () => { + const { getByTestId } = render( + , + ); + const button = getByTestId('button'); + + expect(button).toHaveStyle( + `background-color: ${morfeo.getTheme()['colors']['secondary']}`, + ); + expect(button).toHaveAttribute('type', 'button'); + }); + + test('should handle the variant', async () => { + const { getByTestId } = render( + , + ); + const button = getByTestId('button-primary'); + + expect(button).toHaveStyle( + `background-color: ${morfeo.getTheme()['colors']['primary']}`, + ); + }); + + test('should create a div if the tag is not specified', async () => { + const { getByTestId } = render( + , + ); + const box = getByTestId('box'); + + expect(box.tagName).toBe('DIV'); + }); + + test('should append the additional class if specified', async () => { + const { getByTestId } = render( + , + ); + const box = getByTestId('box'); + + expect(box.classList).toHaveLength(2); + expect(box.classList).toContain('additional-class'); + }); +});