Repository: microsoft/griffel
Pull request #217 (2022-09-20 12:52:51)

docs: add pages about Atomic CSS, build time optimisations
~~Requires #215, #216.~~

- Updates a page about Atomic CSS with real content
- Adds pages about ahead-of-time compilation
- Adds pages about CSS extraction

github-actions[bot]: ## 📊 Bundle size report

| Package & Exports                                                                                                            |    Baseline (minified/GZIP) |                          PR |                                                                                                                                                                                                   Change |
| :--------------------------------------------------------------------------------------------------------------------------- | --------------------------: | --------------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <samp>core</samp> <br /> <abbr title='bundle-size/makeStylesRuntime.fixture.js'>makeStyles + mergeClasses (runtime)</abbr>   | `20.488 kB`<br />`7.628 kB` | `21.354 kB`<br />`7.966 kB` | `866 B` <img aria-hidden="true" src="https://microsoft.github.io/monosize/images/increase.png" /><br />`338 B` <img aria-hidden="true" src="https://microsoft.github.io/monosize/images/increase.png" /> |
| <samp>react</samp> <br /> <abbr title='bundle-size/makeStaticStyles-runtime.fixture.js'>makeStaticStyles (runtime)</abbr>    |  `8.982 kB`<br />`3.908 kB` |  `9.848 kB`<br />`4.243 kB` | `866 B` <img aria-hidden="true" src="https://microsoft.github.io/monosize/images/increase.png" /><br />`335 B` <img aria-hidden="true" src="https://microsoft.github.io/monosize/images/increase.png" /> |
| <samp>react</samp> <br /> <abbr title='bundle-size/makeStyles-runtime.fixture.js'>makeStyles + mergeClasses (runtime)</abbr> | `22.248 kB`<br />`8.337 kB` | `23.116 kB`<br />`8.672 kB` | `868 B` <img aria-hidden="true" src="https://microsoft.github.io/monosize/images/increase.png" /><br />`335 B` <img aria-hidden="true" src="https://microsoft.github.io/monosize/images/increase.png" /> |

<details>
<summary>Unchanged fixtures</summary>

| Package & Exports                                                                                                      |       Size (minified/GZIP) |
| ---------------------------------------------------------------------------------------------------------------------- | -------------------------: |
| <samp>core</samp> <br /> <abbr title='bundle-size/makeStyles.fixture.js'>makeStyles + mergeClasses (build time)</abbr> |    `1.834 kB`<br />`872 B` |
| <samp>react</samp> <br /> <abbr title='bundle-size/__css.fixture.js'>\_\_css + mergeClasses (build time)</abbr>        |    `1.871 kB`<br />`869 B` |
| <samp>react</samp> <br /> <abbr title='bundle-size/__styles.fixture.js'>\_\_styles + mergeClasses (build time)</abbr>  | `3.569 kB`<br />`1.607 kB` |

</details>
<sub>🤖 This report was generated against <a href='https://github.com/microsoft/griffel/commit/9228140c805f662b6c12df4c3f6e45bf9378b4ac'>9228140c805f662b6c12df4c3f6e45bf9378b4ac</a></sub>

<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/.yarn/patches/mdx-mermaid-npm-1.3.2-e8a6432fce.patch b/.yarn/patches/mdx-mermaid-npm-1.3.2-e8a6432fce.patch
new file mode 100644
index 0000000..af387c0
--- /dev/null
+++ b/.yarn/patches/mdx-mermaid-npm-1.3.2-e8a6432fce.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/Mermaid.mjs b/lib/Mermaid.mjs
+index 5140cd5e556ede3debb33ae2202f04480b288d2f..204a3f97d590c9a384ed1bdcfcf7b0dc1375c616 100644
+--- a/lib/Mermaid.mjs
++++ b/lib/Mermaid.mjs
+@@ -45,7 +45,7 @@ const Mermaid = ({ chart, config: configSrc }) => {
+     if (typeof window === 'undefined') {
+         return React.createElement("div", { className: "mermaid", "data-mermaid-src": chart }, chart);
+     }
+-    const config = useMemo(() => typeof configSrc === 'string' ? JSON.parse(configSrc) : configSrc, [configSrc]);
++    const config = useMemo(() => typeof configSrc === 'string' ? JSON.parse(configSrc) : configSrc || {}, [configSrc]);
+     const html = document.querySelector('html');
+     const [rerender, setRerender] = useState(false);
+     const theme = useMemo(() => getTheme(html, config), [config, rerender]);
diff --git a/apps/benchmark/src/components/Select.tsx b/apps/benchmark/src/components/Select.tsx
index 84b1527..523f265 100644
--- a/apps/benchmark/src/components/Select.tsx
+++ b/apps/benchmark/src/components/Select.tsx
@@ -1,6 +1,7 @@
 import React from 'react';
 
 interface SelectProps {
+  children: React.ReactNode;
   label: string;
 }
 
diff --git a/apps/benchmark/src/implementations/types.ts b/apps/benchmark/src/implementations/types.ts
index 5733752..61e8f41 100644
--- a/apps/benchmark/src/implementations/types.ts
+++ b/apps/benchmark/src/implementations/types.ts
@@ -1,3 +1,5 @@
+import React from 'react';
+
 export interface BoxProps {
   color: 0 | 1 | 2 | 3 | 4 | 5;
   fixed: boolean;
@@ -9,5 +11,6 @@ export interface DotProps {
   size: number;
   x: number;
   y: number;
+  children: React.ReactNode;
   color: string;
 }
diff --git a/apps/website/docs/react/ahead-of-time-compilation/_category_.json b/apps/website/docs/react/ahead-of-time-compilation/_category_.json
new file mode 100644
index 0000000..4a3220c
--- /dev/null
+++ b/apps/website/docs/react/ahead-of-time-compilation/_category_.json
@@ -0,0 +1,5 @@
+{
+  "label": "Ahead-of-time compilation",
+  "collapsed": false,
+  "position": 4
+}
diff --git a/apps/website/docs/react/ahead-of-time-compilation/introduction.md b/apps/website/docs/react/ahead-of-time-compilation/introduction.md
new file mode 100644
index 0000000..3859ed0
--- /dev/null
+++ b/apps/website/docs/react/ahead-of-time-compilation/introduction.md
@@ -0,0 +1,14 @@
+---
+sidebar_position: 1
+---
+
+# Introduction
+
+While there is nothing wrong with the associated runtime costs of a CSS-in-JS engine, larger and more complex applications might want to optimize for performance.
+
+Griffel only does the expensive runtime on the first render of the component. This work can be further optimized at build time by pre-computing and transforming styles.
+
+## What to use?
+
+- For library developers, please use [Babel preset](/react/ahead-of-time-compilation/with-babel)
+- For application developers, please use [Webpack loader](/react/ahead-of-time-compilation/with-webpack) (supports Next.js)
diff --git a/apps/website/docs/react/ahead-of-time-compilation/technical-details.md b/apps/website/docs/react/ahead-of-time-compilation/technical-details.md
new file mode 100644
index 0000000..576fc4d
--- /dev/null
+++ b/apps/website/docs/react/ahead-of-time-compilation/technical-details.md
@@ -0,0 +1,146 @@
+---
+sidebar_position: 4
+---
+
+# Technical details
+
+## What is being optimized with AOT (Ahead Of Time) compilation?
+
+:::info
+
+Style resolution only needs to happen on the initial render of a component. Therefore, without build time optimization the performance is comparable with the 2nd and consecutive renders.
+
+It is reasonable to introduce build time optimization if/when it is required.
+
+:::
+
+```jsx
+import { makeStyles } from '@griffel/react';
+
+// 1. Invocation of makeStyles creates a styling hook that will be used inside a component.
+const useStyles = makeStyles({
+  root: { paddingLeft: '1px', display: 'flex' },
+});
+
+function Component() {
+  // 2. The hook call resolves styles which are injected into the document.
+  const classes = useStyles();
+
+  return <div className={classes.root} />;
+}
+```
+
+You can look at the graph below which describes what work is done during style resolution:
+
+```mermaid
+stateDiagram-v2
+    direction LR
+
+    INVOKE_USE_STYLES: useStyles() invocation
+    COMPUTE_RTL_STYLES: Compute RTL styles
+    COMPUTE_CSS_CLASSES: Compute CSS classes
+    COMPUTE_CSS_RULES: Compute CSS rules
+    INSERT_TO_DOM: Insert to DOM
+
+    INVOKE_USE_STYLES --> COMPUTE_RTL_STYLES
+    COMPUTE_RTL_STYLES --> COMPUTE_CSS_CLASSES
+    COMPUTE_CSS_CLASSES --> COMPUTE_CSS_RULES
+    COMPUTE_CSS_RULES --> INSERT_TO_DOM
+
+    note right of INVOKE_USE_STYLES
+     {
+        &nbsp;&nbsp;paddingLeft: '1px',
+        &nbsp;&nbsp;display: 'flex'
+     }
+    end note
+    note right of COMPUTE_RTL_STYLES
+     {
+        &nbsp;&nbsp;paddingLeft: '1px',
+        &nbsp;&nbsp;paddingRight: '1px',
+        &nbsp;&nbsp;display: 'flex'
+      }
+    end note
+    note right of COMPUTE_CSS_CLASSES
+     {
+       &nbsp;&nbsp;paddingLeft: '1px', // .f10xn8zz
+       &nbsp;&nbsp;paddingRight: '1px', // .f136y8j8
+       &nbsp;&nbsp;display: 'flex' // .f22iagw
+     }
+    end note
+    note right of COMPUTE_CSS_RULES
+     .f10xn8zz { padding-left: 1px }
+     .f136y8j8 { padding-right: 1px }
+     .f22iagw { display: flex }
+    end note
+```
+
+:::note
+
+This work only happens once, during first render.
+
+:::
+
+The final result before the CSS rules are inserted into DOM can be compiled ahead of time during build time through the methods described above.
+Once the styles of our simple example are transformed at build time the resulting bundle contains a result similar to what is in our diagram.
+
+The actual runtime code of `makeStyles` is completely stripped from the bundle and replaced with a lightweight function (`__styles`) that simply concatenates the CSS classes and inserts them to DOM.
+
+```jsx
+const useStyles = __styles(
+  {
+    root: {
+      mc9l5x: 'f22iagw',
+      uwmqm3: ['f10xn8zz', 'f136y8j8'],
+    },
+  },
+  {
+    d: ['.f22iagw{display:flex;}', '.f10xn8zz{padding-left:1px;}', '.f136y8j8{padding-right:1px;}'],
+  },
+);
+
+function Component() {
+  const classes = useStyles();
+
+  return <div className={classes.root} />;
+}
+```
+
+## Module evaluation process
+
+Let's consider the following scenario:
+
+```js
+// constants.js
+export const PADDING_TOKEN = '1px';
+```
+
+```js
+// common.js
+export const commonStyles = () => ({
+  display: 'flex',
+  justifyContent: 'center',
+  alignItems: 'center',
+});
+```
+
+```js
+// styles.js
+import { makeStyles } from '@griffel/react';
+import { PADDING_TOKEN } from './constants';
+import { commonStyles } from './common';
+
+const useStyles = makeStyles({
+  root: { paddingLeft: PADDING_TOKEN, ...commonStyles() },
+});
+```
+
+It's perfectly fine, and even recommended to reuse common tokens and create style helpers across an application.
+It's one of the main benefits of using CSS-in-JS.
+
+However, this means that the build time transforms which are described above are not trivial to compute because code needs to be evaluated to know what styles to transform.
+In the example above, in order to transform the `styles.js` file, the code needs to be executed/evaluated by importing the extra modules that it depends on (`constants.js` and `common.js`).
+
+Griffel uses style evaluation from [Linaria](https://linaria.dev/).
+The build-time evaluation happens as a part of the Babel transforms in Griffel. All styles that require evaluation will be batched and done in single evaluation context.
+Linaria's Babel config is separate to any config used by the application.
+Therefore, additional language features may require [extra configuration](/react/ahead-of-time-compilation/with-babel#configuration).
diff --git a/apps/website/docs/react/ahead-of-time-compilation/with-babel.md b/apps/website/docs/react/ahead-of-time-compilation/with-babel.md
new file mode 100644
index 0000000..bff4053
--- /dev/null
+++ b/apps/website/docs/react/ahead-of-time-compilation/with-babel.md
@@ -0,0 +1,41 @@
+---
+sidebar_position: 3
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# With Babel
+
+## Install
+
+<Tabs>
+<TabItem value="yarn" label="Yarn">
+
+```shell
+yarn add --dev @griffel/babel-preset
+```
+
+</TabItem>
+<TabItem value="npm" label="NPM">
+
+```shell
+npm install --save-dev @griffel/babel-preset
+```
+
+</TabItem>
+</Tabs>
+
+## Usage
+
+Modify `.babelrc` to include:
+
+```json
+{
+  "presets": ["@griffel"]
+}
+```
+
+## Configuration
+
+Please check [the README](https://github.com/microsoft/griffel/tree/main/packages/babel-preset) of `@griffel/babel-preset` to check how to configure module evaluation and imports.
diff --git a/apps/website/docs/react/ahead-of-time-compilation/with-webpack.md b/apps/website/docs/react/ahead-of-time-compilation/with-webpack.md
new file mode 100644
index 0000000..2c10965
--- /dev/null
+++ b/apps/website/docs/react/ahead-of-time-compilation/with-webpack.md
@@ -0,0 +1,130 @@
+---
+sidebar_position: 2
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# With Webpack
+
+## Install
+
+<Tabs>
+<TabItem value="yarn" label="Yarn">
+
+```shell
+yarn add --dev @griffel/webpack-loader
+```
+
+</TabItem>
+<TabItem value="npm" label="NPM">
+
+```shell
+npm install --save-dev @griffel/webpack-loader
+```
+
+</TabItem>
+</Tabs>
+
+## Usage
+
+Webpack documentation: [Loaders](https://webpack.js.org/loaders/)
+
+Within your webpack configuration object, you'll need to add the `@griffel/webpack-loader` to the list of modules, like so:
+
+```js
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.(js|jsx)$/,
+        exclude: /node_modules/,
+        use: {
+          loader: '@griffel/webpack-loader',
+        },
+      },
+
+      // If your project uses TypeScript
+      {
+        test: /\.(ts|tsx)$/,
+        exclude: /node_modules/,
+        use: {
+          loader: '@griffel/webpack-loader',
+          options: {
+            babelOptions: {
+              presets: ['@babel/preset-typescript'],
+            },
+          },
+        },
+      },
+    ],
+  },
+};
+```
+
+While the loader itself has a short circuit to avoid processing (invoking Babel transforms) it's better to reduce the scope of processed files. For example, you can enforce a restriction to have `makeStyles()` calls only in `.styles.ts` files:
+
+```js
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.styles.ts$/,
+        exclude: /node_modules/,
+        use: {
+          loader: '@griffel/webpack-loader',
+          options: {
+            babelOptions: {
+              presets: ['@babel/preset-typescript'],
+            },
+          },
+        },
+      },
+    ],
+  },
+};
+```
+
+## Usage with Next.js
+
+Next.js lets users [tweak Webpack's config](https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config) so the same options are applicable to its config.
+
+```js
+// next.config.js
+
+module.exports = {
+  webpack: (config, { buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }) => {
+    config.module.rules.unshift({
+      test: /\.(js|jsx)$/,
+      exclude: /node_modules/,
+      use: [
+        {
+          loader: '@griffel/webpack-loader',
+        },
+      ],
+    });
+
+    // If your project uses TypeScript
+    config.module.rules.unshift({
+      test: /\.(ts|tsx)$/,
+      exclude: /node_modules/,
+      use: [
+        {
+          loader: '@griffel/webpack-loader',
+          options: {
+            babelOptions: {
+              presets: ['next/babel'],
+            },
+          },
+        },
+      ],
+    });
+
+    return config;
+  },
+};
+```
+
+## Configuration
+
+Please check [the README](https://github.com/microsoft/griffel/tree/main/packages/webpack-loader) of `@griffel/webpack-loader` to check how to configure module evaluation and imports.
diff --git a/apps/website/docs/react/css-extraction/_category_.json b/apps/website/docs/react/css-extraction/_category_.json
new file mode 100644
index 0000000..38936e4
--- /dev/null
+++ b/apps/website/docs/react/css-extraction/_category_.json
@@ -0,0 +1,5 @@
+{
+  "label": "CSS extraction 🚧",
+  "collapsed": false,
+  "position": 5
+}
diff --git a/apps/website/docs/react/css-extraction/introduction.md b/apps/website/docs/react/css-extraction/introduction.md
new file mode 100644
index 0000000..02f2834
--- /dev/null
+++ b/apps/website/docs/react/css-extraction/introduction.md
@@ -0,0 +1,23 @@
+---
+sidebar_position: 1
+---
+
+# Introduction
+
+:::caution
+
+This technology is experimental, please [report any issues](https://github.com/microsoft/griffel/issues) if found.
+
+:::
+
+While [ahead-of-time compilation allows](/react/ahead-of-time-compilation/introduction) performs optimization to reduce runtime work, the goal of CSS extraction is to remove runtime insertion to DOM and produce CSS stylesheets.
+
+## When to use it?
+
+It's designed to be used **only** in applications.
+
+## How it works
+
+The tool relies on assets transformed by [ahead-of-time compilation](/react/ahead-of-time-compilation/introduction), its usage is a **prerequisite**. CSS extraction transforms code to remove generated CSS from JavaScript files and create CSS assets.
+
+_Currently, all CSS rules will be extracted to a single CSS file i.e. [code splitting](https://webpack.js.org/guides/code-splitting/) for extracted CSS **will not work**._
diff --git a/apps/website/docs/react/css-extraction/with-nextjs.md b/apps/website/docs/react/css-extraction/with-nextjs.md
new file mode 100644
index 0000000..d44bbca
--- /dev/null
+++ b/apps/website/docs/react/css-extraction/with-nextjs.md
@@ -0,0 +1,74 @@
+---
+sidebar_position: 3
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# With Next.js
+
+## Install
+
+<Tabs>
+<TabItem value="yarn" label="Yarn">
+
+```shell
+yarn add --dev @griffel/next-extraction-plugin
+```
+
+</TabItem>
+<TabItem value="npm" label="NPM">
+
+```shell
+npm install --save-dev @griffel/next-extraction-plugin
+```
+
+</TabItem>
+</Tabs>
+
+## Usage
+
+:::info
+
+Please configure [`@griffel/webpack-loader`](/react/ahead-of-time-compilation/with-webpack) first.
+
+:::
+
+In `next.config.js` file you'll need to add the next-plugin from `@griffel/webpack-extraction-plugin` like so:
+
+```js
+// next.config.js
+const { withGriffelCSSExtraction } = require('@griffel/next-extraction-plugin');
+
+module.exports = withGriffelCSSExtraction()({
+  webpack(config) {
+    config.module.rules.unshift({
+      test: /\.(js|jsx)$/,
+      exclude: /node_modules/,
+      use: [
+        {
+          loader: '@griffel/webpack-loader',
+        },
+      ],
+    });
+
+    // If your project uses TypeScript
+    config.module.rules.unshift({
+      test: /\.(ts|tsx)$/,
+      exclude: /node_modules/,
+      use: [
+        {
+          loader: '@griffel/webpack-loader',
+          options: {
+            babelOptions: {
+              presets: ['next/babel'],
+            },
+          },
+        },
+      ],
+    });
+
+    return config;
+  },
+});
+```
diff --git a/apps/website/docs/react/css-extraction/with-webpack.md b/apps/website/docs/react/css-extraction/with-webpack.md
new file mode 100644
index 0000000..6f3996c
--- /dev/null
+++ b/apps/website/docs/react/css-extraction/with-webpack.md
@@ -0,0 +1,104 @@
+---
+sidebar_position: 2
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# With Webpack
+
+## Install
+
+<Tabs>
+<TabItem value="yarn" label="Yarn">
+
+```shell
+yarn add --dev @griffel/webpack-extraction-plugin
+```
+
+</TabItem>
+<TabItem value="npm" label="NPM">
+
+```shell
+npm install --save-dev @griffel/webpack-extraction-plugin
+```
+
+</TabItem>
+</Tabs>
+
+## Usage
+
+:::info
+
+Please configure [`@griffel/webpack-loader`](/react/ahead-of-time-compilation/with-webpack) first.
+
+:::
+
+Within your Webpack configuration object, you'll need to add the loader and the plugin from `@griffel/webpack-extraction-plugin` like so:
+
+```js
+const { GriffelCSSExtractionPlugin } = require('@griffel/webpack-extraction-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.(js|ts|tsx)$/,
+        // Apply "exclude" only if your dependencies **do not use** Griffel
+        // exclude: /node_modules/,
+        use: {
+          loader: GriffelCSSExtractionPlugin.loader,
+        },
+      },
+      // Add "@griffel/webpack-loader" if you use Griffel directly in your project
+      {
+        test: /\.(ts|tsx)$/,
+        exclude: /node_modules/,
+        use: {
+          loader: '@griffel/webpack-loader',
+          options: {
+            babelOptions: {
+              presets: ['@babel/preset-typescript'],
+            },
+          },
+        },
+      },
+      // "css-loader" is required to handle produced CSS assets by Griffel
+      // you can use "style-loader" or "MiniCssExtractPlugin.loader" to handle CSS insertion
+      {
+        test: /\.css$/,
+        use: [MiniCssExtractPlugin.loader, 'css-loader'],
+      },
+    ],
+  },
+  plugins: [new MiniCssExtractPlugin(), new GriffelCSSExtractionPlugin()],
+};
+```
+
+- `mini-css-extract-plugin` is not mandatory and is used as am example, you can use `style-loader` or other tooling to inject CSS on a page
+
+For better performance (to process less files) consider using `include` for `GriffelCSSExtractionPlugin.loader`:
+
+```js
+const { GriffelCSSExtractionPlugin } = require('@griffel/webpack-extraction-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.(js|ts|tsx)$/,
+        include: [
+          path.resolve(__dirname, 'components'),
+          /\/node_modules\/@fluentui\/,
+          // see https://webpack.js.org/configuration/module/#condition
+        ],
+        use: {
+          loader: GriffelCSSExtractionPlugin.loader,
+        },
+      },
+    ],
+  },
+};
+```
diff --git a/apps/website/docs/react/guides/atomic-css.md b/apps/website/docs/react/guides/atomic-css.md
index cec1fe7..bae1570 100644
--- a/apps/website/docs/react/guides/atomic-css.md
+++ b/apps/website/docs/react/guides/atomic-css.md
@@ -4,4 +4,104 @@ sidebar_position: 1
 
 # Atomic CSS
 
-This page is not ready yet.
+Atomic CSS is a constrasting approach to monolithic classes. In Atomic CSS every property-value is written as a single CSS rule.
+
+```html
+<!-- Monolithic classes -->
+<button class="button"></button>
+<!-- Atomic CSS -->
+<button class="display-flex align-items"></button>
+```
+
+```css
+/* Monolithic classes */
+.button {
+  display: flex;
+  align-items: center;
+}
+
+/* Atomic CSS */
+.display-flex {
+  display: flex;
+}
+.align-items-center {
+  align-items: center;
+}
+```
+
+Atomic CSS enables CSS rules re-use and reduces the total amount of defined rules. Other components can re-use the same CSS rules and create fewer rules as styles grow.
+
+## Style overrides
+
+While Griffel works by default in runtime it has [ahead-of-time compilation](/react/ahead-of-time-compilation/introduction). The AOT compilation process [cannot create new rules at runtime](/react/guides/limitations) and because of that, we rely on [merging CSS rules](/react/api/merge-classes) at runtime.
+
+Take these two rule sets:
+
+```css
+/* Group A */
+.display-flex {
+  display: flex;
+}
+.align-items-center {
+  align-items: center;
+}
+
+/* Group B */
+.align-items-end {
+  align-items: end;
+}
+```
+
+Classes are created using two parts: property name (`display`, `align-items`) & value (`flex`, `center`, `end`). Using [mergeClasses](/react/api/merge-classes) we ensure that only one set of properties is applied. The last defined property-value pair wins.
+
+```html
+<!-- Example: a result of merging classes -->
+<button class="display-flex align-items-end"></button>
+```
+
+## LVFHA order of pseudo classes
+
+Pseudo classes in CSS (like `:hover`, `:link`, `:focus`, `:active`) have equal specificity and the result is determined by [order of appearance](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance#understanding_the_cascade).
+When atomic classes are inserted to DOM, they are inserted based on definition, basically based on usage. This means the resulting styles would be based on which components’ styles were rendered first. A [CodeSandbox](https://codesandbox.io/s/lvfha-puzzle-ihbict) that shows this behavior.
+
+To ensure that results are deterministic Griffel performs automatic ordering of common pseudo classes in the following order:
+
+- `:link`
+- `:visited`
+- `:focus-within`
+- `:focus`
+- `:focus-visible`
+- `:hover`
+- `:active`
+
+The last defined pseudo wins.
+
+## Trade-offs
+
+### Larger classes
+
+Atomic CSS increases size of HTML markup as more classes added to elements: every CSS rule adds a class to the element.
+
+- Compression techniques like [gzip](https://en.wikipedia.org/wiki/HTTP_compression) work well to reduce bundle sizes.
+- CSS stylesheets are significantly smaller compared to traditional approaches due reused to CSS rules.
+
+### Recalculation performance
+
+Once an element has many HTML class names each pointing to different CSS rules, Blink based browsers (Chrome, Edge) have linear performance degradation based on an amount of classes.
+
+| Class names            |     1 |     10 |     50 |    100 |    200 |    500 | 1000   |
+| ---------------------- | ----: | -----: | -----: | -----: | -----: | -----: | ------ |
+| Elapsed (ms)           |    53 |     57 |     74 |     89 |    127 |    207 | 372    |
+| Over baseline (ms)     |     0 |      4 |     21 |     36 |     74 |    154 | 319    |
+| Match attempts         | 10000 |  10000 |  10000 |  10000 |  10000 |  10000 | 10000  |
+| Elapsed time per match |   N/A | 0.0004 | 0.0021 | 0.0036 | 0.0074 | 0.0154 | 0.0319 |
+
+_Measured in Edge 105 & Surface Go 2 on battery power._
+
+Cases when elements have 100 classes and more are rare, but you can easily reach that threshold with [nested selectors](/react/api/make-styles#nesting-selector), which we recommend avoiding.
+
+## Other materials
+
+- [Fluent UI Insights, EP02 Styling](https://www.youtube.com/watch?v=a8TFywbXBt0) & [Fluent UI Insights, EP03 Griffel](https://www.youtube.com/watch?v=edyW7t-rIUU)
+- [Atomic CSS-in-JS](https://sebastienlorber.com/atomic-css-in-js)
+- [The Shorthand-Longhand Problem in Atomic CSS](https://weser.io/blog/the-shorthand-longhand-problem-in-atomic-css)
diff --git a/apps/website/docs/react/guides/build-time-transforms.md b/apps/website/docs/react/guides/build-time-transforms.md
deleted file mode 100644
index b916048..0000000
--- a/apps/website/docs/react/guides/build-time-transforms.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-sidebar_position: 3
----
-
-# Build time transforms
-
-This page is not ready yet.
diff --git a/apps/website/docs/react/guides/child-window-rendering.md b/apps/website/docs/react/guides/child-window-rendering.md
index 20365a3..927a397 100644
--- a/apps/website/docs/react/guides/child-window-rendering.md
+++ b/apps/website/docs/react/guides/child-window-rendering.md
@@ -2,10 +2,9 @@
 sidebar_position: 5
 ---
 
-# Child Window/Shadow DOM Rendering
-
-When rendering in the main browser window, many components will need access to window or document to apply styles, listening for events, or measuring things. However it is possible to render to child windows and elements hosted in iframes.
+# Child Window
 
+When rendering in the main browser window, many components will need access to window or document to apply styles, listening for events, or measuring things. However it is possible to render to child windows and elements hosted in iframes. The same technique can be used to render styles in Shadow DOM.
 
 ## Configure rendering
 
diff --git a/apps/website/docs/react/guides/limitations.md b/apps/website/docs/react/guides/limitations.md
index 6c50bed..9860ea2 100644
--- a/apps/website/docs/react/guides/limitations.md
+++ b/apps/website/docs/react/guides/limitations.md
@@ -4,6 +4,73 @@ sidebar_position: 2
 
 # Limitations
 
+## Runtime styles
+
+Styles can't be created at runtime which includes dynamic selectors as well.
+
+```jsx
+function App(props) {
+  // ❌ This will not work and throw an expection
+  const useClasses = makeStyles({
+    color: props.color,
+    [`.${props.area}`]: { display: 'block' },
+  });
+}
+```
+
+As Griffel performs ahead-of-time [compilation](/react/ahead-of-time-compilation/introduction) values used in CSS rules should be static so that they can be compiled.
+
+### Workarounds
+
+- Enumerate variants. If you know values in advance and a set is limited the best option is to enumerate them.
+
+  ```jsx
+  const useClasses = makeStyles({
+    twoColumns: {},
+    threeColumns: {},
+    fourColumns: {},
+  });
+
+  function App(props) {
+    const classes = useClasses();
+    const className = mergeClasses(
+      props.columns === 'two' && classes.twoColumns,
+      props.columns === 'three' && classes.threeColumns,
+      props.columns === 'four' && classes.fourColumns,
+    );
+
+    return <div className={className} />;
+  }
+  ```
+
+- Use inline styles on elements. They don't have the best performance, but it will be faster than invoking any CSS-in-JS for frequently changing values.
+
+  ```jsx
+  const useClasses = makeStyles({
+    /* your styles */
+  });
+
+  function App(props) {
+    const classes = useClasses();
+    return <div style={{ color: props.color }} />;
+  }
+  ```
+
+- Use local CSS variables for nested/pseudo selectors. Prefer to use inline styles, but they can't be used for pseudo selector, for example.
+
+  ```jsx
+  const useClasses = makeStyles({
+    root: {
+      ':hover': { color: 'var(--my-app-color)' },
+    },
+  });
+
+  function App(props) {
+    const classes = useClasses();
+    return <div style={{ '--my-app-color': props.color }} />;
+  }
+  ```
+
 ## CSS shorthands are not supported
 
 There are [shorthand and longhand properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties) in CSS. Shorthand properties allow to define a set of longhand properties. For example:
diff --git a/apps/website/docs/react/install.mdx b/apps/website/docs/react/install.mdx
index b49c080..afb105a 100644
--- a/apps/website/docs/react/install.mdx
+++ b/apps/website/docs/react/install.mdx
@@ -7,7 +7,7 @@ import TabItem from '@theme/TabItem';
 
 # Install
 
-By default Griffel is a runtime css-in-js engine, you can simply install and use it in code directly:
+By default, Griffel is a runtime CSS-in-JS engine, you can simply install and use it in code directly:
 
 <Tabs>
 <TabItem value="yarn" label="Yarn">
diff --git a/apps/website/docusaurus.config.js b/apps/website/docusaurus.config.js
index 0d48b39..b09a9b4 100644
--- a/apps/website/docusaurus.config.js
+++ b/apps/website/docusaurus.config.js
@@ -27,6 +27,7 @@ const config = {
         docs: {
           editUrl: 'https://github.com/microsoft/griffel/tree/main/apps/website/',
           sidebarPath: require.resolve('./sidebars.js'),
+          remarkPlugins: [require('mdx-mermaid')],
           routeBasePath: '/',
         },
         blog: false,
diff --git a/change/@griffel-core-d2fb7682-ce4e-4be4-b2ae-431801cc95cf.json b/change/@griffel-core-d2fb7682-ce4e-4be4-b2ae-431801cc95cf.json
new file mode 100644
index 0000000..3db2302
--- /dev/null
+++ b/change/@griffel-core-d2fb7682-ce4e-4be4-b2ae-431801cc95cf.json
@@ -0,0 +1,7 @@
+{
+  "type": "patch",
+  "comment": "chore: create stylis plugin to handle :global()",
+  "packageName": "@griffel/core",
+  "email": "olfedias@microsoft.com",
+  "dependentChangeType": "patch"
+}
diff --git a/change/@griffel-react-eb078e75-469e-4056-b2e9-7293b007f909.json b/change/@griffel-react-eb078e75-469e-4056-b2e9-7293b007f909.json
new file mode 100644
index 0000000..81bfce6
--- /dev/null
+++ b/change/@griffel-react-eb078e75-469e-4056-b2e9-7293b007f909.json
@@ -0,0 +1,7 @@
+{
+  "type": "patch",
+  "comment": "fix: Adding children to prop type definitions for React 18",
+  "packageName": "@griffel/react",
+  "email": "liukerry@microsoft.com",
+  "dependentChangeType": "patch"
+}
diff --git a/package.json b/package.json
index ad0526c..84aae72 100644
--- a/package.json
+++ b/package.json
@@ -90,6 +90,8 @@
     "jest-chrome": "^0.7.2",
     "js-beautify": "^1.14.0",
     "log-symbols": "5.1.0",
+    "mdx-mermaid": "1.3.2",
+    "mermaid": "9.1.7",
     "mini-css-extract-plugin": "2.6.0",
     "monosize": "0.0.3",
     "monosize-storage-upstash": "0.0.2",
@@ -135,6 +137,7 @@
     "beachball": "patch:beachball@npm:2.21.0#.yarn/patches/beachball-npm-2.21.0-85c8ba3d6b",
     "monosize@0.0.3": "patch:monosize@npm:0.0.3#.yarn/patches/monosize-npm-0.0.3-9b650c3f51",
     "source-map-js@1.0.2": "patch:source-map-js@npm:1.0.2#.yarn/patches/source-map-js-npm-1.0.2-ee4f9f9b30.patch",
-    "@docusaurus/theme-common@2.1.0": "patch:@docusaurus/theme-common@npm:2.1.0#.yarn/patches/@docusaurus-theme-common-npm-2.1.0-d5ae2a9539.patch"
+    "@docusaurus/theme-common@2.1.0": "patch:@docusaurus/theme-common@npm:2.1.0#.yarn/patches/@docusaurus-theme-common-npm-2.1.0-d5ae2a9539.patch",
+    "mdx-mermaid@1.3.2": "patch:mdx-mermaid@npm:1.3.2#.yarn/patches/mdx-mermaid-npm-1.3.2-e8a6432fce.patch"
   }
 }
diff --git a/packages/babel-preset/__fixtures__/config-babel-options/options.json b/packages/babel-preset/__fixtures__/config-babel-options/options.json
deleted file mode 100644
index 7258485..0000000
--- a/packages/babel-preset/__fixtures__/config-babel-options/options.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "babelOptions": {
-    "plugins": ["./packages/babel-preset/__fixtures__/config-babel-options/colorRenamePlugin"]
-  }
-}
diff --git a/packages/babel-preset/__fixtures__/config-evaluation-rules/options.json b/packages/babel-preset/__fixtures__/config-evaluation-rules/options.json
deleted file mode 100644
index 076f5e0..0000000
--- a/packages/babel-preset/__fixtures__/config-evaluation-rules/options.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "evaluationRules": [
-    {
-      "action": "sampleEvaluator"
-    }
-  ]
-}
diff --git a/packages/babel-preset/__fixtures__/duplicated-imports/options.json b/packages/babel-preset/__fixtures__/duplicated-imports/options.json
deleted file mode 100644
index d8906ae..0000000
--- a/packages/babel-preset/__fixtures__/duplicated-imports/options.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "modules": [{ "moduleSource": "custom-package", "importName": "createStylesA" }]
-}
diff --git a/packages/babel-preset/__fixtures__/import-custom-module/options.json b/packages/babel-preset/__fixtures__/import-custom-module/options.json
deleted file mode 100644
index 4d20ffe..0000000
--- a/packages/babel-preset/__fixtures__/import-custom-module/options.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "modules": [{ "moduleSource": "custom-package", "importName": "makeStyles" }]
-}
diff --git a/packages/babel-preset/__fixtures__/import-custom-name/options.json b/packages/babel-preset/__fixtures__/import-custom-name/options.json
deleted file mode 100644
index 5bb97d6..0000000
--- a/packages/babel-preset/__fixtures__/import-custom-name/options.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "modules": [{ "moduleSource": "custom-package", "importName": "createStyles" }]
-}
diff --git a/packages/babel-preset/__fixtures__/non-existing-module-call/code.tsx b/packages/babel-preset/__fixtures__/non-existing-module-call/code.ts
similarity index 100%
rename from packages/babel-preset/__fixtures__/non-existing-module-call/code.tsx
rename to packages/babel-preset/__fixtures__/non-existing-module-call/code.ts
diff --git a/packages/babel-preset/__fixtures__/non-existing-module-call/output.tsx b/packages/babel-preset/__fixtures__/non-existing-module-call/output.ts
similarity index 100%
rename from packages/babel-preset/__fixtures__/non-existing-module-call/output.tsx
rename to packages/babel-preset/__fixtures__/non-existing-module-call/output.ts
diff --git a/packages/babel-preset/__fixtures__/require-custom-module/options.json b/packages/babel-preset/__fixtures__/require-custom-module/options.json
deleted file mode 100644
index 4d20ffe..0000000
--- a/packages/babel-preset/__fixtures__/require-custom-module/options.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "modules": [{ "moduleSource": "custom-package", "importName": "makeStyles" }]
-}
diff --git a/packages/core/src/runtime/compileCSS.ts b/packages/core/src/runtime/compileCSS.ts
index e3b81a2..ef9c1f5 100644
--- a/packages/core/src/runtime/compileCSS.ts
+++ b/packages/core/src/runtime/compileCSS.ts
@@ -1,5 +1,6 @@
 import { compile, middleware, prefixer, rulesheet, serialize, stringify } from 'stylis';
 
+import { globalPlugin } from './stylis/globalPlugin';
 import { hyphenateProperty } from './utils/hyphenateProperty';
 import { normalizeNestedProperty } from './utils/normalizeNestedProperty';
 
@@ -47,6 +48,7 @@ export function compileCSSRules(cssRules: string): string[] {
   serialize(
     compile(cssRules),
     middleware([
+      globalPlugin,
       prefixer,
       stringify,
 
@@ -61,38 +63,15 @@ export function compileCSSRules(cssRules: string): string[] {
 }
 
 function createCSSRule(classNameSelector: string, cssDeclaration: string, pseudos: string[]): string {
-  let globalSelector = '';
   let cssRule = cssDeclaration;
 
   if (pseudos.length > 0) {
-    cssRule = pseudos.reduceRight((acc, selector, index) => {
-      // Should be handled by namespace plugin of Stylis, is buggy now
-      // Issues are reported:
-      // https://github.com/thysultan/stylis.js/issues/253
-      // https://github.com/thysultan/stylis.js/issues/252
-      if (selector.indexOf(':global(') === 0) {
-        // 👇 :global(GROUP_1)GROUP_2
-        const GLOBAL_PSEUDO_REGEX = /global\((.+)\)(.+)?/;
-        const result = GLOBAL_PSEUDO_REGEX.exec(selector)!;
-
-        globalSelector = result[1] + ' ';
-        const restPseudo = result[2] || '';
-
-        // should be normalized to handle ":global(SELECTOR) &"
-        const normalizedPseudoSelector = normalizePseudoSelector(restPseudo);
-
-        if (normalizedPseudoSelector === '') {
-          return acc;
-        }
-
-        return `${normalizedPseudoSelector} { ${acc} }`;
-      }
-
+    cssRule = pseudos.reduceRight((acc, selector) => {
       return `${normalizePseudoSelector(selector)} { ${acc} }`;
     }, cssDeclaration);
   }
 
-  return `${globalSelector}${classNameSelector}{${cssRule}}`;
+  return `${classNameSelector}{${cssRule}}`;
 }
 
 export function compileCSS(options: CompileCSSOptions): [string /* ltr definition */, string? /* rtl definition */] {
diff --git a/packages/core/src/runtime/stylis/globalPlugin.ts b/packages/core/src/runtime/stylis/globalPlugin.ts
new file mode 100644
index 0000000..81339d6
--- /dev/null
+++ b/packages/core/src/runtime/stylis/globalPlugin.ts
@@ -0,0 +1,54 @@
+import { RULESET, tokenize } from 'stylis';
+import type { Middleware } from 'stylis';
+
+export const globalPlugin: Middleware = element => {
+  switch (element.type) {
+    case RULESET:
+      if (typeof element.props === 'string') {
+        if (process.env.NODE_ENV !== 'production') {
+          throw new Error(
+            `"element.props" has type "string" (${JSON.stringify(
+              element.props,
+              null,
+              2,
+            )}), it's not expected. Please report a bug if it happens.`,
+          );
+        }
+
+        return;
+      }
+
+      element.props = element.props.map(value => {
+        // Avoids calling tokenize() on every string
+        if (value.indexOf(':global(') === -1) {
+          return value;
+        }
+
+        return tokenize(value)
+          .reduce<string[]>((acc, value, index, children) => {
+            if (value === '') {
+              return acc;
+            }
+
+            if (value === ':' && children[index + 1] === 'global') {
+              const selector =
+                // An inner part of ":global()"
+                children[index + 2].slice(1, -1) +
+                // A separator between selectors i.e. "body .class"
+                ' ';
+
+              acc.unshift(selector);
+
+              children[index + 1] = '';
+              children[index + 2] = '';
+
+              return acc;
+            }
+
+            acc.push(value);
+            return acc;
+          }, [])
+          .join('');
+      });
+  }
+};
diff --git a/packages/react/src/RendererContext.tsx b/packages/react/src/RendererContext.tsx
index 2b6251a..62e470e 100644
--- a/packages/react/src/RendererContext.tsx
+++ b/packages/react/src/RendererContext.tsx
@@ -10,6 +10,11 @@ export interface RendererProviderProps {
    * Document used to insert CSS variables to head
    */
   targetDocument?: Document;
+
+  /**
+   * Content wrapped by the RendererProvider
+   */
+  children: React.ReactNode;
 }
 
 /**
diff --git a/packages/react/src/TextDirectionContext.tsx b/packages/react/src/TextDirectionContext.tsx
index 3d4e919..5001c20 100644
--- a/packages/react/src/TextDirectionContext.tsx
+++ b/packages/react/src/TextDirectionContext.tsx
@@ -3,6 +3,11 @@ import * as React from 'react';
 export interface TextDirectionProviderProps {
   /** Indicates the directionality of the element's text. */
   dir: 'ltr' | 'rtl';
+
+  /**
+   * Content wrapped by the TextDirectionProvider.
+   */
+  children: React.ReactNode;
 }
 
 /**
diff --git a/yarn.lock b/yarn.lock
index 1328d84..88e4b9e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1785,6 +1785,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@braintree/sanitize-url@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "@braintree/sanitize-url@npm:6.0.0"
+  checksum: 409ce7709dc1a0c67bc887d20af1becd4145d5c62cc5124b1c4c1f3ea2a8d69b0ee9f582d446469c6f5294b56442b99048cbbba6861dd5c834d4e019b95e1f40
+  languageName: node
+  linkType: hard
+
 "@cnakazawa/watch@npm:^1.0.3":
   version: 1.0.4
   resolution: "@cnakazawa/watch@npm:1.0.4"
@@ -9770,6 +9777,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"commander@npm:2, commander@npm:^2.19.0, commander@npm:^2.20.0":
+  version: 2.20.3
+  resolution: "commander@npm:2.20.3"
+  checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e
+  languageName: node
+  linkType: hard
+
+"commander@npm:7, commander@npm:^7.2.0":
+  version: 7.2.0
+  resolution: "commander@npm:7.2.0"
+  checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc
+  languageName: node
+  linkType: hard
+
 "commander@npm:8.3.0, commander@npm:^8.3.0":
   version: 8.3.0
   resolution: "commander@npm:8.3.0"
@@ -9777,13 +9798,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"commander@npm:^2.19.0, commander@npm:^2.20.0":
-  version: 2.20.3
-  resolution: "commander@npm:2.20.3"
-  checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e
-  languageName: node
-  linkType: hard
-
 "commander@npm:^4.1.1":
   version: 4.1.1
   resolution: "commander@npm:4.1.1"
@@ -9805,13 +9819,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"commander@npm:^7.2.0":
-  version: 7.2.0
-  resolution: "commander@npm:7.2.0"
-  checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc
-  languageName: node
-  linkType: hard
-
 "common-path-prefix@npm:^3.0.0":
   version: 3.0.0
   resolution: "common-path-prefix@npm:3.0.0"
@@ -10694,14 +10701,316 @@ __metadata:
   languageName: node
   linkType: hard
 
-"d3-color@npm:1 - 3":
+"d3-array@npm:1, d3-array@npm:^1.1.1, d3-array@npm:^1.2.0":
+  version: 1.2.4
+  resolution: "d3-array@npm:1.2.4"
+  checksum: d0be1fa7d72dbfac8a3bcffbb669d42bcb9128d8818d84d2b1df0c60bbe4c8e54a798be0457c55a219b399e2c2fabcbd581cbb130eb638b5436b0618d7e56000
+  languageName: node
+  linkType: hard
+
+"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.2.0":
+  version: 3.2.0
+  resolution: "d3-array@npm:3.2.0"
+  dependencies:
+    internmap: 1 - 2
+  checksum: e236f6670b60b64abb6c435da25b5cbbdc2c7c0decdbf9355bc4cf6803d6da4fa820b7b78b9cbd127edb493555934a9788d45084c2f39d7c2e1a2b7aa48264a4
+  languageName: node
+  linkType: hard
+
+"d3-axis@npm:1":
+  version: 1.0.12
+  resolution: "d3-axis@npm:1.0.12"
+  checksum: b1cf820fb6e95cc3371b340353b05272dba16ce6ad4fe9a0992d075ab48a08810f87f5e6c7cbb6c63fca1ee1e9b7c822307a1590187daa7627f45728a747c746
+  languageName: node
+  linkType: hard
+
+"d3-axis@npm:3":
+  version: 3.0.0
+  resolution: "d3-axis@npm:3.0.0"
+  checksum: 227ddaa6d4bad083539c1ec245e2228b4620cca941997a8a650cb0af239375dc20271993127eedac66f0543f331027aca09385e1e16eed023f93eac937cddf0b
+  languageName: node
+  linkType: hard
+
+"d3-brush@npm:1":
+  version: 1.1.6
+  resolution: "d3-brush@npm:1.1.6"
+  dependencies:
+    d3-dispatch: 1
+    d3-drag: 1
+    d3-interpolate: 1
+    d3-selection: 1
+    d3-transition: 1
+  checksum: ffa23a5543699cc1199f45ac87d4e1293167c4bab0833657d77172d84d910448893569393290dba3689af1e5a1fc77503d94a2dec3976de8a7bc68ed0e32413a
+  languageName: node
+  linkType: hard
+
+"d3-brush@npm:3":
+  version: 3.0.0
+  resolution: "d3-brush@npm:3.0.0"
+  dependencies:
+    d3-dispatch: 1 - 3
+    d3-drag: 2 - 3
+    d3-interpolate: 1 - 3
+    d3-selection: 3
+    d3-transition: 3
+  checksum: 1d042167769a02ac76271c71e90376d7184206e489552b7022a8ec2860209fe269db55e0a3430f3dcbe13b6fec2ff65b1adeaccba3218991b38e022390df72e3
+  languageName: node
+  linkType: hard
+
+"d3-chord@npm:1":
+  version: 1.0.6
+  resolution: "d3-chord@npm:1.0.6"
+  dependencies:
+    d3-array: 1
+    d3-path: 1
+  checksum: e4ca95ffff089f0eccf796d16a5574121e0ecbe658dcd9d5fa760af3573c3349264ce325c0adf1f32bcad67038d3938edd109712166cfb5b3bbe068e27c012e9
+  languageName: node
+  linkType: hard
+
+"d3-chord@npm:3":
+  version: 3.0.1
+  resolution: "d3-chord@npm:3.0.1"
+  dependencies:
+    d3-path: 1 - 3
+  checksum: ddf35d41675e0f8738600a8a2f05bf0858def413438c12cba357c5802ecc1014c80a658acbbee63cbad2a8c747912efb2358455d93e59906fe37469f1dc6b78b
+  languageName: node
+  linkType: hard
+
+"d3-collection@npm:1":
+  version: 1.0.7
+  resolution: "d3-collection@npm:1.0.7"
+  checksum: 9c6b910a9da0efb021e294509f98263ca4f62d10b997bb30ccfb6edd582b703da36e176b968b5bac815fbb0f328e49643c38cf93b5edf8572a179ba55cf4a09d
+  languageName: node
+  linkType: hard
+
+"d3-color@npm:1":
+  version: 1.4.1
+  resolution: "d3-color@npm:1.4.1"
+  checksum: a214b61458b5fcb7ad1a84faed0e02918037bab6be37f2d437bf0e2915cbd854d89fbf93754f17b0781c89e39d46704633d05a2bfae77e6209f0f4b140f9894b
+  languageName: node
+  linkType: hard
+
+"d3-color@npm:1 - 3, d3-color@npm:3":
   version: 3.1.0
   resolution: "d3-color@npm:3.1.0"
   checksum: 4931fbfda5d7c4b5cfa283a13c91a954f86e3b69d75ce588d06cde6c3628cebfc3af2069ccf225e982e8987c612aa7948b3932163ce15eb3c11cd7c003f3ee3b
   languageName: node
   linkType: hard
 
-"d3-interpolate@npm:1 - 3":
+"d3-contour@npm:1":
+  version: 1.3.2
+  resolution: "d3-contour@npm:1.3.2"
+  dependencies:
+    d3-array: ^1.1.1
+  checksum: c18a099a7f4af2adf788e96d07bfc7236661a6e40c017ef8e172fe0142561f3722f71263075c565a17b72e6cd6a2a05de3868fcc5420eb77b00d3a0179a69a0d
+  languageName: node
+  linkType: hard
+
+"d3-contour@npm:4":
+  version: 4.0.0
+  resolution: "d3-contour@npm:4.0.0"
+  dependencies:
+    d3-array: ^3.2.0
+  checksum: 1f9b9e56d0966d98a4c740b6af32b4fa2d14424159644adc24f4eb0ab023afbd414938f63f95032a66407fb701f4966efe40875e2cc0460fb653a943d3fc86b0
+  languageName: node
+  linkType: hard
+
+"d3-delaunay@npm:6":
+  version: 6.0.2
+  resolution: "d3-delaunay@npm:6.0.2"
+  dependencies:
+    delaunator: 5
+  checksum: 80b18686dd7a5919a570000061f1515d106b7c7e3cba9da55706c312fc8f6de58a72674f2ea4eadc6694611f2df59f82c8b9d304845dd8b7903ee1f303aa5865
+  languageName: node
+  linkType: hard
+
+"d3-dispatch@npm:1":
+  version: 1.0.6
+  resolution: "d3-dispatch@npm:1.0.6"
+  checksum: b4ecb016b6dda8b99aa4263b2d0a0c7b12e7dea93e4b0ce3013c94dca4d360d9ba00f5bdc15dc944cc4543af8e341067bd628f061f7b8deb642257e2ac90d06c
+  languageName: node
+  linkType: hard
+
+"d3-dispatch@npm:1 - 3, d3-dispatch@npm:3":
+  version: 3.0.1
+  resolution: "d3-dispatch@npm:3.0.1"
+  checksum: fdfd4a230f46463e28e5b22a45dd76d03be9345b605e1b5dc7d18bd7ebf504e6c00ae123fd6d03e23d9e2711e01f0e14ea89cd0632545b9f0c00b924ba4be223
+  languageName: node
+  linkType: hard
+
+"d3-drag@npm:1":
+  version: 1.2.5
+  resolution: "d3-drag@npm:1.2.5"
+  dependencies:
+    d3-dispatch: 1
+    d3-selection: 1
+  checksum: 6e86e89aa8d511979eea1b5326709c05c2a3c2d43a93a82ed6b6f98528b2ab03b2f58f5e4f66582f2f1c0ae44f9c19f6f4f857249eb66aabc46e4942295fa0a7
+  languageName: node
+  linkType: hard
+
+"d3-drag@npm:2 - 3, d3-drag@npm:3":
+  version: 3.0.0
+  resolution: "d3-drag@npm:3.0.0"
+  dependencies:
+    d3-dispatch: 1 - 3
+    d3-selection: 3
+  checksum: d297231e60ecd633b0d076a63b4052b436ddeb48b5a3a11ff68c7e41a6774565473a6b064c5e9256e88eca6439a917ab9cea76032c52d944ddbf4fd289e31111
+  languageName: node
+  linkType: hard
+
+"d3-dsv@npm:1":
+  version: 1.2.0
+  resolution: "d3-dsv@npm:1.2.0"
+  dependencies:
+    commander: 2
+    iconv-lite: 0.4
+    rw: 1
+  bin:
+    csv2json: bin/dsv2json
+    csv2tsv: bin/dsv2dsv
+    dsv2dsv: bin/dsv2dsv
+    dsv2json: bin/dsv2json
+    json2csv: bin/json2dsv
+    json2dsv: bin/json2dsv
+    json2tsv: bin/json2dsv
+    tsv2csv: bin/dsv2dsv
+    tsv2json: bin/dsv2json
+  checksum: 96c6e3d5ca1566624ca613b5941bc6fa916082cbe4b2b71cb6c5978c471db58c489b17206e3e31fbe30719dbd75e9c8ed8ab12a9d353cff90a35102690de7823
+  languageName: node
+  linkType: hard
+
+"d3-dsv@npm:1 - 3, d3-dsv@npm:3":
+  version: 3.0.1
+  resolution: "d3-dsv@npm:3.0.1"
+  dependencies:
+    commander: 7
+    iconv-lite: 0.6
+    rw: 1
+  bin:
+    csv2json: bin/dsv2json.js
+    csv2tsv: bin/dsv2dsv.js
+    dsv2dsv: bin/dsv2dsv.js
+    dsv2json: bin/dsv2json.js
+    json2csv: bin/json2dsv.js
+    json2dsv: bin/json2dsv.js
+    json2tsv: bin/json2dsv.js
+    tsv2csv: bin/dsv2dsv.js
+    tsv2json: bin/dsv2json.js
+  checksum: 5fc0723647269d5dccd181d74f2265920ab368a2868b0b4f55ffa2fecdfb7814390ea28622cd61ee5d9594ab262879509059544e9f815c54fe76fbfb4ffa4c8a
+  languageName: node
+  linkType: hard
+
+"d3-ease@npm:1":
+  version: 1.0.7
+  resolution: "d3-ease@npm:1.0.7"
+  checksum: 117811d51dfc4a126e8d23d249252df792fbbe30a93615e1d67158c482eff69b900e45a4cc92746fe65b1143287455406a89aae04eb4ca1ba5b1dc2a42af5b85
+  languageName: node
+  linkType: hard
+
+"d3-ease@npm:1 - 3, d3-ease@npm:3":
+  version: 3.0.1
+  resolution: "d3-ease@npm:3.0.1"
+  checksum: 06e2ee5326d1e3545eab4e2c0f84046a123dcd3b612e68858219aa034da1160333d9ce3da20a1d3486d98cb5c2a06f7d233eee1bc19ce42d1533458bd85dedcd
+  languageName: node
+  linkType: hard
+
+"d3-fetch@npm:1":
+  version: 1.2.0
+  resolution: "d3-fetch@npm:1.2.0"
+  dependencies:
+    d3-dsv: 1
+  checksum: 00f091945bff4afbd06e6ce9ad762f0e91b7aac912c1ae7fe0efdbcce3a997d4fa2a93c254a3ba9b3f53f2134d606b20fb13791adbf5c6ed5c0be329a775945f
+  languageName: node
+  linkType: hard
+
+"d3-fetch@npm:3":
+  version: 3.0.1
+  resolution: "d3-fetch@npm:3.0.1"
+  dependencies:
+    d3-dsv: 1 - 3
+  checksum: 382dcea06549ef82c8d0b719e5dc1d96286352579e3b51b20f71437f5800323315b09cf7dcfd4e1f60a41e1204deb01758470cea257d2285a7abd9dcec806984
+  languageName: node
+  linkType: hard
+
+"d3-force@npm:1":
+  version: 1.2.1
+  resolution: "d3-force@npm:1.2.1"
+  dependencies:
+    d3-collection: 1
+    d3-dispatch: 1
+    d3-quadtree: 1
+    d3-timer: 1
+  checksum: b73fe29d6c9a9c432ae65166d71238d14578a3a9537df095bebff87b7814161cd2822aff54a38d2400edb98b7f6d9221a810dcad7a53c6e8ddff0973f44ab3fa
+  languageName: node
+  linkType: hard
+
+"d3-force@npm:3":
+  version: 3.0.0
+  resolution: "d3-force@npm:3.0.0"
+  dependencies:
+    d3-dispatch: 1 - 3
+    d3-quadtree: 1 - 3
+    d3-timer: 1 - 3
+  checksum: 6c7e96438cab62fa32aeadb0ade3297b62b51f81b1b38b0a60a5ec9fd627d74090c1189654d92df2250775f31b06812342f089f1d5947de9960a635ee3581def
+  languageName: node
+  linkType: hard
+
+"d3-format@npm:1":
+  version: 1.4.5
+  resolution: "d3-format@npm:1.4.5"
+  checksum: 1b8b2c0bca182173bccd290a43e8b635a83fc8cfe52ec878c7bdabb997d47daac11f2b175cebbe73f807f782ad655f542bdfe18180ca5eb3498a3a82da1e06ab
+  languageName: node
+  linkType: hard
+
+"d3-format@npm:1 - 3, d3-format@npm:3":
+  version: 3.1.0
+  resolution: "d3-format@npm:3.1.0"
+  checksum: f345ec3b8ad3cab19bff5dead395bd9f5590628eb97a389b1dd89f0b204c7c4fc1d9520f13231c2c7cf14b7c9a8cf10f8ef15bde2befbab41454a569bd706ca2
+  languageName: node
+  linkType: hard
+
+"d3-geo@npm:1":
+  version: 1.12.1
+  resolution: "d3-geo@npm:1.12.1"
+  dependencies:
+    d3-array: 1
+  checksum: 8ede498e5fce65c127403646f5cc6181a858a1e401e23e2856ce50ad27e6fdf8b49aeb88d2fad02696879d5825a45420ca1b5db9fa9c935ee413fe15b5bc37c4
+  languageName: node
+  linkType: hard
+
+"d3-geo@npm:3":
+  version: 3.0.1
+  resolution: "d3-geo@npm:3.0.1"
+  dependencies:
+    d3-array: 2.5.0 - 3
+  checksum: e0f7e6a2f0d4c26efe08a7aa2c40b9a1a5a037220c6aaa51fb527035597e6e8841222b433e5681f9b5588b5b6f9a1c2d7f032a76ccbac3a17b0c1cbfffd05c1b
+  languageName: node
+  linkType: hard
+
+"d3-hierarchy@npm:1":
+  version: 1.1.9
+  resolution: "d3-hierarchy@npm:1.1.9"
+  checksum: 5fd8761c302252cb9abe9ce2a0934fc97104dd0df8d1b5de6472532903416f40e13b4b58d03ce215a0b816d7129c4ed4503bd4fdbc00a130fdcf46a63d734a52
+  languageName: node
+  linkType: hard
+
+"d3-hierarchy@npm:3":
+  version: 3.1.2
+  resolution: "d3-hierarchy@npm:3.1.2"
+  checksum: 0fd946a8c5fd4686d43d3e11bbfc2037a145fda29d2261ccd0e36f70b66af6d7638e2c0c7112124d63fc3d3127197a00a6aecf676bd5bd392a94d7235a214263
+  languageName: node
+  linkType: hard
+
+"d3-interpolate@npm:1":
+  version: 1.4.0
+  resolution: "d3-interpolate@npm:1.4.0"
+  dependencies:
+    d3-color: 1
+  checksum: d98988bd1e2f59d01f100d0a19315ad8f82ef022aa09a65aff76f747a44f9b52f2d64c6578b8f47e01f2b14a8f0ef88f5460d11173c0dd2d58238c217ac0ec03
+  languageName: node
+  linkType: hard
+
+"d3-interpolate@npm:1 - 3, d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:3":
   version: 3.0.1
   resolution: "d3-interpolate@npm:3.0.1"
   dependencies:
@@ -10710,7 +11019,73 @@ __metadata:
   languageName: node
   linkType: hard
 
-"d3-scale-chromatic@npm:^3.0.0":
+"d3-path@npm:1":
+  version: 1.0.9
+  resolution: "d3-path@npm:1.0.9"
+  checksum: d4382573baf9509a143f40944baeff9fead136926aed6872f7ead5b3555d68925f8a37935841dd51f1d70b65a294fe35c065b0906fb6e42109295f6598fc16d0
+  languageName: node
+  linkType: hard
+
+"d3-path@npm:1 - 3, d3-path@npm:3":
+  version: 3.0.1
+  resolution: "d3-path@npm:3.0.1"
+  checksum: 6347c7055e0af330acadbe7f02144963eecabff560a791ecfeaffb45662e4d38eedabc6109dc481478f136b41d03707d3a43321ca9a115962888c99732ceb41a
+  languageName: node
+  linkType: hard
+
+"d3-polygon@npm:1":
+  version: 1.0.6
+  resolution: "d3-polygon@npm:1.0.6"
+  checksum: 4a9764c2064d15e9f4fc9018c975f127540f6e701c18442e2a2e9339e743726f40e017d5213982d983cac3c23802321c257f2a10e686c803ec5533c6ff42bb7a
+  languageName: node
+  linkType: hard
+
+"d3-polygon@npm:3":
+  version: 3.0.1
+  resolution: "d3-polygon@npm:3.0.1"
+  checksum: 0b85c532517895544683849768a2c377cee3801ef8ccf3fa9693c8871dd21a0c1a2a0fc75ff54192f0ba2c562b0da2bc27f5bf959dfafc7fa23573b574865d2c
+  languageName: node
+  linkType: hard
+
+"d3-quadtree@npm:1":
+  version: 1.0.7
+  resolution: "d3-quadtree@npm:1.0.7"
+  checksum: 32181f578cbd69eed6b240073fed7f977f8039a121a3b9fc58ea1eea0c3c14d1237ef48cb4f80abb833063f8b0e7b885ef6de734e7bcc4e5b37e53ec444830f8
+  languageName: node
+  linkType: hard
+
+"d3-quadtree@npm:1 - 3, d3-quadtree@npm:3":
+  version: 3.0.1
+  resolution: "d3-quadtree@npm:3.0.1"
+  checksum: 5469d462763811475f34a7294d984f3eb100515b0585ca5b249656f6b1a6e99b20056a2d2e463cc9944b888896d2b1d07859c50f9c0cf23438df9cd2e3146066
+  languageName: node
+  linkType: hard
+
+"d3-random@npm:1":
+  version: 1.1.2
+  resolution: "d3-random@npm:1.1.2"
+  checksum: a27326319fa61d59b6ce8d5ce7547cc823dee1bc6dda35e9c233d709f43f76488c09353862463c9c5da99081482b0f7ea4177d78721b67bb677bb12354bffe42
+  languageName: node
+  linkType: hard
+
+"d3-random@npm:3":
+  version: 3.0.1
+  resolution: "d3-random@npm:3.0.1"
+  checksum: a70ad8d1cabe399ebeb2e482703121ac8946a3b336830b518da6848b9fdd48a111990fc041dc716f16885a72176ffa2898f2a250ca3d363ecdba5ef92b18e131
+  languageName: node
+  linkType: hard
+
+"d3-scale-chromatic@npm:1":
+  version: 1.5.0
+  resolution: "d3-scale-chromatic@npm:1.5.0"
+  dependencies:
+    d3-color: 1
+    d3-interpolate: 1
+  checksum: 3bff7717f6e6b309b3347d48d6532e2295037a280bc5174f908ce5fc0e17a9470f6b202e49499b01a17a1f28cb76a61aae870a6c13c57195a362847f33747501
+  languageName: node
+  linkType: hard
+
+"d3-scale-chromatic@npm:3, d3-scale-chromatic@npm:^3.0.0":
   version: 3.0.0
   resolution: "d3-scale-chromatic@npm:3.0.0"
   dependencies:
@@ -10720,6 +11095,252 @@ __metadata:
   languageName: node
   linkType: hard
 
+"d3-scale@npm:2":
+  version: 2.2.2
+  resolution: "d3-scale@npm:2.2.2"
+  dependencies:
+    d3-array: ^1.2.0
+    d3-collection: 1
+    d3-format: 1
+    d3-interpolate: 1
+    d3-time: 1
+    d3-time-format: 2
+  checksum: 42086d4b9db9f8492a99dbbdacf546983faef1bb6260fe875c0c1884f1ca9cf5fd233de3702c2f9e24145b1c5383945e929c8682d80fa57ab515ef2c4f2c61f6
+  languageName: node
+  linkType: hard
+
+"d3-scale@npm:4":
+  version: 4.0.2
+  resolution: "d3-scale@npm:4.0.2"
+  dependencies:
+    d3-array: 2.10.0 - 3
+    d3-format: 1 - 3
+    d3-interpolate: 1.2.0 - 3
+    d3-time: 2.1.1 - 3
+    d3-time-format: 2 - 4
+  checksum: a9c770d283162c3bd11477c3d9d485d07f8db2071665f1a4ad23eec3e515e2cefbd369059ec677c9ac849877d1a765494e90e92051d4f21111aa56791c98729e
+  languageName: node
+  linkType: hard
+
+"d3-selection@npm:1, d3-selection@npm:^1.1.0":
+  version: 1.4.2
+  resolution: "d3-selection@npm:1.4.2"
+  checksum: 2484b392259b087a98f546f2610e6a11c90f38dae6b6b20a3fc85171038fcab4c72e702788b1960a4fece88bed2e36f268096358b5b48d3c7f0d35cfbe305da6
+  languageName: node
+  linkType: hard
+
+"d3-selection@npm:2 - 3, d3-selection@npm:3":
+  version: 3.0.0
+  resolution: "d3-selection@npm:3.0.0"
+  checksum: f4e60e133309115b99f5b36a79ae0a19d71ee6e2d5e3c7216ef3e75ebd2cb1e778c2ed2fa4c01bef35e0dcbd96c5428f5bd6ca2184fe2957ed582fde6841cbc5
+  languageName: node
+  linkType: hard
+
+"d3-shape@npm:1":
+  version: 1.3.7
+  resolution: "d3-shape@npm:1.3.7"
+  dependencies:
+    d3-path: 1
+  checksum: 46566a3ab64a25023653bf59d64e81e9e6c987e95be985d81c5cedabae5838bd55f4a201a6b69069ca862eb63594cd263cac9034afc2b0e5664dfe286c866129
+  languageName: node
+  linkType: hard
+
+"d3-shape@npm:3":
+  version: 3.1.0
+  resolution: "d3-shape@npm:3.1.0"
+  dependencies:
+    d3-path: 1 - 3
+  checksum: 3dffe31b56feaf0817954748c9823c0e1fb6ab888b83775e9d568176ffa369546064ae49403963aac70108272988f632452634851f1c8a92805134d0c40e6dba
+  languageName: node
+  linkType: hard
+
+"d3-time-format@npm:2":
+  version: 2.3.0
+  resolution: "d3-time-format@npm:2.3.0"
+  dependencies:
+    d3-time: 1
+  checksum: 5445eaaf2b3b2095cdc1fa75dfd2f361a61c39b677dcc1c2ba4cb6bc0442953de0fbaaa397d7d7a9325ad99c63d869f162a713e150e826ff8af482615664cb3f
+  languageName: node
+  linkType: hard
+
+"d3-time-format@npm:2 - 4, d3-time-format@npm:4":
+  version: 4.1.0
+  resolution: "d3-time-format@npm:4.1.0"
+  dependencies:
+    d3-time: 1 - 3
+  checksum: 7342bce28355378152bbd4db4e275405439cabba082d9cd01946d40581140481c8328456d91740b0fe513c51ec4a467f4471ffa390c7e0e30ea30e9ec98fcdf4
+  languageName: node
+  linkType: hard
+
+"d3-time@npm:1":
+  version: 1.1.0
+  resolution: "d3-time@npm:1.1.0"
+  checksum: 33fcfff94ff093dde2048c190ecca8b39fe0ec8b3c61e9fc39c5f6072ce5b86dd2b91823f086366995422bbbac7f74fd9abdb7efe4f292a73b1c6197c699cc78
+  languageName: node
+  linkType: hard
+
+"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:3":
+  version: 3.0.0
+  resolution: "d3-time@npm:3.0.0"
+  dependencies:
+    d3-array: 2 - 3
+  checksum: 01646568ef01682550b7ee9f32394e4eb116a29515564861958871ed8de8fff02a25cd50dd8c4413921e6d9ecb8c8ce39be3266f655c8c18599fe58bcb253d60
+  languageName: node
+  linkType: hard
+
+"d3-timer@npm:1":
+  version: 1.0.10
+  resolution: "d3-timer@npm:1.0.10"
+  checksum: f7040953672deb2dfa03830ace80dbbcb212f80890218eba15dcca6f33f74102d943023ccc2a563295195cd8c63639bb2410ef1691c8fecff4a114fdf5c666f4
+  languageName: node
+  linkType: hard
+
+"d3-timer@npm:1 - 3, d3-timer@npm:3":
+  version: 3.0.1
+  resolution: "d3-timer@npm:3.0.1"
+  checksum: 1cfddf86d7bca22f73f2c427f52dfa35c49f50d64e187eb788dcad6e927625c636aa18ae4edd44d084eb9d1f81d8ca4ec305dae7f733c15846a824575b789d73
+  languageName: node
+  linkType: hard
+
+"d3-transition@npm:1":
+  version: 1.3.2
+  resolution: "d3-transition@npm:1.3.2"
+  dependencies:
+    d3-color: 1
+    d3-dispatch: 1
+    d3-ease: 1
+    d3-interpolate: 1
+    d3-selection: ^1.1.0
+    d3-timer: 1
+  checksum: 1b4a0cfa7aeb4033ab20e26a310488cfac989de44c6c2bf10e9f0808af915a33add6dca23fbafcefe8c08613fd0d6a933e48b4de24c0779163c2852a1c7c16f4
+  languageName: node
+  linkType: hard
+
+"d3-transition@npm:2 - 3, d3-transition@npm:3":
+  version: 3.0.1
+  resolution: "d3-transition@npm:3.0.1"
+  dependencies:
+    d3-color: 1 - 3
+    d3-dispatch: 1 - 3
+    d3-ease: 1 - 3
+    d3-interpolate: 1 - 3
+    d3-timer: 1 - 3
+  peerDependencies:
+    d3-selection: 2 - 3
+  checksum: cb1e6e018c3abf0502fe9ff7b631ad058efb197b5e14b973a410d3935aead6e3c07c67d726cfab258e4936ef2667c2c3d1cd2037feb0765f0b4e1d3b8788c0ea
+  languageName: node
+  linkType: hard
+
+"d3-voronoi@npm:1":
+  version: 1.1.4
+  resolution: "d3-voronoi@npm:1.1.4"
+  checksum: d28a74bc62f2b936b0d3b51d5be8d2366afca4fd7026d7ee8f655600650bf0c985da38a8c3ae46bfa315b5f524f3ca1c5211437cf1c8c737cc1da681e015baee
+  languageName: node
+  linkType: hard
+
+"d3-zoom@npm:1":
+  version: 1.8.3
+  resolution: "d3-zoom@npm:1.8.3"
+  dependencies:
+    d3-dispatch: 1
+    d3-drag: 1
+    d3-interpolate: 1
+    d3-selection: 1
+    d3-transition: 1
+  checksum: de408e5dc6df1481ef6854a3d495f8e963dbf5b0de41bcbd35def0602abda55b3f2c1fa751c75c2f0a9bafd3b278f30795c27503fe609b3dbe06a0720d01d5be
+  languageName: node
+  linkType: hard
+
+"d3-zoom@npm:3":
+  version: 3.0.0
+  resolution: "d3-zoom@npm:3.0.0"
+  dependencies:
+    d3-dispatch: 1 - 3
+    d3-drag: 2 - 3
+    d3-interpolate: 1 - 3
+    d3-selection: 2 - 3
+    d3-transition: 2 - 3
+  checksum: 8056e3527281cfd1ccbcbc458408f86973b0583e9dac00e51204026d1d36803ca437f970b5736f02fafed9f2b78f145f72a5dbc66397e02d4d95d4c594b8ff54
+  languageName: node
+  linkType: hard
+
+"d3@npm:^5.14":
+  version: 5.16.0
+  resolution: "d3@npm:5.16.0"
+  dependencies:
+    d3-array: 1
+    d3-axis: 1
+    d3-brush: 1
+    d3-chord: 1
+    d3-collection: 1
+    d3-color: 1
+    d3-contour: 1
+    d3-dispatch: 1
+    d3-drag: 1
+    d3-dsv: 1
+    d3-ease: 1
+    d3-fetch: 1
+    d3-force: 1
+    d3-format: 1
+    d3-geo: 1
+    d3-hierarchy: 1
+    d3-interpolate: 1
+    d3-path: 1
+    d3-polygon: 1
+    d3-quadtree: 1
+    d3-random: 1
+    d3-scale: 2
+    d3-scale-chromatic: 1
+    d3-selection: 1
+    d3-shape: 1
+    d3-time: 1
+    d3-time-format: 2
+    d3-timer: 1
+    d3-transition: 1
+    d3-voronoi: 1
+    d3-zoom: 1
+  checksum: 1462789c421c3ea3930a18b91be6c02c7b976fa4d714200ee2a042c62cbfb349448c79f1ae3dbaf186f79edb734b7aa7b734ee6ad61d81ab4305e6663623ab8e
+  languageName: node
+  linkType: hard
+
+"d3@npm:^7.0.0":
+  version: 7.6.1
+  resolution: "d3@npm:7.6.1"
+  dependencies:
+    d3-array: 3
+    d3-axis: 3
+    d3-brush: 3
+    d3-chord: 3
+    d3-color: 3
+    d3-contour: 4
+    d3-delaunay: 6
+    d3-dispatch: 3
+    d3-drag: 3
+    d3-dsv: 3
+    d3-ease: 3
+    d3-fetch: 3
+    d3-force: 3
+    d3-format: 3
+    d3-geo: 3
+    d3-hierarchy: 3
+    d3-interpolate: 3
+    d3-path: 3
+    d3-polygon: 3
+    d3-quadtree: 3
+    d3-random: 3
+    d3-scale: 4
+    d3-scale-chromatic: 3
+    d3-selection: 3
+    d3-shape: 3
+    d3-time: 3
+    d3-time-format: 4
+    d3-timer: 3
+    d3-transition: 3
+    d3-zoom: 3
+  checksum: af883cfeaf0a861afb2424edcb5419a5c56c84ddbc1ac9c7771c569f1926ace8db3cf0f4996038eb1db9700f7335e30c23b885199e0320a002893492ae83b415
+  languageName: node
+  linkType: hard
+
 "d@npm:1, d@npm:^1.0.1":
   version: 1.0.1
   resolution: "d@npm:1.0.1"
@@ -10730,6 +11351,28 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dagre-d3@npm:^0.6.4":
+  version: 0.6.4
+  resolution: "dagre-d3@npm:0.6.4"
+  dependencies:
+    d3: ^5.14
+    dagre: ^0.8.5
+    graphlib: ^2.1.8
+    lodash: ^4.17.15
+  checksum: 14d5ae9c438c72e928adaac625fb6341367082b401e8abc1cbc8a5b0be72abbc28502c47d497aa8386ff66bf1bed4c27be9b3f040291e9c631eae9858d2444e3
+  languageName: node
+  linkType: hard
+
+"dagre@npm:^0.8.5":
+  version: 0.8.5
+  resolution: "dagre@npm:0.8.5"
+  dependencies:
+    graphlib: ^2.1.8
+    lodash: ^4.17.15
+  checksum: b9fabd425466d7b662381c2e457b1adda996bc4169aa60121d4de50250d83a6bb4b77d559e2f887c9c564caea781c2a377fd4de2a76c15f8f04ec3d086ca95f9
+  languageName: node
+  linkType: hard
+
 "damerau-levenshtein@npm:^1.0.7":
   version: 1.0.8
   resolution: "damerau-levenshtein@npm:1.0.8"
@@ -10928,6 +11571,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"delaunator@npm:5":
+  version: 5.0.0
+  resolution: "delaunator@npm:5.0.0"
+  dependencies:
+    robust-predicates: ^3.0.0
+  checksum: d6764188442b7f7c6bcacebd96edc00e35f542a96f1af3ef600e586bfb9849a3682c489c0ab423440c90bc4c7cac77f28761babff76fa29e193e1cf50a95b860
+  languageName: node
+  linkType: hard
+
 "delayed-stream@npm:~1.0.0":
   version: 1.0.0
   resolution: "delayed-stream@npm:1.0.0"
@@ -11202,6 +11854,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dompurify@npm:2.4.0":
+  version: 2.4.0
+  resolution: "dompurify@npm:2.4.0"
+  checksum: c93ea73cf8e3ba044588450198563e56ce6902e36d0e16e3699df2fa59e82c4fdd11d4ad04ef5024569ce96a35b46f29d0bbea522516add33cd39a7f56a8a675
+  languageName: node
+  linkType: hard
+
 "domutils@npm:^1.7.0":
   version: 1.7.0
   resolution: "domutils@npm:1.7.0"
@@ -13777,6 +14436,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"graphlib@npm:^2.1.8":
+  version: 2.1.8
+  resolution: "graphlib@npm:2.1.8"
+  dependencies:
+    lodash: ^4.17.15
+  checksum: 1e0db4dea1c8187d59103d5582ecf32008845ebe2103959a51d22cb6dae495e81fb9263e22c922bca3aaecb56064a45cd53424e15a4626cfb5a0c52d0aff61a8
+  languageName: node
+  linkType: hard
+
 "gray-matter@npm:^4.0.3":
   version: 4.0.3
   resolution: "gray-matter@npm:4.0.3"
@@ -13872,6 +14540,8 @@ __metadata:
     js-beautify: ^1.14.0
     loader-utils: ^2.0.0
     log-symbols: 5.1.0
+    mdx-mermaid: 1.3.2
+    mermaid: 9.1.7
     mini-css-extract-plugin: 2.6.0
     monosize: 0.0.3
     monosize-storage-upstash: 0.0.2
@@ -14535,7 +15205,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"iconv-lite@npm:0.4.24":
+"iconv-lite@npm:0.4, iconv-lite@npm:0.4.24":
   version: 0.4.24
   resolution: "iconv-lite@npm:0.4.24"
   dependencies:
@@ -14544,7 +15214,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
+"iconv-lite@npm:0.6, iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
   version: 0.6.3
   resolution: "iconv-lite@npm:0.6.3"
   dependencies:
@@ -14797,6 +15467,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"internmap@npm:1 - 2":
+  version: 2.0.3
+  resolution: "internmap@npm:2.0.3"
+  checksum: 7ca41ec6aba8f0072fc32fa8a023450a9f44503e2d8e403583c55714b25efd6390c38a87161ec456bf42d7bc83aab62eb28f5aef34876b1ac4e60693d5e1d241
+  languageName: node
+  linkType: hard
+
 "interpret@npm:^1.0.0":
   version: 1.4.0
   resolution: "interpret@npm:1.4.0"
@@ -16547,6 +17224,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"khroma@npm:^2.0.0":
+  version: 2.0.0
+  resolution: "khroma@npm:2.0.0"
+  checksum: 3be7ef681f41f6071464e21060731fa63e2915bcd0774b9f35e431aa664c0c0e0826825403360654935111d4309f6704e5dc27cd953614133dfbdee4c056c3a8
+  languageName: node
+  linkType: hard
+
 "kind-of@npm:^3.0.2, kind-of@npm:^3.0.3, kind-of@npm:^3.2.0":
   version: 3.2.2
   resolution: "kind-of@npm:3.2.2"
@@ -17243,6 +17927,28 @@ __metadata:
   languageName: node
   linkType: hard
 
+"mdx-mermaid@npm:1.3.2":
+  version: 1.3.2
+  resolution: "mdx-mermaid@npm:1.3.2"
+  peerDependencies:
+    mermaid: ">=8.11.0"
+    react: ^16.8.4 || ^17.0.0 || ^18.0.0
+    unist-util-visit: ^2.0.0
+  checksum: f4fde2b5de6408167e240288c977e776a45a5c146510747461c49410855cf3ff59699d8ecb2b189f6a9dd477a08f55c324a1288ad917f15897b637a3f5613174
+  languageName: node
+  linkType: hard
+
+"mdx-mermaid@patch:mdx-mermaid@npm:1.3.2#.yarn/patches/mdx-mermaid-npm-1.3.2-e8a6432fce.patch::locator=griffel-repository%40workspace%3A.":
+  version: 1.3.2
+  resolution: "mdx-mermaid@patch:mdx-mermaid@npm%3A1.3.2#.yarn/patches/mdx-mermaid-npm-1.3.2-e8a6432fce.patch::version=1.3.2&hash=d12a40&locator=griffel-repository%40workspace%3A."
+  peerDependencies:
+    mermaid: ">=8.11.0"
+    react: ^16.8.4 || ^17.0.0 || ^18.0.0
+    unist-util-visit: ^2.0.0
+  checksum: c0e2dfb8121add98a4d9c8d16cb4701e1506a82f86ddef850614ebdf059c013f37bf61627d66b9770737a1d7021a2d9a67d4e3636f24e4061b1a339f93d182a8
+  languageName: node
+  linkType: hard
+
 "media-typer@npm:0.3.0":
   version: 0.3.0
   resolution: "media-typer@npm:0.3.0"
@@ -17319,6 +18025,23 @@ __metadata:
   languageName: node
   linkType: hard
 
+"mermaid@npm:9.1.7":
+  version: 9.1.7
+  resolution: "mermaid@npm:9.1.7"
+  dependencies:
+    "@braintree/sanitize-url": ^6.0.0
+    d3: ^7.0.0
+    dagre: ^0.8.5
+    dagre-d3: ^0.6.4
+    dompurify: 2.4.0
+    graphlib: ^2.1.8
+    khroma: ^2.0.0
+    moment-mini: 2.24.0
+    stylis: ^4.0.10
+  checksum: 7f3f4c55de9e290aa4fa37b01d37772bceae8b7fad888a034ba4cebbdba5e25632fcfbdcadc168d9c3589d173399b6bb74517bba91237f3b0ce7f945e62ab21c
+  languageName: node
+  linkType: hard
+
 "methods@npm:~1.1.2":
   version: 1.1.2
   resolution: "methods@npm:1.1.2"
@@ -17675,6 +18398,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"moment-mini@npm:2.24.0":
+  version: 2.24.0
+  resolution: "moment-mini@npm:2.24.0"
+  checksum: c1162322fd05a305cf5d403107fe702a928e5a72c56a614142fae4882846f66bb21c423cef397fe56802564b0353386f1bca46c8bb080d2097e68cbd687d589e
+  languageName: node
+  linkType: hard
+
 "monosize-storage-upstash@npm:0.0.2":
   version: 0.0.2
   resolution: "monosize-storage-upstash@npm:0.0.2"
@@ -21325,6 +22055,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"robust-predicates@npm:^3.0.0":
+  version: 3.0.1
+  resolution: "robust-predicates@npm:3.0.1"
+  checksum: 45e9de2df4380da84a2a561d4fd54ea92194e878b93ed19d5e4bc90f4e834a13755e846c8516bab8360190309696f0564a0150386c52ef01f70f2b388449dac5
+  languageName: node
+  linkType: hard
+
 "rollup-plugin-copy@npm:^3.4.0":
   version: 3.4.0
   resolution: "rollup-plugin-copy@npm:3.4.0"
@@ -21465,6 +22202,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"rw@npm:1":
+  version: 1.3.3
+  resolution: "rw@npm:1.3.3"
+  checksum: c20d82421f5a71c86a13f76121b751553a99cd4a70ea27db86f9b23f33db941f3f06019c30f60d50c356d0bd674c8e74764ac146ea55e217c091bde6fba82aa3
+  languageName: node
+  linkType: hard
+
 "rxjs-for-await@npm:0.0.2":
   version: 0.0.2
   resolution: "rxjs-for-await@npm:0.0.2"
@@ -22843,7 +23587,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"stylis@npm:4.0.13, stylis@npm:^4.0.13":
+"stylis@npm:4.0.13, stylis@npm:^4.0.10, stylis@npm:^4.0.13":
   version: 4.0.13
   resolution: "stylis@npm:4.0.13"
   checksum: 8ea7a87028b6383c6a982231c4b5b6150031ce028e0fdaf7b2ace82253d28a8af50cc5a9da8a421d3c7c4441592f393086e332795add672aa4a825f0fe3713a3


Test patch:
diff --git a/packages/babel-preset/src/transformPlugin.test.ts b/packages/babel-preset/src/transformPlugin.test.ts
index 53f7262..33bfe43 100644
--- a/packages/babel-preset/src/transformPlugin.test.ts
+++ b/packages/babel-preset/src/transformPlugin.test.ts
@@ -27,11 +27,166 @@ pluginTester({
         parser: 'typescript',
       },
     }),
-
-  fixtures: fixturesDir,
   tests: [
+    // 🎩 Tip: use "only: true" to run a single test
+    // https://github.com/babel-utils/babel-plugin-tester#only
+    //
+
+    // Fixtures
+    //
+    //
+    {
+      title: 'assets import handling',
+      fixture: path.resolve(fixturesDir, 'assets', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'assets', 'output.ts'),
+    },
+    {
+      title: 'duplicated imports',
+      fixture: path.resolve(fixturesDir, 'duplicated-imports', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'duplicated-imports', 'output.ts'),
+      pluginOptions: {
+        modules: [{ moduleSource: 'custom-package', importName: 'createStylesA' }],
+      },
+    },
+    {
+      title: 'multiple declarations',
+      fixture: path.resolve(fixturesDir, 'multiple-declarations', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'multiple-declarations', 'output.ts'),
+    },
+    {
+      title: 'call of non existing module',
+      fixture: path.resolve(fixturesDir, 'non-existing-module-call', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'non-existing-module-call', 'output.ts'),
+    },
+
+    // Evaluation
+    //
+    //
+    {
+      title: 'evaluation: mixins via functions',
+      fixture: path.resolve(fixturesDir, 'function-mixin', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'function-mixin', 'output.ts'),
+    },
+    {
+      title: 'evaluation: object',
+      fixture: path.resolve(fixturesDir, 'object', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object', 'output.ts'),
+    },
+    {
+      title: 'evaluation: object with computed keys',
+      fixture: path.resolve(fixturesDir, 'object-computed-keys', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object-computed-keys', 'output.ts'),
+    },
+    {
+      title: 'evaluation: object with imported keys',
+      fixture: path.resolve(fixturesDir, 'object-imported-keys', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object-imported-keys', 'output.ts'),
+    },
+    {
+      title: 'evaluation: object with mixins',
+      fixture: path.resolve(fixturesDir, 'object-mixins', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object-mixins', 'output.ts'),
+    },
+    {
+      title: 'evaluation: nested objects',
+      fixture: path.resolve(fixturesDir, 'object-nesting', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object-nesting', 'output.ts'),
+    },
+    {
+      title: 'evaluation: objects with sequence expression',
+      fixture: path.resolve(fixturesDir, 'object-sequence-expr', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object-sequence-expr', 'output.ts'),
+    },
+    {
+      title: 'evaluation: objects with variables',
+      fixture: path.resolve(fixturesDir, 'object-variables', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'object-variables', 'output.ts'),
+    },
+    {
+      title: 'evaluation: rules with metadata',
+      fixture: path.resolve(fixturesDir, 'rules-with-metadata', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'rules-with-metadata', 'output.ts'),
+    },
+    {
+      title: 'evaluation: shared mixins',
+      fixture: path.resolve(fixturesDir, 'shared-mixins', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'shared-mixins', 'output.ts'),
+    },
+    {
+      title: 'evaluation: tokens scenario',
+      fixture: path.resolve(fixturesDir, 'tokens', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'tokens', 'output.ts'),
+    },
+
+    // Configs
+    //
+    //
+    {
+      title: 'config: babelOptions',
+      fixture: path.resolve(fixturesDir, 'config-babel-options', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'config-babel-options', 'output.ts'),
+      pluginOptions: {
+        babelOptions: {
+          plugins: ['./packages/babel-preset/__fixtures__/config-babel-options/colorRenamePlugin'],
+        },
+      },
+    },
+    {
+      title: 'config: evaluationRules',
+      fixture: path.resolve(fixturesDir, 'config-evaluation-rules', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'config-evaluation-rules', 'output.ts'),
+      pluginOptions: {
+        evaluationRules: [
+          {
+            action: 'sampleEvaluator',
+          },
+        ],
+      },
+    },
+
+    // Imports
+    //
+    //
+    {
+      title: 'imports: alias usage',
+      fixture: path.resolve(fixturesDir, 'import-alias', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'import-alias', 'output.ts'),
+    },
+    {
+      title: 'imports: custom module',
+      fixture: path.resolve(fixturesDir, 'import-custom-module', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'import-custom-module', 'output.ts'),
+      pluginOptions: {
+        modules: [{ moduleSource: 'custom-package', importName: 'makeStyles' }],
+      },
+    },
+    {
+      title: 'imports: custom module name',
+      fixture: path.resolve(fixturesDir, 'import-custom-name', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'import-custom-name', 'output.ts'),
+      pluginOptions: {
+        modules: [{ moduleSource: 'custom-package', importName: 'createStyles' }],
+      },
+    },
+    {
+      title: 'imports: require()',
+      fixture: path.resolve(fixturesDir, 'require', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'require', 'output.ts'),
+    },
+    {
+      title: 'imports: require() with custom module',
+      fixture: path.resolve(fixturesDir, 'require-custom-module', 'code.ts'),
+      outputFixture: path.resolve(fixturesDir, 'require-custom-module', 'output.ts'),
+      pluginOptions: {
+        modules: [{ moduleSource: 'custom-package', importName: 'makeStyles' }],
+      },
+    },
+
+    // Errors
+    //
+    //
     {
-      title: 'Unsupported shorthand CSS properties',
+      title: 'errors: unsupported shorthand CSS properties',
       fixture: path.resolve(fixturesDir, 'unsupported-css-properties', 'fixture.ts'),
       outputFixture: path.resolve(fixturesDir, 'unsupported-css-properties', 'output.ts'),
       setup() {
diff --git a/packages/core/src/runtime/stylis/globalPlugin.test.ts b/packages/core/src/runtime/stylis/globalPlugin.test.ts
new file mode 100644
index 0000000..417d14d
--- /dev/null
+++ b/packages/core/src/runtime/stylis/globalPlugin.test.ts
@@ -0,0 +1,24 @@
+import { compile, middleware, serialize, stringify } from 'stylis';
+import { globalPlugin } from './globalPlugin';
+
+function compileRule(rule: string) {
+  return serialize(compile(rule), middleware([globalPlugin, stringify]));
+}
+
+describe('globalPlugin', () => {
+  it('handles basic selectors', () => {
+    expect(compileRule('.foo :global(.baz) { color: red }')).toMatchInlineSnapshot(`".baz .foo {color:red;}"`);
+    expect(compileRule('.foo :global(body) { color: red }')).toMatchInlineSnapshot(`"body .foo {color:red;}"`);
+  });
+
+  it('handles multiple entries in selector', () => {
+    expect(compileRule('.foo :global(.baz.qux) { color: red }')).toMatchInlineSnapshot(`".baz.qux .foo {color:red;}"`);
+    expect(compileRule('.foo :global(body div) { color: red }')).toMatchInlineSnapshot(`"body div .foo {color:red;}"`);
+  });
+
+  it('handles data selectors', () => {
+    expect(compileRule('.foo :global([data-global-style]) { color: red }')).toMatchInlineSnapshot(
+      `"[data-global-style] .foo {color:red;}"`,
+    );
+  });
+});