From f5c15ca468ea74e3560104228ea63e1a99231329 Mon Sep 17 00:00:00 2001
From: mauroerta
Date: Sun, 29 May 2022 22:47:41 +0200
Subject: [PATCH 1/4] BREAKING CHANGE: #86
use `useSyncExternalStore` to sync morfeo with the React render.
Removed `MorfeoProvider` / `MorfeoContext` and introduced `useMorfeo`
Closes #86
---
devtool/src/devtool/index.tsx | 8 +-
docs/docs/Packages/hooks.mdx | 91 ++++++++++----
docs/docs/Packages/native.mdx | 4 +-
examples/react/src/index.tsx | 6 +-
packages/cli/tests/utils/run.ts | 6 -
packages/hooks/README.md | 138 ++-------------------
packages/hooks/src/MorfeoContext.tsx | 4 -
packages/hooks/src/MorfeoProvider.tsx | 20 ---
packages/hooks/src/index.ts | 3 +-
packages/hooks/src/useCurrentTheme.ts | 20 +--
packages/hooks/src/useMorfeo.ts | 17 +++
packages/hooks/src/useProps.ts | 4 +-
packages/hooks/src/useStyles.ts | 8 +-
packages/hooks/src/useTheme.ts | 8 +-
packages/hooks/tests/customRenderer.ts | 11 --
packages/hooks/tests/useMorfeo.test.ts | 46 +++++++
packages/hooks/tests/useProps.test.ts | 2 +-
packages/hooks/tests/useStyles.test.ts | 31 +++--
packages/hooks/tests/useTheme.test.ts | 11 +-
packages/react/tests/useClassName.test.tsx | 7 +-
packages/react/tests/useStyles.test.tsx | 5 +-
21 files changed, 184 insertions(+), 266 deletions(-)
delete mode 100644 packages/hooks/src/MorfeoContext.tsx
delete mode 100644 packages/hooks/src/MorfeoProvider.tsx
create mode 100644 packages/hooks/src/useMorfeo.ts
delete mode 100644 packages/hooks/tests/customRenderer.ts
create mode 100644 packages/hooks/tests/useMorfeo.test.ts
diff --git a/devtool/src/devtool/index.tsx b/devtool/src/devtool/index.tsx
index 2f399c55..0b51b0e1 100644
--- a/devtool/src/devtool/index.tsx
+++ b/devtool/src/devtool/index.tsx
@@ -1,6 +1,6 @@
import { createRoot } from 'react-dom/client';
import browser from 'webextension-polyfill';
-import { resetCss, MorfeoProvider } from '@morfeo/react';
+import { resetCss } from '@morfeo/react';
import { getThemeFromAppAndInitMorfeo } from '../_shared/utils';
import { MORFEO_DEVTOOL_PANEL_NAME, ASSETS_PATHS } from '../_shared/constants';
import Devtool from './Devtool';
@@ -19,9 +19,5 @@ const container = document.getElementById('devtool');
if (container) {
const root = createRoot(container);
- root.render(
-
-
- ,
- );
+ root.render();
}
diff --git a/docs/docs/Packages/hooks.mdx b/docs/docs/Packages/hooks.mdx
index 1fd642b0..c084b363 100644
--- a/docs/docs/Packages/hooks.mdx
+++ b/docs/docs/Packages/hooks.mdx
@@ -7,6 +7,10 @@ description: morfeo's hooks package
**@morfeo/hooks** expose a set of hooks to easily use morfeo inside a `react` context.
+:::info React v18
+To properly use Morfeo in a React environment, you need to have a version of `react >= 18`
+:::
+
## Installation
```bash
@@ -17,7 +21,6 @@ npm i @morfeo/hooks
yarn add @morfeo/hooks
```
-- [MorfeoProvider](#morfeo-provider)
- [useTheme](#usetheme)
- [useThemeSlice](#usethemeslice)
- [useThemeValue](#usethemevalue)
@@ -27,24 +30,9 @@ yarn add @morfeo/hooks
Advanced
+- [useMorfeo](#useMorfeo)
- [useProps](#useprops)
-## Morfeo Provider
-
-To sync morfeo with react you have to first of all wrap you app with the `MorfeoProvider`:
-
-```tsx
-import { MorfeoProvider } from '@morfeo/hooks';
-
-function App() {
- return (
-
-
-
- );
-}
-```
-
## useTheme
Use this hook to get the current theme and use it inside a components:
@@ -118,9 +106,7 @@ they correspond to `morfeo.getCurrentTheme` and `morfeo.setCurrentTheme` of the
```jsx live
function Button() {
- // highlight-start
const [currentTheme, setCurrentTheme] = useCurrentTheme();
- // highlight-end
const style = useStyle({
componentName: 'Button',
@@ -129,9 +115,7 @@ function Button() {
});
const onClick = () => {
- // highlight-start
setCurrentTheme(currentTheme === 'light' ? 'dark' : 'light');
- // highlight-end
};
return (
@@ -184,14 +168,73 @@ Just like useTheme, **useStyles** and **useStyle** are the equivalent of the [co
but they force a re-render when the theme changes.
:::
-## useProps
+## Advanced
+
+### useMorfeo
+
+This hook is used under the hood in all the others hooks, you'll probably never need to use it directly.
+It returns the same `morfeo instance` that you'll get from the core API, but it's reactive, to understand
+the difference just look at these 2 examples:
+
+By using `useMorfeo` the component is subscribed to theme changes, which means that if the theme changes the component
+will be re-rendered:
+
+```tsx live
+function App() {
+ const morfeo = useMorfeo();
+
+ const onClick = () => {
+ morfeo.setCurrentTheme(
+ morfeo.getCurrentTheme() === 'light' ? 'dark' : 'light',
+ );
+ };
+
+ return (
+
+ The current theme is: {morfeo.getCurrentTheme()}
+
+
+
+ );
+}
+```
+
+If instead we use directly the `morfeo` instance from the core-api, the component will not re-render when the theme changes:
+
+```tsx live
+function App() {
+ const onClick = () => {
+ morfeo.setCurrentTheme(
+ morfeo.getCurrentTheme() === 'light' ? 'dark' : 'light',
+ );
+ };
+
+ return (
+
+ The current theme is: {morfeo.getCurrentTheme()}
+
+
+
+ );
+}
+```
+
+### useProps
Use it to get the default props of a components, a common use is to merge the defaut props with the current props:
-```jsx
+```jsx live
function MyButton(props) {
const defaultProps = useProps('Button', 'primary');
+ const className = useClassName({
+ componentName: 'Button',
+ variant: 'primary',
+ });
- return ;
+ return (
+
+ );
}
```
diff --git a/docs/docs/Packages/native.mdx b/docs/docs/Packages/native.mdx
index 42f3d24c..3860605e 100644
--- a/docs/docs/Packages/native.mdx
+++ b/docs/docs/Packages/native.mdx
@@ -5,7 +5,7 @@ title: native
description: morfeo's native package
---
-@morfeo/native package is brings to `React Native` the morfeo's eco system
+@morfeo/native package brings to `React Native` the morfeo's ecosystem
## Installation
@@ -23,7 +23,7 @@ yarn add @morfeo/native
## Usage
-Just like @morfeo/react, the API of this package is the same as [@morfeo/hooks](./hooks.mdx), the main differences between `@morfeo/react` and `@morfeo/native` are related to how the parsers converts style objects to valid style for React Native, for example in @morfeo/native there you cannot use any pseudo element/class and shadows output is different (`shadowOffset`, `shadowColor`, `shadowOpacity` and `shadowRadius` instead of `boxShadow`)
+Just like @morfeo/react, the API of this package is the same as [@morfeo/hooks](./hooks.mdx), the main differences between `@morfeo/react` and `@morfeo/native` are related to how the parsers converts style objects to valid style for React Native, for example in @morfeo/native you cannot use any pseudo element/class, and also, shadows output is different (`shadowOffset`, `shadowColor`, `shadowOpacity` and `shadowRadius` instead of `boxShadow`)
```tsx
import { View, ViewProps } from 'react-native';
diff --git a/examples/react/src/index.tsx b/examples/react/src/index.tsx
index 9dd775f2..897704f0 100644
--- a/examples/react/src/index.tsx
+++ b/examples/react/src/index.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import { initPreset } from '@morfeo/preset-default';
-import { morfeo, resetCss, loadFont, MorfeoProvider } from '@morfeo/react';
+import { morfeo, resetCss, loadFont } from '@morfeo/react';
import { enableMorfeoDevTool } from '@morfeo/dev-tools';
import App from './App';
import reportWebVitals from './reportWebVitals';
@@ -48,9 +48,7 @@ if (container) {
const root = createRoot(container);
root.render(
-
-
-
+ ,
);
}
diff --git a/packages/cli/tests/utils/run.ts b/packages/cli/tests/utils/run.ts
index e8c3904c..355b2324 100644
--- a/packages/cli/tests/utils/run.ts
+++ b/packages/cli/tests/utils/run.ts
@@ -2,9 +2,6 @@ import { cli } from 'cli-ux';
import { morfeoCLI } from '../../src/commands';
export function run(...args: string[]) {
- const _log = console.log;
- const _error = console.error;
- const _info = cli.info;
const stdout: any[] = [];
const stderr: any[] = [];
@@ -12,21 +9,18 @@ export function run(...args: string[]) {
if (typeof message === 'string') {
stdout.push(message);
}
- return _info(message);
};
console.log = (message: any) => {
if (typeof message === 'string') {
stdout.push(message);
}
- return _log(message);
};
console.error = (message: any) => {
if (typeof message === 'string') {
stderr.push(message);
}
- return _error(message);
};
morfeoCLI(args);
diff --git a/packages/hooks/README.md b/packages/hooks/README.md
index e0618695..202d1b6e 100644
--- a/packages/hooks/README.md
+++ b/packages/hooks/README.md
@@ -12,142 +12,20 @@
**@morfeo/hooks** expose a set of hooks to easily use morfeo inside a `react` context.
+> **React v18**
+>
+> To properly use Morfeo in a React environment, you need to have a version of `react >= 18`
+
## Installation
```bash
# npm
-npm i @morfeo/react
+npm i @morfeo/hooks
# yarn
-yarn add @morfeo/react
-```
-
-- [MorfeoProvider](#morfeo-provider)
-- [useTheme](#usetheme)
- - [useThemeSlice](#usethemeslice)
- - [useThemeValue](#usethemevalue)
-- [useStyles](#usestyles)
- - [useStyle](#usestyle)
-
-Advanced
-
-- [useProps](#useprops)
-
-## Morfeo Provider
-
-To sync morfeo with react you have to first of all wrap you app with the `MorfeoProvider`:
-
-```tsx
-import { MorfeoProvider } from '@morfeo/hooks';
-
-function App() {
- return (
-
-
-
- );
-}
+yarn add @morfeo/hooks
```
-## useTheme
-
-Use this hook to get the current theme and use it inside a components:
-
-```jsx
-const MyComponent: React.FC = () => {
- const theme = useTheme();
-
- return (
-
-
My primary color is: {theme.colors.primary}
-
My xxl space is: {theme.spaces.xxl}
-
- );
-};
-```
-
-> If you already know the [core API](./core) useTheme is the equivalent of `morfeo.getTheme()`, the main difference is that useTheme react
-> to theme changes and force a re-render of the component.
-
-Most of the time you don't need all theme, but just a slice or single value, in this cases [useThemeSlice](#useThemeSlice) and [useThemeValue](#useThemeValue) can will give you only the part of the theme you want:
-
-### useThemeSlice
-
-```jsx
-const MyComponent: React.FC = () => {
- const colors = useThemeSlice('colors');
-
- return (
-