feat(storybook): add support for Storybook v6
Co-authored-by: Katerina Skroumpelou <katerina@fileas.local> Co-authored-by: Juri <juri.strumpflohner@gmail.com>
This commit is contained in:
parent
341cc6bdba
commit
5da9e668fd
@ -1,6 +1,6 @@
|
||||
# Storybook
|
||||
|
||||

|
||||

|
||||
|
||||
Storybook is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.
|
||||
|
||||
@ -25,7 +25,7 @@ If there's no `.storybook` folder at the root of the workspace, one is created.
|
||||
```treeview
|
||||
<workspace name>/
|
||||
├── .storybook/
|
||||
│ ├── addons.js
|
||||
│ ├── main.js
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── apps/
|
||||
@ -41,8 +41,7 @@ Also, a project-specific `.storybook` folder is added in the root of the project
|
||||
```treeview
|
||||
<project root>/
|
||||
├── .storybook/
|
||||
│ ├── addons.js
|
||||
│ ├── config.js
|
||||
│ ├── main.js
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── src/
|
||||
@ -134,11 +133,15 @@ describe('shared-ui', () => {
|
||||
|
||||
To register an [addon](https://storybook.js.org/addons/) for all storybook instances in your workspace:
|
||||
|
||||
1. In `/.storybook/addons.js` add the register import statement.
|
||||
1. In `/.storybook/main.js`, in the `addons` array of the `module.exports` object, add the new addon:
|
||||
```
|
||||
import '@storybook/addon-knobs/register';
|
||||
module.exports = {
|
||||
stories: [...],
|
||||
...,
|
||||
addons: [..., '@storybook/addon-knobs/register'],
|
||||
};
|
||||
```
|
||||
2. If a decorator is required, in each project's `<project-path>/.storybook/config.js` use the `addDecorator` function.
|
||||
2. If a decorator is required, in each project's `<project-path>/.storybook/preview.js` use the `addDecorator` function.
|
||||
|
||||
```
|
||||
import { configure, addDecorator } from '@storybook/angular';
|
||||
@ -151,11 +154,15 @@ To register an [addon](https://storybook.js.org/addons/) for all storybook insta
|
||||
|
||||
To register an [addon](https://storybook.js.org/addons/) for a single storybook instance, go to that project's `.storybook` folder:
|
||||
|
||||
1. In `addons.js` add the register import statement.
|
||||
1. In `main.js`, in the `addons` array of the `module.exports` object, add the new addon:
|
||||
```
|
||||
import '@storybook/addon-knobs/register';
|
||||
module.exports = {
|
||||
stories: [...],
|
||||
...,
|
||||
addons: [..., '@storybook/addon-knobs/register'],
|
||||
};
|
||||
```
|
||||
2. If a decorator is required, in `config.js` use the `addDecorator` function.
|
||||
2. If a decorator is required, in `preview.js` use the `addDecorator` function.
|
||||
|
||||
```
|
||||
import { configure, addDecorator } from '@storybook/angular';
|
||||
@ -167,3 +174,169 @@ To register an [addon](https://storybook.js.org/addons/) for a single storybook
|
||||
### More Information
|
||||
|
||||
For more on using Storybook, see the [official Storybook documentation](https://storybook.js.org/docs/basics/introduction/).
|
||||
|
||||
## Upgrading to Storybook 6 (and Nx versions >10.1.x)
|
||||
|
||||
Nx now comes with [Storybook version 6](https://storybook.js.org/releases/6.0). Chances are, if you used Nx version `10.1.x` or older with Storybook, you are using [Storybook version 5.3](https://storybook.js.org/releases/5.3) with configuration files of [Storybook version 5.2](https://storybook.js.org/releases/5.2).
|
||||
|
||||
Nx version `10.2.x` will continue to support Storybook version `5.2.x`, however newer versions of Nx will only support Storybook version `6` (and on).
|
||||
|
||||
We chose not to provide an automatic migration script for your Storybook instances and configurations across your apps and libraries, since there a number of breaking changes that Storybook introduced in versions `5.3` and `6.0`, and making decisions on what to migrate automatically would risk the integrity of your code. Instead, when you choose to migrate from Nx versions `<10.1.x` to Nx versions `>10.2.x` we will keep your Storybook packages and Storybook instances and configurations intact. We suggest that you do the migration on your own, manually, using the guide below, with all the references to the official Storybook migration guides. Look at the use cases below, and follow the one that matches your case.
|
||||
|
||||
### Use cases:
|
||||
|
||||
#### Use case 1: Create an Nx workspace from scratch using the latest version of Nx
|
||||
|
||||
If you are creating an Nx workspace using the latest version of Nx, the latest version of Storybook (version 6) will be used as well. You do not need to do anything.
|
||||
|
||||
#### Use case 2: I already have an Nx workspace that does NOT use Storybook and I want to migrate to the latest Nx
|
||||
|
||||
If you already have an Nx workspace with a previous version of Nx that does NOT use Storybook, and you migrate to the latest Nx using the migrate scripts provided by Nx, and then, after the migration to the latest Nx, you choose to add Storybook, the latest version of Storybook will be used. You do not need to do anything.
|
||||
|
||||
#### Use case 3: I already have an Nx workspace with Storybook and I want to migrate to the latest Nx
|
||||
|
||||
In that case, when you run the Nx migration scripts, the scripts will ignore the Storybook packages, the Storybook configuration files, the Storybook instances in your apps and libraries, and all the generated stories. If you continue to add Storybook configurations and Storybook instances to new libraries and applications, then the version of Storybook that you already have will be used (most probably, if you have not changed anything manually, that version will be `5.3.9` using, however, the configuration files of `5.2`). You will have to do the [upgrade to the latest Storybook on your own, manually](#upgrading-to-storybook-6-manually). After that, Nx will use that version, and configure all new Storybook instances using the new version.
|
||||
|
||||
### Upgrading to Storybook 6 manually
|
||||
|
||||
#### Step 0:
|
||||
|
||||
**Commit any changes you have locally**. We would suggest that you start the migration with a clean git history, in case anything goes wrong.
|
||||
|
||||
#### Step 1: Changing the configuration files from version 5.2 to 5.3
|
||||
|
||||
The most noticeable change in Storybook versions newer than `5.2` is that the configuration files have changed names and content.
|
||||
Quoting from the [official Storybook migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-52x-to-53x):
|
||||
|
||||
- `presets.js` has been renamed to `main.js`. `main.js` is the main point of configuration for storybook.
|
||||
- `config.js` has been renamed to `preview.js`. `preview.js` configures the "preview" iframe that renders your components.
|
||||
- `addons.js` has been renamed to `manager.js`. `manager.js` configures Storybook's "manager" UI that wraps the preview, and also configures addons panel.
|
||||
|
||||
Please follow the [official Storybook version 5.2.x to 5.3.x migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-52x-to-53x) to change your files accordingly.
|
||||
|
||||
If you are using Storybook using only the generated files after running the `storybook-configuration` schematic, things might be easier for you. Please check the [sample files for a manual upgrade](#sample-files-for-manual-upgrade).
|
||||
|
||||
#### Step 2: Going from version 5.3 to 6.0
|
||||
|
||||
Please check out this official [Storybook 6 Migration Guide](https://medium.com/storybookjs/storybook-6-migration-guide-200346241bb5) article, as well as the [detailed guides here](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-53x-to-60x).
|
||||
|
||||
- One big change in Storybook version `6` is that it has **built-in Typescript support**. This means that you can remove Typescript configurations from your configuration files.
|
||||
- Please also **check that your stories match any differences in syntax** introduced in versions `5.3` and `6.0`.
|
||||
|
||||
#### Step 3: Upgrade all `@storybook/*` packages in your project
|
||||
|
||||
Check your `package.json` file for all `@storybook` packages. Install the latest versions of these, usign `yarn`:
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
yarn add --dev @storybook/angular@latest
|
||||
```
|
||||
|
||||
#### Step 4: Check that everything works as expected
|
||||
|
||||
Check that everything works as expected. If you are still having trouble, you can submit you issue in the [GitHub Nx repo](https://github.com/nrwl/nx). We wish you luck!
|
||||
|
||||
### Sample files for manual upgrade
|
||||
|
||||
If you have not changed the content of the files which the `storybook-configuration` schematic produced, you can use the following samples to migrate to Storybook `6`:
|
||||
|
||||
#### Configuring the root `./storybook` directory
|
||||
|
||||
- In the root `./storybook` directory, create a new file named `main.js` with the following content:
|
||||
|
||||
```
|
||||
module.exports = {
|
||||
stories: [],
|
||||
addons: ['@storybook/addon-knobs/register'],
|
||||
};
|
||||
```
|
||||
|
||||
- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. If you are using the default generated files without any changes, you should only have the `@storybook/addon-knobs/register` addon, which we already put in the array. You can now delete the `addons.js` file.
|
||||
|
||||
- The other two files remain unchanged.
|
||||
|
||||
#### Configuring the Storybook instances across apps and libraries - the library-specific `./storybook` directories
|
||||
|
||||
- In the library `./storybook` directory, create a new file named `main.js` with the following content:
|
||||
|
||||
```
|
||||
const lib_main_module = require('../../.storybook/main');
|
||||
|
||||
lib_main_module.stories.push('../src/lib/**/*.stories.mdx');
|
||||
lib_main_module.stories.push('../src/lib/**/*.stories.@(js|jsx|ts|tsx)');
|
||||
module.exports = lib_main_module;
|
||||
```
|
||||
|
||||
Please take extra care making sure that the path to the root `./storybook` directory provided in the first line is correct.
|
||||
|
||||
- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. You can add any addons in the `addons` module array using the following syntax:
|
||||
|
||||
```
|
||||
lib_main_module.addons.push('<YOUR_ADDON_HERE>');
|
||||
```
|
||||
|
||||
After you add any addons in the `main.js` file, you can safely delete the `addons.js` file. If you are using the default generated files without any changes, your `addons.js` file should be empty (but an import line, referencing the root `addons.js` file).
|
||||
|
||||
- Rename the file `config.js` to `preview.js` and remove the last line where your stories paths are configured. Now, the contents of the `preview.js` file will look like this:
|
||||
|
||||
```
|
||||
import { addDecorator } from '<%= uiFramework %>';
|
||||
import { withKnobs } from '@storybook/addon-knobs';
|
||||
|
||||
addDecorator(withKnobs);
|
||||
```
|
||||
|
||||
- Modify the contents of `webpack.config.js`. Remove the following lines, which are the TypeScript configuration, which is not needed by Storybook any more:
|
||||
|
||||
```
|
||||
config.resolve.extensions.push('.ts', '.tsx');
|
||||
config.module.rules.push({
|
||||
test: /\.(ts|tsx)$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### Check final folder structure
|
||||
|
||||
Your folder structure should now look like this:
|
||||
|
||||
```
|
||||
<workspace name>/
|
||||
├── .storybook/
|
||||
│ ├── main.js
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── apps/
|
||||
├── libs/
|
||||
│ └── <library name>/
|
||||
│ ├── .storybook/
|
||||
│ │ ├── main.js
|
||||
│ │ ├── tsconfig.json
|
||||
│ │ └── webpack.config.js
|
||||
│ ├── src/
|
||||
│ ├── README.md
|
||||
│ ├── tsconfig.json
|
||||
│ └── etc...
|
||||
├── nx.json
|
||||
├── package.json
|
||||
├── README.md
|
||||
└── etc...
|
||||
```
|
||||
|
||||
### Storybook v6 args and controls
|
||||
|
||||
Storybook v6 moves from "knobs" to args and controls when it comes to defining and manipulating your storybook
|
||||
component properties. Feel free to use the new args way of defining stories. More can be found
|
||||
[on the official Storybook docs](https://storybook.js.org/docs/angular/writing-stories/args).
|
||||
|
||||
> **Note:** Nx does not yet automatically generate stories that use the args syntax. The main reason is that args don't
|
||||
> yet support being loaded via the iframe URL which is used in Nx to setup your Storybook based e2e tests. Once support
|
||||
> is present in Storybook v6, we will provide a way to generate args & controls based stories. More on the progress [here](https://github.com/storybookjs/storybook/issues/12291).
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Storybook
|
||||
|
||||

|
||||

|
||||
|
||||
Storybook is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.
|
||||
|
||||
@ -25,7 +25,7 @@ If there's no `.storybook` folder at the root of the workspace, one is created.
|
||||
```treeview
|
||||
<workspace name>/
|
||||
├── .storybook/
|
||||
│ ├── addons.js
|
||||
│ ├── main.js
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── apps/
|
||||
@ -41,7 +41,7 @@ Also, a project-specific `.storybook` folder is added in the root of the project
|
||||
```treeview
|
||||
<project root>/
|
||||
├── .storybook/
|
||||
│ ├── addons.js
|
||||
│ ├── main.js
|
||||
│ ├── config.js
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
@ -115,11 +115,15 @@ describe('shared-ui', () => {
|
||||
|
||||
To register an [addon](https://storybook.js.org/addons/) for all storybook instances in your workspace:
|
||||
|
||||
1. In `/.storybook/addons.js` add the register import statement.
|
||||
1. In `/.storybook/main.js`, in the `addons` array of the `module.exports` object, add the new addon:
|
||||
```
|
||||
import '@storybook/addon-knobs/register';
|
||||
module.exports = {
|
||||
stories: [...],
|
||||
...,
|
||||
addons: [..., '@storybook/addon-knobs/register'],
|
||||
};
|
||||
```
|
||||
2. If a decorator is required, in each project's `<project-path>/.storybook/config.js` use the `addDecorator` function.
|
||||
2. If a decorator is required, in each project's `<project-path>/.storybook/preview.js` use the `addDecorator` function.
|
||||
|
||||
```
|
||||
import { configure, addDecorator } from '@storybook/angular';
|
||||
@ -132,11 +136,15 @@ To register an [addon](https://storybook.js.org/addons/) for all storybook insta
|
||||
|
||||
To register an [addon](https://storybook.js.org/addons/) for a single storybook instance, go to that project's `.storybook` folder:
|
||||
|
||||
1. In `addons.js` add the register import statement.
|
||||
1. In `main.js`, in the `addons` array of the `module.exports` object, add the new addon:
|
||||
```
|
||||
import '@storybook/addon-knobs/register';
|
||||
module.exports = {
|
||||
stories: [...],
|
||||
...,
|
||||
addons: [..., '@storybook/addon-knobs/register'],
|
||||
};
|
||||
```
|
||||
2. If a decorator is required, in `config.js` use the `addDecorator` function.
|
||||
2. If a decorator is required, in `preview.js` use the `addDecorator` function.
|
||||
|
||||
```
|
||||
import { configure, addDecorator } from '@storybook/angular';
|
||||
@ -148,3 +156,167 @@ To register an [addon](https://storybook.js.org/addons/) for a single storybook
|
||||
### More Information
|
||||
|
||||
For more on using Storybook, see the [official Storybook documentation](https://storybook.js.org/docs/basics/introduction/).
|
||||
|
||||
## Upgrading to Storybook 6 (and Nx versions >10.1.x)
|
||||
|
||||
Nx now comes with [Storybook version 6](https://storybook.js.org/releases/6.0). Chances are, if you used Nx version `10.1.x` or older with Storybook, you are using [Storybook version 5.3](https://storybook.js.org/releases/5.3) with configuration files of [Storybook version 5.2](https://storybook.js.org/releases/5.2).
|
||||
|
||||
Nx version `10.2.x` will continue to support Storybook version `5.2.x`, however newer versions of Nx will only support Storybook version `6` (and on).
|
||||
|
||||
We chose not to provide an automatic migration script for your Storybook instances and configurations across your apps and libraries, since there a number of breaking changes that Storybook introduced in versions `5.3` and `6.0`, and making decisions on what to migrate automatically would risk the integrity of your code. Instead, when you choose to migrate from Nx versions `<10.1.x` to Nx versions `>10.2.x` we will keep your Storybook packages and Storybook instances and configurations intact. We suggest that you do the migration on your own, manually, using the guide below, with all the references to the official Storybook migration guides. Look at the use cases below, and follow the one that matches your case.
|
||||
|
||||
### Use cases:
|
||||
|
||||
#### Use case 1: Create an Nx workspace from scratch using the latest version of Nx
|
||||
|
||||
If you are creating an Nx workspace using the latest version of Nx, the latest version of Storybook (version 6) will be used as well. You do not need to do anything.
|
||||
|
||||
#### Use case 2: I already have an Nx workspace that does NOT use Storybook and I want to migrate to the latest Nx
|
||||
|
||||
If you already have an Nx workspace with a previous version of Nx that does NOT use Storybook, and you migrate to the latest Nx using the migrate scripts provided by Nx, and then, after the migration to the latest Nx, you choose to add Storybook, the latest version of Storybook will be used. You do not need to do anything.
|
||||
|
||||
#### Use case 3: I already have an Nx workspace with Storybook and I want to migrate to the latest Nx
|
||||
|
||||
In that case, when you run the Nx migration scripts, the scripts will ignore the Storybook packages, the Storybook configuration files, the Storybook instances in your apps and libraries, and all the generated stories. If you continue to add Storybook configurations and Storybook instances to new libraries and applications, then the version of Storybook that you already have will be used (most probably, if you have not changed anything manually, that version will be `5.3.9` using, however, the configuration files of `5.2`). You will have to do the [upgrade to the latest Storybook on your own, manually](#upgrading-to-storybook-6-manually). After that, Nx will use that version, and configure all new Storybook instances using the new version.
|
||||
|
||||
### Upgrading to Storybook 6 manually
|
||||
|
||||
#### Step 0:
|
||||
|
||||
**Commit any changes you have locally**. We would suggest that you start the migration with a clean git history, in case anything goes wrong.
|
||||
|
||||
#### Step 1: Changing the configuration files from version 5.2 to 5.3
|
||||
|
||||
The most noticeable change in Storybook versions newer than `5.2` is that the configuration files have changed names and content.
|
||||
Quoting from the [official Storybook migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-52x-to-53x):
|
||||
|
||||
- `presets.js` has been renamed to `main.js`. `main.js` is the main point of configuration for storybook.
|
||||
- `config.js` has been renamed to `preview.js`. `preview.js` configures the "preview" iframe that renders your components.
|
||||
- `addons.js` has been renamed to `manager.js`. `manager.js` configures Storybook's "manager" UI that wraps the preview, and also configures addons panel.
|
||||
|
||||
Please follow the [official Storybook version 5.2.x to 5.3.x migration guide](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-52x-to-53x) to change your files accordingly.
|
||||
|
||||
#### Step 2: Going from version 5.3 to 6.0
|
||||
|
||||
Please check out this official [Storybook 6 Migration Guide](https://medium.com/storybookjs/storybook-6-migration-guide-200346241bb5) article, as well as the [detailed guides here](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-53x-to-60x).
|
||||
|
||||
- One big change in Storybook version `6` is that it has **built-in Typescript support**. This means that you can remove Typescript configurations from your configuration files.
|
||||
- Please also **check that your stories match any differences in syntax** introduced in versions `5.3` and `6.0`.
|
||||
|
||||
#### Step 3: Upgrade all `@storybook/*` packages in your project
|
||||
|
||||
Check your `package.json` file for all `@storybook` packages. Install the latest versions of these, usign `yarn`:
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
yarn add --dev @storybook/react@latest
|
||||
```
|
||||
|
||||
#### Step 4: Check that everything works as expected
|
||||
|
||||
Check that everything works as expected. If you are still having trouble, you can submit you issue in the [GitHub Nx repo](https://github.com/nrwl/nx). We wish you luck!
|
||||
|
||||
### Sample files for manual upgrade
|
||||
|
||||
If you have not changed the content of the files which the `storybook-configuration` schematic produced, you can use the following samples to migrate to Storybook `6`:
|
||||
|
||||
#### Configuring the root `./storybook` directory
|
||||
|
||||
- In the root `./storybook` directory, create a new file named `main.js` with the following content:
|
||||
|
||||
```
|
||||
module.exports = {
|
||||
stories: [],
|
||||
addons: ['@storybook/addon-knobs/register'],
|
||||
};
|
||||
```
|
||||
|
||||
- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. If you are using the default generated files without any changes, you should only have the `@storybook/addon-knobs/register` addon, which we already put in the array. You can now delete the `addons.js` file.
|
||||
|
||||
- The other two files remain unchanged.
|
||||
|
||||
#### Configuring the Storybook instances across apps and libraries - the library-specific `./storybook` directories
|
||||
|
||||
- In the library `./storybook` directory, create a new file named `main.js` with the following content:
|
||||
|
||||
```
|
||||
const lib_main_module = require('../../.storybook/main');
|
||||
|
||||
lib_main_module.stories.push('../src/lib/**/*.stories.mdx');
|
||||
lib_main_module.stories.push('../src/lib/**/*.stories.@(js|jsx|ts|tsx)');
|
||||
module.exports = lib_main_module;
|
||||
```
|
||||
|
||||
Please take extra care making sure that the path to the root `./storybook` directory provided in the first line is correct.
|
||||
|
||||
- If you have any addons in the `addons.js` file, add them in the `addons` array in the `main.js` file. You can add any addons in the `addons` module array using the following syntax:
|
||||
|
||||
```
|
||||
lib_main_module.addons.push('<YOUR_ADDON_HERE>');
|
||||
```
|
||||
|
||||
After you add any addons in the `main.js` file, you can safely delete the `addons.js` file. If you are using the default generated files without any changes, your `addons.js` file should be empty (but an import line, referencing the root `addons.js` file).
|
||||
|
||||
- Rename the file `config.js` to `preview.js` and remove the last line where your stories paths are configured. Now, the contents of the `preview.js` file will look like this:
|
||||
|
||||
```
|
||||
import { addDecorator } from '<%= uiFramework %>';
|
||||
import { withKnobs } from '@storybook/addon-knobs';
|
||||
|
||||
addDecorator(withKnobs);
|
||||
```
|
||||
|
||||
- Modify the contents of `webpack.config.js`. Remove the following lines, which are the TypeScript configuration, which is not needed by Storybook any more:
|
||||
|
||||
```
|
||||
config.resolve.extensions.push('.ts', '.tsx');
|
||||
config.module.rules.push({
|
||||
test: /\.(ts|tsx)$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### Check final folder structure
|
||||
|
||||
Your folder structure should now look like this:
|
||||
|
||||
```
|
||||
<workspace name>/
|
||||
├── .storybook/
|
||||
│ ├── main.js
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── apps/
|
||||
├── libs/
|
||||
│ └── <library name>/
|
||||
│ ├── .storybook/
|
||||
│ │ ├── main.js
|
||||
│ │ ├── tsconfig.json
|
||||
│ │ └── webpack.config.js
|
||||
│ ├── src/
|
||||
│ ├── README.md
|
||||
│ ├── tsconfig.json
|
||||
│ └── etc...
|
||||
├── nx.json
|
||||
├── package.json
|
||||
├── README.md
|
||||
└── etc...
|
||||
```
|
||||
|
||||
### Storybook v6 args and controls
|
||||
|
||||
Storybook v6 moves from "knobs" to args and controls when it comes to defining and manipulating your storybook
|
||||
component properties. Feel free to use the new args way of defining stories. More can be found
|
||||
[on the official Storybook docs](https://storybook.js.org/docs/react/writing-stories/args).
|
||||
|
||||
> **Note:** Nx does not yet automatically generate stories that use the args syntax. The main reason is that args don't
|
||||
> yet support being loaded via the iframe URL which is used in Nx to setup your Storybook based e2e tests. Once support
|
||||
> is present in Storybook v6, we will provide a way to generate args & controls based stories. More on the progress [here](https://github.com/storybookjs/storybook/issues/12291).
|
||||
|
||||
@ -57,8 +57,8 @@ forEachCli(() => {
|
||||
tmpProjPath(`libs/${mylib2}/src/lib/button.stories.tsx`),
|
||||
`
|
||||
import React from 'react';
|
||||
import { text, number } from '@storybook/addon-knobs';
|
||||
import { Button, ButtonStyle } from './button';
|
||||
import { text, number } from '@storybook/addon-knobs';
|
||||
|
||||
export default { title: 'Button' };
|
||||
|
||||
@ -67,6 +67,9 @@ forEachCli(() => {
|
||||
padding={number('Padding', 0)}
|
||||
style={text('Style', 'default') as ButtonStyle}
|
||||
text={text('Text', 'Click me')}
|
||||
// padding='0'
|
||||
// style='default'
|
||||
// text='Click me'
|
||||
/>
|
||||
);
|
||||
`
|
||||
|
||||
@ -76,10 +76,10 @@
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "7.1.1",
|
||||
"@schematics/angular": "10.0.3",
|
||||
"@storybook/addon-knobs": "5.3.9",
|
||||
"@storybook/angular": "5.3.9",
|
||||
"@storybook/core": "5.3.9",
|
||||
"@storybook/react": "5.3.9",
|
||||
"@storybook/addon-knobs": "^6.0.21",
|
||||
"@storybook/angular": "^6.0.21",
|
||||
"@storybook/core": "^6.0.21",
|
||||
"@storybook/react": "^6.0.21",
|
||||
"@svgr/webpack": "^5.4.0",
|
||||
"@testing-library/react": "9.4.0",
|
||||
"@types/copy-webpack-plugin": "6.0.0",
|
||||
|
||||
@ -13,4 +13,4 @@ export const primary = () => ({
|
||||
props: {<% for (let prop of props) { %>
|
||||
<%=prop.name%>: <%=prop.type%>('<%=prop.name%>', <%=prop.defaultValue%>),<% } %>
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -41,11 +41,11 @@ Array [
|
||||
"/libs/test-ui-lib/src/lib/test-other/test-other.component.spec.ts",
|
||||
"/libs/test-ui-lib/src/lib/test-other/test-other.component.ts",
|
||||
"/libs/test-ui-lib/src/lib/test-other/test-other.component.stories.ts",
|
||||
"/libs/test-ui-lib/.storybook/addons.js",
|
||||
"/libs/test-ui-lib/.storybook/config.js",
|
||||
"/libs/test-ui-lib/.storybook/main.js",
|
||||
"/libs/test-ui-lib/.storybook/preview.js",
|
||||
"/libs/test-ui-lib/.storybook/tsconfig.json",
|
||||
"/libs/test-ui-lib/.storybook/webpack.config.js",
|
||||
"/.storybook/addons.js",
|
||||
"/.storybook/main.js",
|
||||
"/.storybook/tsconfig.json",
|
||||
"/.storybook/webpack.config.js",
|
||||
"/apps/test-ui-lib-e2e/tslint.json",
|
||||
|
||||
@ -2,12 +2,19 @@ import { Tree } from '@angular-devkit/schematics';
|
||||
import { runSchematic } from '../../utils/testing';
|
||||
import { StorybookConfigureSchema } from './schema';
|
||||
import { createTestUILib } from '../stories/stories-lib.spec';
|
||||
import * as fileUtils from '@nrwl/workspace/src/core/file-utils';
|
||||
|
||||
describe('schematic:configuration', () => {
|
||||
let appTree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
appTree = await createTestUILib('test-ui-lib');
|
||||
jest.spyOn(fileUtils, 'readPackageJson').mockReturnValue({
|
||||
devDependencies: {
|
||||
'@storybook/addon-essentials': '^6.0.21',
|
||||
'@storybook/react': '^6.0.21',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should only configure storybook', async () => {
|
||||
@ -21,8 +28,7 @@ describe('schematic:configuration', () => {
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/addons.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/config.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/main.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
@ -60,8 +66,7 @@ describe('schematic:configuration', () => {
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/addons.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/config.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/main.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
|
||||
@ -16,4 +16,4 @@ export const primary = () => {
|
||||
<% } %>
|
||||
|
||||
return <<%= componentName %> <% for (let prop of props) { %><%= prop.name %> = {props.<%= prop.name %>} <% } %> />;
|
||||
};
|
||||
};
|
||||
@ -2,58 +2,61 @@ import { externalSchematic, Tree } from '@angular-devkit/schematics';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import { callRule, runSchematic } from '../../utils/testing';
|
||||
import { StorybookConfigureSchema } from './schema';
|
||||
import * as fileUtils from '@nrwl/workspace/src/core/file-utils';
|
||||
|
||||
describe('react:storybook-configuration', () => {
|
||||
let appTree;
|
||||
|
||||
// beforeEach(async () => {
|
||||
// appTree = await createTestUILib('test-ui-lib');
|
||||
// });
|
||||
|
||||
describe('libraries', () => {
|
||||
it('should configure everything at once', async () => {
|
||||
appTree = await createTestUILib('test-ui-lib');
|
||||
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-lib',
|
||||
configureCypress: true,
|
||||
generateCypressSpecs: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/addons.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/config.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
expect(tree.exists('apps/test-ui-lib-e2e/cypress.json')).toBeTruthy();
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(fileUtils, 'readPackageJson').mockReturnValue({
|
||||
devDependencies: {
|
||||
'@storybook/addon-essentials': '^6.0.21',
|
||||
'@storybook/react': '^6.0.21',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate stories for components', async () => {
|
||||
appTree = await createTestUILib('test-ui-lib');
|
||||
it('should configure everything at once', async () => {
|
||||
appTree = await createTestUILib('test-ui-lib');
|
||||
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-lib',
|
||||
generateStories: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-lib',
|
||||
configureCypress: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/main.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
expect(tree.exists('apps/test-ui-lib-e2e/cypress.json')).toBeTruthy();
|
||||
});
|
||||
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/src/lib/test-ui-lib.stories.tsx')
|
||||
).toBeTruthy();
|
||||
});
|
||||
it('should generate stories for components', async () => {
|
||||
appTree = await createTestUILib('test-ui-lib');
|
||||
|
||||
it('should generate stories for components written in plain JS', async () => {
|
||||
appTree = await createTestUILib('test-ui-lib', true);
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-lib',
|
||||
generateStories: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
|
||||
appTree.create(
|
||||
'libs/test-ui-lib/src/lib/test-ui-libplain.js',
|
||||
`import React from 'react';
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/src/lib/test-ui-lib.stories.tsx')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should generate stories for components written in plain JS', async () => {
|
||||
appTree = await createTestUILib('test-ui-lib', true);
|
||||
|
||||
appTree.create(
|
||||
'libs/test-ui-lib/src/lib/test-ui-libplain.js',
|
||||
`import React from 'react';
|
||||
|
||||
import './test.scss';
|
||||
|
||||
@ -67,75 +70,71 @@ describe('react:storybook-configuration', () => {
|
||||
|
||||
export default Test;
|
||||
`
|
||||
);
|
||||
);
|
||||
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-lib',
|
||||
generateCypressSpecs: true,
|
||||
generateStories: true,
|
||||
js: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-lib',
|
||||
generateCypressSpecs: true,
|
||||
generateStories: true,
|
||||
js: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/src/lib/test-ui-libplain.stories.js')
|
||||
).toBeTruthy();
|
||||
});
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/src/lib/test-ui-libplain.stories.js')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('applications', () => {
|
||||
it('should configure everything at once', async () => {
|
||||
appTree = await createTestAppLib('test-ui-app');
|
||||
it('should configure everything at once', async () => {
|
||||
appTree = await createTestAppLib('test-ui-app');
|
||||
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-app',
|
||||
configureCypress: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-app',
|
||||
configureCypress: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
|
||||
expect(tree.exists('apps/test-ui-app/.storybook/addons.js')).toBeTruthy();
|
||||
expect(tree.exists('apps/test-ui-app/.storybook/config.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('apps/test-ui-app/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
expect(tree.exists('apps/test-ui-app/.storybook/main.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('apps/test-ui-app/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
|
||||
/**
|
||||
* Note on the removal of
|
||||
* expect(tree.exists('apps/test-ui-app-e2e/cypress.json')).toBeTruthy();
|
||||
*
|
||||
* When calling createTestAppLib() we do not generate an e2e suite.
|
||||
* The storybook schematic for apps does not generate e2e test.
|
||||
* So, there exists no test-ui-app-e2e!
|
||||
*/
|
||||
});
|
||||
/**
|
||||
* Note on the removal of
|
||||
* expect(tree.exists('apps/test-ui-app-e2e/cypress.json')).toBeTruthy();
|
||||
*
|
||||
* When calling createTestAppLib() we do not generate an e2e suite.
|
||||
* The storybook schematic for apps does not generate e2e test.
|
||||
* So, there exists no test-ui-app-e2e!
|
||||
*/
|
||||
});
|
||||
|
||||
it('should generate stories for components', async () => {
|
||||
appTree = await createTestAppLib('test-ui-app');
|
||||
it('should generate stories for components', async () => {
|
||||
appTree = await createTestAppLib('test-ui-app');
|
||||
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-app',
|
||||
generateStories: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
const tree = await runSchematic(
|
||||
'storybook-configuration',
|
||||
<StorybookConfigureSchema>{
|
||||
name: 'test-ui-app',
|
||||
generateStories: true,
|
||||
},
|
||||
appTree
|
||||
);
|
||||
|
||||
// Currently the auto-generate stories feature only picks up components under the 'lib' directory.
|
||||
// In our 'createTestAppLib' function, we call @nrwl/react:component to generate a component
|
||||
// under the specified 'lib' directory
|
||||
expect(
|
||||
tree.exists(
|
||||
'apps/test-ui-app/src/app/my-component/my-component.stories.tsx'
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
// Currently the auto-generate stories feature only picks up components under the 'lib' directory.
|
||||
// In our 'createTestAppLib' function, we call @nrwl/react:component to generate a component
|
||||
// under the specified 'lib' directory
|
||||
expect(
|
||||
tree.exists(
|
||||
'apps/test-ui-app/src/app/my-component/my-component.stories.tsx'
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ describe('Build storybook', () => {
|
||||
config: {
|
||||
pluginPath: join(
|
||||
__dirname,
|
||||
`/../../schematics/configuration/root-files/.storybook/addons.js`
|
||||
`/../../schematics/configuration/root-files/.storybook/main.js`
|
||||
),
|
||||
configPath: join(
|
||||
__dirname,
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
},
|
||||
"configPath": {
|
||||
"type": "string",
|
||||
"description": "Path to storybook config.js file."
|
||||
"description": "Path to storybook preview.js file."
|
||||
},
|
||||
"srcRoot": {
|
||||
"type": "string",
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
},
|
||||
"configPath": {
|
||||
"type": "string",
|
||||
"description": "Path to storybook config.js file."
|
||||
"description": "Path to storybook preview.js file."
|
||||
},
|
||||
"srcRoot": {
|
||||
"type": "string",
|
||||
|
||||
@ -3,12 +3,19 @@ import { readJsonInTree, getProjectConfig } from '@nrwl/workspace';
|
||||
|
||||
import { createTestUILib, runSchematic } from '../../utils/testing';
|
||||
import { getTsConfigContent, TsConfig } from '../../utils/utils';
|
||||
import * as fileUtils from '@nrwl/workspace/src/core/file-utils';
|
||||
|
||||
describe('schematic:configuration', () => {
|
||||
let appTree: Tree;
|
||||
|
||||
beforeEach(async () => {
|
||||
appTree = await createTestUILib('test-ui-lib', '@nrwl/angular');
|
||||
jest.spyOn(fileUtils, 'readPackageJson').mockReturnValue({
|
||||
devDependencies: {
|
||||
'@storybook/addon-knobs': '^6.0.21',
|
||||
'@storybook/angular': '^6.0.21',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate files', async () => {
|
||||
@ -20,6 +27,7 @@ describe('schematic:configuration', () => {
|
||||
|
||||
// Root
|
||||
expect(tree.exists('.storybook/tsconfig.json')).toBeTruthy();
|
||||
expect(tree.exists('.storybook/main.js')).toBeTruthy();
|
||||
const rootStorybookTsconfigJson = readJsonInTree<TsConfig>(
|
||||
tree,
|
||||
'.storybook/tsconfig.json'
|
||||
@ -32,11 +40,11 @@ describe('schematic:configuration', () => {
|
||||
]);
|
||||
|
||||
// Local
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/addons.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/config.js')).toBeTruthy();
|
||||
expect(
|
||||
tree.exists('libs/test-ui-lib/.storybook/tsconfig.json')
|
||||
).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/main.js')).toBeTruthy();
|
||||
expect(tree.exists('libs/test-ui-lib/.storybook/preview.js')).toBeTruthy();
|
||||
|
||||
const storybookTsconfigJson = readJsonInTree<{ exclude: string[] }>(
|
||||
tree,
|
||||
|
||||
@ -26,18 +26,28 @@ import {
|
||||
import { CypressConfigureSchema } from '../cypress-project/cypress-project';
|
||||
import { StorybookConfigureSchema } from './schema';
|
||||
import { toJS } from '@nrwl/workspace/src/utils/rules/to-js';
|
||||
import { readPackageJson } from '@nrwl/workspace/src/core/file-utils';
|
||||
import { storybookVersion } from '../../utils/versions';
|
||||
import { projectDir } from '@nrwl/workspace/src/utils/project-type';
|
||||
|
||||
export default function (rawSchema: StorybookConfigureSchema): Rule {
|
||||
const schema = normalizeSchema(rawSchema);
|
||||
|
||||
const workspaceStorybookVersion = readCurrentWorkspaceStorybookVersion();
|
||||
|
||||
return (tree: Tree, context: SchematicContext) => {
|
||||
const { projectType } = getProjectConfig(tree, schema.name);
|
||||
return chain([
|
||||
schematic('ng-add', {
|
||||
uiFramework: schema.uiFramework,
|
||||
}),
|
||||
createRootStorybookDir(schema.name, schema.uiFramework, schema.js),
|
||||
createProjectStorybookDir(schema.name, schema.uiFramework, schema.js),
|
||||
createRootStorybookDir(schema.name, schema.js, workspaceStorybookVersion),
|
||||
createProjectStorybookDir(
|
||||
schema.name,
|
||||
schema.uiFramework,
|
||||
schema.js,
|
||||
workspaceStorybookVersion
|
||||
),
|
||||
configureTsProjectConfig(schema),
|
||||
configureTsSolutionConfig(schema),
|
||||
updateLintTask(schema),
|
||||
@ -68,23 +78,23 @@ function normalizeSchema(schema: StorybookConfigureSchema) {
|
||||
|
||||
function createRootStorybookDir(
|
||||
projectName: string,
|
||||
uiFramework: StorybookConfigureSchema['uiFramework'],
|
||||
js: boolean
|
||||
js: boolean,
|
||||
workspaceStorybookVersion: string
|
||||
): Rule {
|
||||
return (tree: Tree, context: SchematicContext) => {
|
||||
const { projectType } = getProjectConfig(tree, projectName);
|
||||
const projectDirectory = projectDir(projectType);
|
||||
|
||||
context.logger.debug(`adding .storybook folder to' ${projectDirectory}`);
|
||||
context.logger.debug(
|
||||
`adding .storybook folder to ${projectDirectory} -\n
|
||||
based on the Storybook version installed: ${workspaceStorybookVersion}, we'll bootstrap a scaffold for that particular version.`
|
||||
);
|
||||
return chain([
|
||||
applyWithSkipExisting(url('./root-files'), [
|
||||
js ? toJS() : noop(),
|
||||
template({
|
||||
tmpl: '',
|
||||
uiFramework,
|
||||
projectType: projectDirectory,
|
||||
}),
|
||||
]),
|
||||
applyWithSkipExisting(
|
||||
url(
|
||||
workspaceStorybookVersion === '6' ? './root-files' : './root-files-5'
|
||||
),
|
||||
[js ? toJS() : noop()]
|
||||
),
|
||||
])(tree, context);
|
||||
};
|
||||
}
|
||||
@ -92,25 +102,42 @@ function createRootStorybookDir(
|
||||
function createProjectStorybookDir(
|
||||
projectName: string,
|
||||
uiFramework: StorybookConfigureSchema['uiFramework'],
|
||||
js: boolean
|
||||
js: boolean,
|
||||
workspaceStorybookVersion: string
|
||||
): Rule {
|
||||
return (tree: Tree, context: SchematicContext) => {
|
||||
/**
|
||||
* Here, same as above
|
||||
* Check storybook version
|
||||
* and use the correct folder
|
||||
* lib-files-5 or lib-files-6
|
||||
*/
|
||||
|
||||
const projectConfig = getProjectConfig(tree, projectName);
|
||||
const { projectType } = getProjectConfig(tree, projectName);
|
||||
const projectDirectory = projectDir(projectType);
|
||||
context.logger.debug(
|
||||
`adding .storybook folder to ${projectDirectory} - using Storybook version ${workspaceStorybookVersion}`
|
||||
);
|
||||
|
||||
context.logger.debug(`adding .storybook folder to ${projectDirectory}`);
|
||||
const projectConfig = getProjectConfig(tree, projectName);
|
||||
return chain([
|
||||
applyWithSkipExisting(url('./project-files'), [
|
||||
template({
|
||||
tmpl: '',
|
||||
uiFramework,
|
||||
offsetFromRoot: offsetFromRoot(projectConfig.root),
|
||||
projectType: projectDirectory,
|
||||
}),
|
||||
move(projectConfig.root),
|
||||
js ? toJS() : noop(),
|
||||
]),
|
||||
applyWithSkipExisting(
|
||||
url(
|
||||
workspaceStorybookVersion === '6'
|
||||
? './project-files'
|
||||
: './project-files-5'
|
||||
),
|
||||
[
|
||||
template({
|
||||
tmpl: '',
|
||||
uiFramework,
|
||||
offsetFromRoot: offsetFromRoot(projectConfig.root),
|
||||
projectType: projectDirectory,
|
||||
}),
|
||||
move(projectConfig.root),
|
||||
js ? toJS() : noop(),
|
||||
]
|
||||
),
|
||||
])(tree, context);
|
||||
};
|
||||
}
|
||||
@ -228,3 +255,43 @@ function addStorybookTask(projectName: string, uiFramework: string): Rule {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function readCurrentWorkspaceStorybookVersion(): string {
|
||||
const packageJsonContents = readPackageJson();
|
||||
let workspaceStorybookVersion = storybookVersion;
|
||||
if (packageJsonContents && packageJsonContents['devDependencies']) {
|
||||
if (packageJsonContents['devDependencies']['@storybook/angular']) {
|
||||
workspaceStorybookVersion =
|
||||
packageJsonContents['devDependencies']['@storybook/angular'];
|
||||
}
|
||||
if (packageJsonContents['devDependencies']['@storybook/react']) {
|
||||
workspaceStorybookVersion =
|
||||
packageJsonContents['devDependencies']['@storybook/react'];
|
||||
}
|
||||
if (packageJsonContents['devDependencies']['@storybook/core']) {
|
||||
workspaceStorybookVersion =
|
||||
packageJsonContents['devDependencies']['@storybook/core'];
|
||||
}
|
||||
}
|
||||
if (packageJsonContents && packageJsonContents['dependencies']) {
|
||||
if (packageJsonContents['dependencies']['@storybook/angular']) {
|
||||
workspaceStorybookVersion =
|
||||
packageJsonContents['dependencies']['@storybook/angular'];
|
||||
}
|
||||
if (packageJsonContents['dependencies']['@storybook/react']) {
|
||||
workspaceStorybookVersion =
|
||||
packageJsonContents['dependencies']['@storybook/react'];
|
||||
}
|
||||
if (packageJsonContents['dependencies']['@storybook/core']) {
|
||||
workspaceStorybookVersion =
|
||||
packageJsonContents['dependencies']['@storybook/core'];
|
||||
}
|
||||
}
|
||||
if (
|
||||
workspaceStorybookVersion.startsWith('6') ||
|
||||
workspaceStorybookVersion.startsWith('^6')
|
||||
) {
|
||||
workspaceStorybookVersion = '6';
|
||||
}
|
||||
return workspaceStorybookVersion;
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "<%= offsetFromRoot %>../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"exclude": ["../**/*.spec.ts" <% if(uiFramework === '@storybook/react') { %>, "../**/*.spec.js", "../**/*.spec.tsx", "../**/*.spec.jsx"<% } %>],
|
||||
"include": ["../src/**/*"]
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
const rootWebpackConfig = require('<%= offsetFromRoot %>../.storybook/webpack.config');
|
||||
/**
|
||||
* Export a function. Accept the base config as the only param.
|
||||
*
|
||||
* @param {Parameters<typeof rootWebpackConfig>[0]} options
|
||||
*/
|
||||
module.exports = async ({ config, mode }) => {
|
||||
config = await rootWebpackConfig({ config, mode });
|
||||
|
||||
const tsPaths = new TsconfigPathsPlugin({
|
||||
configFile: './tsconfig.base.json',
|
||||
});
|
||||
|
||||
config.resolve.plugins
|
||||
? config.resolve.plugins.push(tsPaths)
|
||||
: (config.resolve.plugins = [tsPaths])
|
||||
|
||||
<% if(uiFramework === '@storybook/react') { %>
|
||||
config.resolve.extensions.push('.ts', '.tsx');
|
||||
|
||||
config.module.rules.push({
|
||||
test: /\.(ts|tsx)$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Found this here: https://github.com/nrwl/nx/issues/2859
|
||||
// And copied the part of the solution that made it work
|
||||
|
||||
const svgRuleIndex = config.module.rules.findIndex(rule => {
|
||||
const { test } = rule;
|
||||
|
||||
return test.toString().startsWith('/\\.(svg|ico');
|
||||
});
|
||||
config.module.rules[svgRuleIndex].test = /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/;
|
||||
|
||||
config.module.rules.push(
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|webp)$/,
|
||||
loader: require.resolve('url-loader'),
|
||||
options: {
|
||||
limit: 10000, // 10kB
|
||||
name: '[name].[hash:7].[ext]',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
oneOf: [
|
||||
// If coming from JS/TS file, then transform into React component using SVGR.
|
||||
{
|
||||
issuer: {
|
||||
test: /\.[jt]sx?$/,
|
||||
},
|
||||
use: [
|
||||
'@svgr/webpack?-svgo,+titleProp,+ref![path]',
|
||||
{
|
||||
loader: require.resolve('url-loader'),
|
||||
options: {
|
||||
limit: 10000, // 10kB
|
||||
name: '[name].[hash:7].[ext]',
|
||||
esModule: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// Fallback to plain URL loader.
|
||||
{
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('url-loader'),
|
||||
options: {
|
||||
limit: 10000, // 10kB
|
||||
name: '[name].[hash:7].[ext]',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
<% } %>
|
||||
return config;
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
const rootMain = require('<%= offsetFromRoot %>../.storybook/main');
|
||||
|
||||
// Use the following syntax to add addons!
|
||||
// rootMain.addons.push('');
|
||||
rootMain.stories.push(...['../src/<%= projectType %>/**/*.stories.mdx', '../src/<%= projectType %>/**/*.stories.@(js|jsx|ts|tsx)'])
|
||||
|
||||
module.exports = rootMain;
|
||||
@ -0,0 +1,4 @@
|
||||
import { addDecorator } from '<%= uiFramework %>';
|
||||
import { withKnobs } from '@storybook/addon-knobs';
|
||||
|
||||
addDecorator(withKnobs);
|
||||
@ -17,21 +17,6 @@ module.exports = async ({ config, mode }) => {
|
||||
: (config.resolve.plugins = [tsPaths])
|
||||
|
||||
<% if(uiFramework === '@storybook/react') { %>
|
||||
config.resolve.extensions.push('.ts', '.tsx');
|
||||
|
||||
config.module.rules.push({
|
||||
test: /\.(ts|tsx)$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Found this here: https://github.com/nrwl/nx/issues/2859
|
||||
// And copied the part of the solution that made it work
|
||||
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"exclude": [
|
||||
"../**/*.spec.js",
|
||||
"../**/*.spec.ts",
|
||||
"../**/*.spec.tsx",
|
||||
"../**/*.spec.jsx"
|
||||
],
|
||||
"include": ["../**/*"]
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Export a function. Accept the base config as the only param.
|
||||
* @param {Object} options
|
||||
* @param {Required<import('webpack').Configuration>} options.config
|
||||
* @param {'DEVELOPMENT' | 'PRODUCTION'} options.mode - change the build configuration. 'PRODUCTION' is used when building the static version of storybook.
|
||||
*/
|
||||
module.exports = async ({ config, mode }) => {
|
||||
// Make whatever fine-grained changes you need
|
||||
|
||||
// Return the altered config
|
||||
return config;
|
||||
};
|
||||
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
stories: [],
|
||||
addons: ['@storybook/addon-knobs/register'],
|
||||
};
|
||||
@ -30,11 +30,28 @@ function checkDependenciesInstalled(schema: Schema): Rule {
|
||||
|
||||
// base deps
|
||||
devDependencies['@nrwl/storybook'] = nxVersion;
|
||||
devDependencies['@storybook/addon-knobs'] = storybookVersion;
|
||||
devDependencies['@types/webpack'] = webpackTypesVersion;
|
||||
|
||||
/**
|
||||
* If Storybook already exists, do NOT update it to the latest version.
|
||||
* Leave it alone.
|
||||
*/
|
||||
|
||||
if (
|
||||
!packageJson.dependencies['@storybook/addon-knobs'] &&
|
||||
!packageJson.devDependencies['@storybook/addon-knobs']
|
||||
) {
|
||||
devDependencies['@storybook/addon-knobs'] = storybookVersion;
|
||||
}
|
||||
|
||||
if (isFramework('angular', schema)) {
|
||||
devDependencies['@storybook/angular'] = storybookVersion;
|
||||
if (
|
||||
!packageJson.dependencies['@storybook/angular'] &&
|
||||
!packageJson.devDependencies['@storybook/angular']
|
||||
) {
|
||||
devDependencies['@storybook/angular'] = storybookVersion;
|
||||
}
|
||||
|
||||
if (
|
||||
!packageJson.dependencies['@angular/forms'] &&
|
||||
!packageJson.devDependencies['@angular/forms']
|
||||
@ -42,6 +59,7 @@ function checkDependenciesInstalled(schema: Schema): Rule {
|
||||
devDependencies['@angular/forms'] = '*';
|
||||
}
|
||||
}
|
||||
|
||||
if (isFramework('react', schema)) {
|
||||
devDependencies['@storybook/react'] = storybookVersion;
|
||||
devDependencies['@svgr/webpack'] = svgrVersion;
|
||||
@ -51,6 +69,13 @@ function checkDependenciesInstalled(schema: Schema): Rule {
|
||||
devDependencies[
|
||||
'@babel/preset-typescript'
|
||||
] = babelPresetTypescriptVersion;
|
||||
|
||||
if (
|
||||
!packageJson.dependencies['@storybook/react'] &&
|
||||
!packageJson.devDependencies['@storybook/react']
|
||||
) {
|
||||
devDependencies['@storybook/react'] = storybookVersion;
|
||||
}
|
||||
}
|
||||
|
||||
return addDepsToPackageJson(dependencies, devDependencies);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export const nxVersion = '*';
|
||||
export const storybookVersion = '5.3.9';
|
||||
export const storybookVersion = '^6.0.21';
|
||||
export const babelCoreVersion = '7.9.6';
|
||||
export const babelLoaderVersion = '8.1.0';
|
||||
export const babelPresetTypescriptVersion = '7.9.0';
|
||||
|
||||
@ -489,6 +489,16 @@
|
||||
"glob": "**/root-files/.storybook/**",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"input": "packages/storybook",
|
||||
"glob": "**/lib-files-5/.storybook/**",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"input": "packages/storybook",
|
||||
"glob": "**/root-files-5/.storybook/**",
|
||||
"output": "/"
|
||||
},
|
||||
{
|
||||
"input": "packages/storybook",
|
||||
"glob": "**/*.json",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user