mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-31 05:03:21 +08:00
Fix useChannel tests
This commit is contained in:
commit
b07a636af9
@ -13,6 +13,7 @@ const withTests = {
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
ignore: ['./lib/codemod/src/transforms/__testfixtures__'],
|
||||
presets: [
|
||||
['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage', corejs: '3' }],
|
||||
'@babel/preset-typescript',
|
||||
@ -53,6 +54,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: './lib',
|
||||
exclude: './addons/storysource/src/loader',
|
||||
presets: [
|
||||
['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage', corejs: '3' }],
|
||||
'@babel/preset-react',
|
||||
@ -76,6 +78,7 @@ module.exports = {
|
||||
'./lib/core/src/server',
|
||||
'./lib/node-logger',
|
||||
'./lib/codemod',
|
||||
'./lib/source-loader/src',
|
||||
'./addons/storyshots',
|
||||
'./addons/storysource/src/loader',
|
||||
'./app/**/src/server/**',
|
||||
|
@ -10,6 +10,7 @@ lib/cli/test
|
||||
scripts/storage
|
||||
*.bundle.js
|
||||
*.js.map
|
||||
*.d.ts
|
||||
|
||||
!.remarkrc.js
|
||||
!.babelrc.js
|
||||
@ -18,7 +19,3 @@ scripts/storage
|
||||
!.jest.config.js
|
||||
!.storybook
|
||||
|
||||
REACT_NATIVE
|
||||
examples-native
|
||||
react-native
|
||||
ondevice-*
|
2
.github/automention.yml
vendored
2
.github/automention.yml
vendored
@ -7,7 +7,7 @@
|
||||
'app: react-native': ['benoitdion', 'gongreg']
|
||||
'app: react-native-server': ['benoitdion', 'igor-dv']
|
||||
'app: svelte': ['cam-stitt', 'plumpNation']
|
||||
'app: vue': ['backbone87', 'elevatebart']
|
||||
'app: vue': ['backbone87', 'elevatebart', 'pksunkara']
|
||||
'api: addons': ['ndelangen']
|
||||
'addon: a11y': ['CodeByAlex', 'Armanio', 'jsomsanith']
|
||||
'addon: contexts': ['leoyli']
|
||||
|
314
CHANGELOG.md
314
CHANGELOG.md
@ -1,3 +1,188 @@
|
||||
## 5.2.0-alpha.32 (June 29, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* Addon-docs: Add .story.mdx support to preset ([#7229](https://github.com/storybookjs/storybook/pull/7229))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* React-native: Fix react native server ([#7187](https://github.com/storybookjs/storybook/pull/7187))
|
||||
* Addon-docs: Fix source-loader in monorepo examples ([#7214](https://github.com/storybookjs/storybook/pull/7214))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Addon-docs: Convert repo stories to new module format ([#7175](https://github.com/storybookjs/storybook/pull/7175))
|
||||
|
||||
## 5.2.0-alpha.31 (June 27, 2019)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Module format: story field for name/parameters annotation ([#7202](https://github.com/storybookjs/storybook/pull/7202))
|
||||
|
||||
### Features
|
||||
|
||||
* Core: Story sorting ([#6472](https://github.com/storybookjs/storybook/pull/6472))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Addon-docs: Fix source-loader CI errors ([#7203](https://github.com/storybookjs/storybook/pull/7203))
|
||||
|
||||
## 5.2.0-alpha.30 (June 25, 2019)
|
||||
|
||||
This release merges `release/docs-technical-preview` branch back into `next` through a series of PRs. It also contains other changes that came in on `next` since the last alpha.
|
||||
|
||||
### Features
|
||||
|
||||
* CLI: Add info command to print environment information ([#6937](https://github.com/storybookjs/storybook/pull/6937))
|
||||
* CLI: Use process.env.CI if available ([#7118](https://github.com/storybookjs/storybook/pull/7118))
|
||||
* Addon-docs: Source loader library ([#7117](https://github.com/storybookjs/storybook/pull/7117))
|
||||
* Addon-docs: Support non-story exports in MDX ([#7188](https://github.com/storybookjs/storybook/pull/7188))
|
||||
* Addon-docs: Support non-story exports in module format ([#7185](https://github.com/storybookjs/storybook/pull/7185))
|
||||
* Addon-docs: Docs mode with `--docs` flag ([#7154](https://github.com/storybookjs/storybook/pull/7154))
|
||||
* Addon-docs: Convert to module format codemod ([#7174](https://github.com/storybookjs/storybook/pull/7174))
|
||||
* Addon-docs: MDX support ([#7145](https://github.com/storybookjs/storybook/pull/7145))
|
||||
* Addon-docs: Component parameter codemod ([#7155](https://github.com/storybookjs/storybook/pull/7155))
|
||||
* Addon-docs: DocsPage and doc blocks ([#7119](https://github.com/storybookjs/storybook/pull/7119))
|
||||
* Addon-docs: Module story format & framework param ([#7110](https://github.com/storybookjs/storybook/pull/7110))
|
||||
* Addon-docs: Basic skeleton, UI viewMode handling ([#7107](https://github.com/storybookjs/storybook/pull/7107))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Addon-backgrounds: Fix unstretched preview background wrapper ([#7173](https://github.com/storybookjs/storybook/pull/7173))
|
||||
* Addon-notes/info: Fix indenting on markdown code blocks ([#7158](https://github.com/storybookjs/storybook/pull/7158))
|
||||
* Core: Improve HMR error reporting, no refreshes needed for error recovery ([#6972](https://github.com/storybookjs/storybook/pull/6972))
|
||||
* Addon-info: change stylesheetBase info height from 110vh to 100vh ([#7141](https://github.com/storybookjs/storybook/pull/7141))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Typescript: Migrate addon viewport ([#7177](https://github.com/storybookjs/storybook/pull/7177))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* Bump css-loader from 2.1.1 to 3.0.0 ([#7122](https://github.com/storybookjs/storybook/pull/7122))
|
||||
* Upgrade core-js to 3.x in devkits ([#7171](https://github.com/storybookjs/storybook/pull/7171))
|
||||
* UPGRADE lazy-universal-dotenv ([#7151](https://github.com/storybookjs/storybook/pull/7151))
|
||||
|
||||
## 5.1.9 (June 20, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Fix JSON babel config error reporting ([#7104](https://github.com/storybookjs/storybook/pull/7104))
|
||||
* UI: Fix about page version check message ([#7105](https://github.com/storybookjs/storybook/pull/7105))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* Add missing dependencies to ui/react ([#7081](https://github.com/storybookjs/storybook/pull/7081))
|
||||
* UPGRADE lazy-universal-dotenv ([#7151](https://github.com/storybookjs/storybook/pull/7151))
|
||||
* Make compatible with yarn Pnp ([#6922](https://github.com/storybookjs/storybook/pull/6922))
|
||||
|
||||
## 5.2.0-alpha.29 (June 17, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* Addon-notes: enable multiple sections in notes panel ([#6861](https://github.com/storybookjs/storybook/pull/6861))
|
||||
* Addon-context: title fallback ([#7078](https://github.com/storybookjs/storybook/pull/7078))
|
||||
* Addon-info: Fix rendering of code block ([#6016](https://github.com/storybookjs/storybook/pull/6016))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Fix JSON babel config error reporting ([#7104](https://github.com/storybookjs/storybook/pull/7104))
|
||||
* UI: Fix about page version check message ([#7105](https://github.com/storybookjs/storybook/pull/7105))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Core: Refactor story_store ([#6382](https://github.com/storybookjs/storybook/pull/6382))
|
||||
* Core: Make compatible with yarn Pnp ([#6922](https://github.com/storybookjs/storybook/pull/6922))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* Bump jest-expo from 32.0.1 to 33.0.2 ([#6996](https://github.com/storybookjs/storybook/pull/6996))
|
||||
|
||||
## 5.2.0-alpha.28 (June 17, 2019)
|
||||
|
||||
Publish failed
|
||||
|
||||
## 5.2.0-alpha.27 (June 17, 2019)
|
||||
|
||||
* CLI: improve bootstrap list ([#6993](https://github.com/storybookjs/storybook/pull/6993))
|
||||
* CLI: replaced merge-dirs dependency by fs-extra ([#7100](https://github.com/storybookjs/storybook/pull/7100))
|
||||
|
||||
## 5.1.8 (June 14, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* CLI: Fix RN template to not import addons ([#7096](https://github.com/storybookjs/storybook/pull/7096))
|
||||
|
||||
## 5.1.7 (June 14, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* UI: Fix warning of loading prop not being a string ([#7080](https://github.com/storybookjs/storybook/pull/7080))
|
||||
|
||||
## 5.1.6 (June 14, 2019)
|
||||
|
||||
Publish failed
|
||||
|
||||
## 5.1.5 (June 14, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Upgrade plugin core-js fix ([#7086](https://github.com/storybookjs/storybook/pull/7086))
|
||||
* UI: Fix sidebar loading visibility ([#7073](https://github.com/storybookjs/storybook/pull/7073))
|
||||
* UI: Fix unnecessary large bundlesize ([#7091](https://github.com/storybookjs/storybook/pull/7091))
|
||||
* Addon-contexts, RN-server: Add core-js dep ([#7094](https://github.com/storybookjs/storybook/pull/7094))
|
||||
|
||||
## 5.2.0-alpha.26 (June 14, 2019)
|
||||
|
||||
- Merge in changes from 5.1.7/next branch.
|
||||
- Fix earlier merge problems relating to addon-docs:
|
||||
- Restore `--docs` command-line functionality
|
||||
- Fix refreshing docs page bug
|
||||
|
||||
## 5.2.0-alpha.25 (June 14, 2019)
|
||||
|
||||
Publish failed
|
||||
|
||||
## 5.1.4 (June 13, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Fix core-js 3 errors ([#7051](https://github.com/storybookjs/storybook/pull/7051))
|
||||
* UI: Fix syntax highlighter plain text not visible ([#7057](https://github.com/storybookjs/storybook/pull/7057))
|
||||
* Addon-actions: Add default options to action(s) ([#6438](https://github.com/storybookjs/storybook/pull/6438))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* fix: add missing core-js dependency ([#7016](https://github.com/storybookjs/storybook/pull/7016))
|
||||
* chore: set react version to 16.8.3 to match react native ([#7008](https://github.com/storybookjs/storybook/pull/7008))
|
||||
|
||||
## 5.2.0-alpha.24 (June 13, 2019)
|
||||
|
||||
Merge in changes from 5.1.3/next branch.
|
||||
|
||||
## 5.2.0-alpha.23 (June 10, 2019)
|
||||
|
||||
Merge in changes from 5.1.3/next branch. Releasing from the addon-docs branch to keep things moving until we can merge addon-docs into next.
|
||||
|
||||
## 5.2.0-alpha.22 (June 7, 2019)
|
||||
|
||||
- Merge in changes from 5.1.1
|
||||
- Addon-docs:
|
||||
- Inline stories respect height prop
|
||||
- Export Description block
|
||||
|
||||
## 5.1.3 (June 6, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* UI: Fix links that are not working with plain left click ([#6970](https://github.com/storybookjs/storybook/pull/6970))
|
||||
* Core: Don't redefine `process` variable ([#6991](https://github.com/storybookjs/storybook/pull/6991))
|
||||
* Core: Don't mutate user's babel config ([#6987](https://github.com/storybookjs/storybook/pull/6987))
|
||||
|
||||
## 5.1.2 (June 6, 2019)
|
||||
|
||||
Publish failed
|
||||
|
||||
## 5.1.1 (June 5, 2019)
|
||||
|
||||
Storybook 5.1 is a juicy upgrade including:
|
||||
@ -42,6 +227,16 @@ Publish failed
|
||||
* Core: Fix webpack `process.*` variable definitions ([#6946](https://github.com/storybookjs/storybook/pull/6946))
|
||||
* Angular: Fix tsconfig.app.json detection for Angular 8 ([#6940](https://github.com/storybookjs/storybook/pull/6940))
|
||||
|
||||
## 5.2.0-alpha.21 (June 2, 2019)
|
||||
|
||||
- Core: Convert module format to use default export for metadata
|
||||
- Addon-docs: Compile MDX to default export modules format
|
||||
- Source-loader: Support parameter injection for default export metadata
|
||||
|
||||
## 5.2.0-alpha.20 (May 31, 2019)
|
||||
|
||||
- Addon-docs: Use Meta doc block instead of exporting componentMeta
|
||||
|
||||
## 5.1.0-rc.3 (May 29, 2019)
|
||||
|
||||
### Features
|
||||
@ -62,12 +257,46 @@ Publish failed
|
||||
* Bump ts-node from 8.1.0 to 8.2.0 ([#6890](https://github.com/storybookjs/storybook/pull/6890))
|
||||
* Bump svelte from 3.4.2 to 3.4.4 ([#6892](https://github.com/storybookjs/storybook/pull/6892))
|
||||
|
||||
## 5.2.0-alpha.19 (May 28, 2019)
|
||||
|
||||
- Source-loader: Fix bad package dependencies
|
||||
|
||||
## 5.1.0-rc.2 (May 27, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Fix JS/JSON loading babel config ([#6878](https://github.com/storybookjs/storybook/pull/6878))
|
||||
|
||||
## 5.2.0-alpha.18 (May 26, 2019)
|
||||
|
||||
- Addon-docs: Codemod for adding component parameters
|
||||
- Core: Babel config loading bugfix ([#6878](https://github.com/storybookjs/storybook/pull/6878))
|
||||
|
||||
## 5.2.0-alpha.17 (May 26, 2019)
|
||||
|
||||
- Addon-docs: Refer to selected story/component with `id="."` / `of="."`
|
||||
|
||||
## 5.2.0-alpha.16 (May 25, 2019)
|
||||
|
||||
- Addon-docs: Auto-configure `inlineStories` & `getPropDefs` based on framework
|
||||
|
||||
## 5.2.0-alpha.15 (May 25, 2019)
|
||||
|
||||
- Addon-docs: Expanded Vue support
|
||||
- Props table support
|
||||
- iframeHeight configuration parameter
|
||||
|
||||
## 5.2.0-alpha.14 (May 25, 2019)
|
||||
|
||||
- Addon-docs: Expanded source formats via `@storybook/source-loader`
|
||||
- Legacy `storiesOf` format x (JS / TSX)
|
||||
- Component modules format x (JS / TSX)
|
||||
- Component MDX format
|
||||
|
||||
## 5.2.0-alpha.13 (May 24, 2019)
|
||||
|
||||
- Addon-docs: Add documentation-only `--docs` option to build storybook
|
||||
|
||||
## 5.1.0-rc.1 (May 24, 2019)
|
||||
|
||||
### Features
|
||||
@ -122,6 +351,29 @@ Publish failed
|
||||
* Bump svelte from 3.4.1 to 3.4.2 ([#6838](https://github.com/storybookjs/storybook/pull/6838))
|
||||
* Misc upgrades ([#6820](https://github.com/storybookjs/storybook/pull/6820))
|
||||
|
||||
## 5.2.0-alpha.12 (May 21, 2019)
|
||||
|
||||
- Addon-docs: Fix regression in preview source for legacy stories
|
||||
|
||||
## 5.2.0-alpha.11 (May 21, 2019)
|
||||
|
||||
- Addon-docs:
|
||||
- Source refer to stories by name
|
||||
- Source support for multi-story previews
|
||||
- Fix loader bug for plaintext stories
|
||||
|
||||
## 5.2.0-alpha.10 (May 19, 2019)
|
||||
|
||||
- Addon-docs: Display source dropdown in preview component
|
||||
|
||||
## 5.2.0-alpha.9 (May 17, 2019)
|
||||
|
||||
- Addon-docs bugfixes:
|
||||
- Fix broken components stories
|
||||
- Fix regression in iframe preview
|
||||
- Fix docgen props block
|
||||
- Fix margin styling on docs page
|
||||
|
||||
## 5.1.0-beta.1 (May 16, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
@ -139,6 +391,49 @@ Publish failed
|
||||
|
||||
* Bump fs-extra from 7.0.1 to 8.0.1 ([#6776](https://github.com/storybookjs/storybook/pull/6776))
|
||||
|
||||
## 5.2.0-alpha.8 (May 15, 2019)
|
||||
|
||||
- Addon-docs: Optimize docs pane rerendering
|
||||
|
||||
## 5.2.0-alpha.7 (May 15, 2019)
|
||||
|
||||
- Addon-docs: Docs page bugfix
|
||||
- Addon-docs: Fix source block for legacy stories
|
||||
|
||||
NOTE: use `@storybook/addon-storysource/loader` with option `injectParameters: true` for legacy source
|
||||
|
||||
## 5.2.0-alpha.6 (May 14, 2019)
|
||||
|
||||
- Addon-docs: Docs page content update
|
||||
- Addon-docs: Preview component redefinition
|
||||
|
||||
#### Breaking changes
|
||||
|
||||
Preview behavior has been updated. Docs page content has been updated.
|
||||
|
||||
Before:
|
||||
|
||||
- `<Story name="a">` defines a story, `<Preview id="x--a"/>` references it
|
||||
|
||||
After:
|
||||
|
||||
- `<Story name="a">` defines a story, `<Story id="x--a"/>` references it
|
||||
- `<Preview><Story .../><Story .../><Component/></Preview>` shows one or more stories in a grid
|
||||
|
||||
## 5.2.0-alpha.5 (May 12, 2019)
|
||||
|
||||
- Addon-docs: Description block refactor and bugfixes
|
||||
|
||||
## 5.2.0-alpha.4 (May 11, 2019)
|
||||
|
||||
- Addon-docs: Source, Props, DocsPage doc blocks
|
||||
|
||||
#### Breaking changes
|
||||
|
||||
- Doc blocks & presets have moved. Update your MDX stories and `presets.js` file accordingly:
|
||||
- `import { Preview, Story } from '@storybook/addon-docs/blocks';
|
||||
- `module.exports = ['@storybook/addon-docs/common/preset'];`
|
||||
|
||||
## 5.1.0-beta.0 (May 10, 2019)
|
||||
|
||||
Welcome to the 5.1 beta! Feature development's done; `beta.0` kicks off the stabilization process for the 5.1 final release. 🚀
|
||||
@ -204,6 +499,25 @@ Failed publish
|
||||
|
||||
- CLI: Refactor how we install dev dependencies in cli ([#6695](https://github.com/storybookjs/storybook/pull/6695))
|
||||
|
||||
## 5.2.0-alpha.3 (May 1, 2019)
|
||||
|
||||
- Addon-docs: Add Story decorator and parameter support
|
||||
- Addon-docs: Remove need for extra project babelrc
|
||||
|
||||
## 5.2.0-alpha.2 (April 30, 2019)
|
||||
|
||||
- Addon-docs: Streamline setup, fix MDX dependencies, improve MDX import, and update guide
|
||||
|
||||
## 5.2.0-alpha.0 (April 29, 2019)
|
||||
|
||||
Storybook Docs technical preview:
|
||||
|
||||
- Docs addon
|
||||
- MDX story format
|
||||
- Module story format
|
||||
- Load API
|
||||
- [Guide](https://docs.google.com/document/d/1un6YX7xDKEKl5-MVb-egnOYN8dynb5Hf7mq0hipk8JE/edit?usp=sharing)
|
||||
|
||||
## 5.0.11 (April 28, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
11
MIGRATION.md
11
MIGRATION.md
@ -1,5 +1,7 @@
|
||||
# Migration
|
||||
|
||||
- [From version 5.1.x to 5.2.x](#from-version-51x-to-52x)
|
||||
- [Docs mode docgen](#docs-mode-docgen)
|
||||
- [From version 5.0.x to 5.1.x](#from-version-50x-to-51x)
|
||||
- [React native server](#react-native-server)
|
||||
- [Angular 7](#angular-7)
|
||||
@ -56,6 +58,15 @@
|
||||
- [Packages renaming](#packages-renaming)
|
||||
- [Deprecated embedded addons](#deprecated-embedded-addons)
|
||||
|
||||
## From version 5.1.x to 5.2.x
|
||||
|
||||
### Docs mode docgen
|
||||
|
||||
This isn't a breaking change per se, because `addon-docs` is a new feature. However it's intended to replace `addon-info`, so if you're migrating from `addon-info` there are a few things you should know:
|
||||
|
||||
1. Support for only one prop table
|
||||
2. Prop table docgen info should be stored on the component and not in the global variable `STORYBOOK_REACT_CLASSES` as before.
|
||||
|
||||
## From version 5.0.x to 5.1.x
|
||||
|
||||
### React native server
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-a11y",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "a11y addon for storybook",
|
||||
"keywords": [
|
||||
"a11y",
|
||||
@ -26,12 +26,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"axe-core": "^3.2.2",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-actions",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Action Logger addon for storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -21,12 +21,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/client-api": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-api": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-backgrounds",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -25,12 +25,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"memoizerific": "^1.11.3",
|
||||
"react": "^16.8.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-centered",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook decorator to center components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-contexts",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook Addon Contexts",
|
||||
"keywords": [
|
||||
"storybook",
|
||||
@ -28,10 +28,10 @@
|
||||
"dev:check-types": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-cssresources",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "A storybook addon to switch between css resources at runtime for your story",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -25,10 +25,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-design-assets",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Design asset preview for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -11,13 +11,13 @@
|
||||
"files",
|
||||
"viewer"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook#readme",
|
||||
"homepage": "https://github.com/storybookjs/storybook#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
"url": "https://github.com/storybookjs/storybook/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/storybooks/storybook.git",
|
||||
"url": "git+https://github.com/storybookjs/storybook.git",
|
||||
"directory": "addons/design-assets"
|
||||
},
|
||||
"license": "MIT",
|
||||
@ -27,14 +27,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.5",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
"use-image": "^1.0.3"
|
||||
|
@ -1,3 +1,88 @@
|
||||
# Storybook Docs
|
||||
|
||||
Living documentation for your components.
|
||||
|
||||
- [Sneak peak article](https://medium.com/storybookjs/storybook-docs-sneak-peak-5be78445094a)
|
||||
- [Technical preview guide](https://docs.google.com/document/d/1un6YX7xDKEKl5-MVb-egnOYN8dynb5Hf7mq0hipk8JE/edit?usp=sharing)
|
||||
|
||||
## View layer support
|
||||
|
||||
Docs supports all view layers that Storybook supports except for React Native (currently). There are some view-layer specific
|
||||
features as well. This chart captures the current state of support
|
||||
|
||||
| | React | Vue | Angular | Polymer | Mithril | HTML | Marko | Svelte | Riot | Ember | Preact |
|
||||
| -------------- | :---: | :-: | :-----: | :-----: | :-----: | :--: | :---: | :----: | :--: | :---: | :----: |
|
||||
| MDX stories | + | + | + | + | + | + | + | + | + | + | + |
|
||||
| Module stories | + | + | + | + | + | + | + | + | + | + | + |
|
||||
| Legacy stories | + | + | + | + | + | + | + | + | + | + | + |
|
||||
| Source \* | + | + | + | + | + | + | + | + | + | + | + |
|
||||
| Notes / Info | + | + | + | + | + | + | + | + | + | + | + |
|
||||
| Props table | + | # | # | | | | | | | | |
|
||||
| Docgen | + | # | # | | | | | | | | |
|
||||
| Inline stories | + | # | | | | | | | | | |
|
||||
|
||||
**Notes:**
|
||||
|
||||
- `#` denotes planned/WIP support
|
||||
- \* Source supports legacy `JS storiesOf` and `MDX` stories. `Typescript` and new `module format` support is WIP
|
||||
|
||||
## Installation
|
||||
|
||||
First add the package. Make sure that the versions for your `@storybook/*` packages match:
|
||||
|
||||
```sh
|
||||
yarn add -D @storybook/addon-docs
|
||||
```
|
||||
|
||||
The add the following line to your `.storybook/presets.js` file:
|
||||
|
||||
```js
|
||||
module.exports = ['@storybook/addon-docs/react/preset'];
|
||||
```
|
||||
|
||||
Finally, import your stories and MDX files in `.storybook/config.js`:
|
||||
|
||||
```js
|
||||
import { load } from '@storybook/react';
|
||||
|
||||
// standard configuration here
|
||||
// ...
|
||||
|
||||
// wherever your story files are located
|
||||
load(require.context('../src', true, /\.stories\.js$/), module);
|
||||
load(require.context('../src', true, /\.stories\.mdx$/), module);
|
||||
```
|
||||
|
||||
## Manual configuration
|
||||
|
||||
Docs uses Storybook presets as a configuration shortcut. To configure "the long way", first register the addon in `.storybook/addons.js`:
|
||||
|
||||
```js
|
||||
import '@storybook/addon-docs/register';
|
||||
```
|
||||
|
||||
Then configure Storybook's webpack loader to understand MDX files in `.storybook/webpack.config.js`:
|
||||
|
||||
```js
|
||||
const createCompiler = require('@storybook/addon-docs/mdx-compiler-plugin');
|
||||
|
||||
module.exports = async ({ config }) => {
|
||||
config.module.rules.push({
|
||||
test: /\.mdx$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
// may or may not need this line depending on your app's setup
|
||||
plugins: ['@babel/plugin-transform-react-jsx'],
|
||||
},
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
options: {
|
||||
compilers: [createCompiler({})],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
return config;
|
||||
};
|
||||
```
|
||||
|
612
addons/docs/__snapshots__/mdx-compiler-plugin.test.js.snap
Normal file
612
addons/docs/__snapshots__/mdx-compiler-plugin.test.js.snap
Normal file
@ -0,0 +1,612 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports "smart" current story 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<h1>{\`Current story\`}</h1>
|
||||
<Story id=\\".\\" mdxType=\\"Story\\" />
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
const componentMeta = { includeStories: [] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports decorators 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta
|
||||
title=\\"Button\\"
|
||||
decorators={[
|
||||
storyFn => (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'yellow',
|
||||
}}
|
||||
>
|
||||
{storyFn()}
|
||||
</div>
|
||||
),
|
||||
]}
|
||||
mdxType=\\"Meta\\"
|
||||
/>
|
||||
<h1>{\`Decorated story\`}</h1>
|
||||
<Story name=\\"one\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">One</Button>
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const one = () => <Button>One</Button>;
|
||||
one.story = {};
|
||||
one.story.parameters = { mdxSource: \`<Button>One</Button>\` };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
decorators: [
|
||||
storyFn => (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'yellow',
|
||||
}}
|
||||
>
|
||||
{storyFn()}
|
||||
</div>
|
||||
),
|
||||
],
|
||||
includeStories: ['one'],
|
||||
};
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports non-story exports 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
export const two = 2;
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {
|
||||
two,
|
||||
};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"Button\\" mdxType=\\"Meta\\" />
|
||||
<h1>{\`Story definition\`}</h1>
|
||||
<Story name=\\"one\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">One</Button>
|
||||
</Story>
|
||||
|
||||
<Story name=\\"hello story\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Hello button</Button>
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const one = () => <Button>One</Button>;
|
||||
one.story = {};
|
||||
one.story.parameters = { mdxSource: \`<Button>One</Button>\` };
|
||||
|
||||
export const helloStory = () => <Button>Hello button</Button>;
|
||||
helloStory.story = {};
|
||||
helloStory.story.name = 'hello story';
|
||||
helloStory.story.parameters = { mdxSource: \`<Button>Hello button</Button>\` };
|
||||
|
||||
const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports object-style story definitions 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Welcome, Button } from '@storybook/angular/demo';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"MDX|Welcome\\" mdxType=\\"Meta\\" />
|
||||
<h1>{\`Story object\`}</h1>
|
||||
<Story name=\\"to storybook\\" height=\\"300px\\" mdxType=\\"Story\\">
|
||||
{{
|
||||
template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`,
|
||||
props: {
|
||||
showApp: linkTo('Button'),
|
||||
},
|
||||
moduleMetadata: {
|
||||
declarations: [Welcome],
|
||||
},
|
||||
}}
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const toStorybook = () => ({
|
||||
template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`,
|
||||
props: {
|
||||
showApp: linkTo('Button'),
|
||||
},
|
||||
moduleMetadata: {
|
||||
declarations: [Welcome],
|
||||
},
|
||||
});
|
||||
toStorybook.story = {};
|
||||
toStorybook.story.name = 'to storybook';
|
||||
toStorybook.story.parameters = {
|
||||
mdxSource: \`{
|
||||
template: \\\\\`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\\\\\`,
|
||||
props: {
|
||||
showApp: linkTo('Button')
|
||||
},
|
||||
moduleMetadata: {
|
||||
declarations: [Welcome]
|
||||
}
|
||||
}\`,
|
||||
};
|
||||
|
||||
const componentMeta = { title: 'MDX|Welcome', includeStories: ['toStorybook'] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports parameters 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta
|
||||
title=\\"Button\\"
|
||||
parameters={{
|
||||
component: Button,
|
||||
notes: 'component notes',
|
||||
}}
|
||||
mdxType=\\"Meta\\"
|
||||
/>
|
||||
<Story name=\\"component notes\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Component notes</Button>
|
||||
</Story>
|
||||
<Story
|
||||
name=\\"story notes\\"
|
||||
parameters={{
|
||||
notes: 'story notes',
|
||||
}}
|
||||
mdxType=\\"Story\\"
|
||||
>
|
||||
<Button mdxType=\\"Button\\">Story notes</Button>
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const componentNotes = () => <Button>Component notes</Button>;
|
||||
componentNotes.story = {};
|
||||
componentNotes.story.name = 'component notes';
|
||||
componentNotes.story.parameters = { mdxSource: \`<Button>Component notes</Button>\` };
|
||||
|
||||
export const storyNotes = () => <Button>Story notes</Button>;
|
||||
storyNotes.story = {};
|
||||
storyNotes.story.name = 'story notes';
|
||||
storyNotes.story.parameters = {
|
||||
mdxSource: \`<Button>Story notes</Button>\`,
|
||||
...{
|
||||
notes: 'story notes',
|
||||
},
|
||||
};
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
parameters: {
|
||||
component: Button,
|
||||
notes: 'component notes',
|
||||
},
|
||||
includeStories: ['componentNotes', 'storyNotes'],
|
||||
};
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports previews 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Preview, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta
|
||||
title=\\"Button\\"
|
||||
parameters={{
|
||||
component: Button,
|
||||
notes: 'component notes',
|
||||
}}
|
||||
mdxType=\\"Meta\\"
|
||||
/>
|
||||
<h1>{\`Preview\`}</h1>
|
||||
<p>{\`Previews can contain normal components, stories, and story references\`}</p>
|
||||
<Preview mdxType=\\"Preview\\">
|
||||
<Button mdxType=\\"Button\\">Just a button</Button>
|
||||
<Story name=\\"hello button\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Hello button</Button>
|
||||
</Story>
|
||||
<Story name=\\"two\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Two</Button>
|
||||
</Story>
|
||||
<Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" />
|
||||
</Preview>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const helloButton = () => <Button>Hello button</Button>;
|
||||
helloButton.story = {};
|
||||
helloButton.story.name = 'hello button';
|
||||
helloButton.story.parameters = { mdxSource: \`<Button>Hello button</Button>\` };
|
||||
|
||||
export const two = () => <Button>Two</Button>;
|
||||
two.story = {};
|
||||
two.story.parameters = { mdxSource: \`<Button>Two</Button>\` };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
parameters: {
|
||||
component: Button,
|
||||
notes: 'component notes',
|
||||
},
|
||||
includeStories: ['helloButton', 'two'],
|
||||
};
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports story definitions 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"Button\\" mdxType=\\"Meta\\" />
|
||||
<h1>{\`Story definition\`}</h1>
|
||||
<Story name=\\"one\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">One</Button>
|
||||
</Story>
|
||||
<Story name=\\"hello story\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Hello button</Button>
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const one = () => <Button>One</Button>;
|
||||
one.story = {};
|
||||
one.story.parameters = { mdxSource: \`<Button>One</Button>\` };
|
||||
|
||||
export const helloStory = () => <Button>Hello button</Button>;
|
||||
helloStory.story = {};
|
||||
helloStory.story.name = 'hello story';
|
||||
helloStory.story.parameters = { mdxSource: \`<Button>Hello button</Button>\` };
|
||||
|
||||
const componentMeta = { title: 'Button', includeStories: ['one', 'helloStory'] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports story references 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<h1>{\`Story reference\`}</h1>
|
||||
<Story id=\\"welcome--welcome\\" mdxType=\\"Story\\" />
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
const componentMeta = { includeStories: [] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports text-only story definitions 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"Text\\" mdxType=\\"Meta\\" />
|
||||
<h1>{\`Story definition\`}</h1>
|
||||
<Story name=\\"text\\" mdxType=\\"Story\\">
|
||||
Plain text
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const text = () => 'Plain text';
|
||||
text.story = {};
|
||||
text.story.parameters = { mdxSource: \`'Plain text'\` };
|
||||
|
||||
const componentMeta = { title: 'Text', includeStories: ['text'] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin supports vanilla mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<h1>{\`Hello MDX\`}</h1>
|
||||
<p>{\`This is some random content.\`}</p>
|
||||
<Button mdxType=\\"Button\\">Hello button</Button>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
const componentMeta = { includeStories: [] };
|
||||
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => (
|
||||
<DocsContainer context={{ ...context, mdxKind }} content={MDXContent} />
|
||||
);
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
1
addons/docs/blocks.js
Normal file
1
addons/docs/blocks.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./dist/blocks');
|
2
addons/docs/common/index.js
Normal file
2
addons/docs/common/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// FIXME: move this to typescript and src/react folder
|
||||
module.exports = require('../dist/lib/getPropDefs');
|
66
addons/docs/common/preset.js
Normal file
66
addons/docs/common/preset.js
Normal file
@ -0,0 +1,66 @@
|
||||
const createCompiler = require('../mdx-compiler-plugin');
|
||||
|
||||
function createBabelOptions({ babelOptions, configureJSX }) {
|
||||
if (!configureJSX) {
|
||||
return babelOptions;
|
||||
}
|
||||
|
||||
return {
|
||||
...babelOptions,
|
||||
// for frameworks that are not working with react, we need to configure
|
||||
// the jsx to transpile mdx, for now there will be a flag for that
|
||||
// for more complex solutions we can find alone that we need to add '@babel/plugin-transform-react-jsx'
|
||||
plugins: [...babelOptions.plugins, '@babel/plugin-transform-react-jsx'],
|
||||
};
|
||||
}
|
||||
|
||||
function webpack(webpackConfig = {}, options = {}) {
|
||||
const { module = {} } = webpackConfig;
|
||||
// it will reuse babel options that are already in use in storybook
|
||||
// also, these babel options are chained with other presets.
|
||||
const { babelOptions, configureJSX } = options;
|
||||
|
||||
return {
|
||||
...webpackConfig,
|
||||
module: {
|
||||
...module,
|
||||
rules: [
|
||||
...(module.rules || []),
|
||||
{
|
||||
test: /\.(stories|story).mdx$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: createBabelOptions({ babelOptions, configureJSX }),
|
||||
},
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
options: {
|
||||
compilers: [createCompiler(options)],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.mdx$/,
|
||||
exclude: /\.(stories|story).mdx$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: createBabelOptions({ babelOptions, configureJSX }),
|
||||
},
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function addons(entry = []) {
|
||||
return [...entry, require.resolve('../register')];
|
||||
}
|
||||
|
||||
module.exports = { webpack, addons };
|
13
addons/docs/fixtures/decorators.mdx
Normal file
13
addons/docs/fixtures/decorators.mdx
Normal file
@ -0,0 +1,13 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta
|
||||
title="Button"
|
||||
decorators={[storyFn => <div style={{ backgroundColor: 'yellow' }}>{storyFn()}</div>]}
|
||||
/>
|
||||
|
||||
# Decorated story
|
||||
|
||||
<Story name="one">
|
||||
<Button>One</Button>
|
||||
</Story>
|
16
addons/docs/fixtures/non-story-exports.mdx
Normal file
16
addons/docs/fixtures/non-story-exports.mdx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Button" />
|
||||
|
||||
# Story definition
|
||||
|
||||
<Story name="one">
|
||||
<Button>One</Button>
|
||||
</Story>
|
||||
|
||||
export const two = 2;
|
||||
|
||||
<Story name="hello story">
|
||||
<Button>Hello button</Button>
|
||||
</Story>
|
12
addons/docs/fixtures/parameters.mdx
Normal file
12
addons/docs/fixtures/parameters.mdx
Normal file
@ -0,0 +1,12 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Button" parameters={{ component: Button, notes: 'component notes' }} />
|
||||
|
||||
<Story name="component notes">
|
||||
<Button>Component notes</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="story notes" parameters={{ notes: 'story notes' }}>
|
||||
<Button>Story notes</Button>
|
||||
</Story>
|
19
addons/docs/fixtures/previews.mdx
Normal file
19
addons/docs/fixtures/previews.mdx
Normal file
@ -0,0 +1,19 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Preview, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Button" parameters={{ component: Button, notes: 'component notes' }} />
|
||||
|
||||
# Preview
|
||||
|
||||
Previews can contain normal components, stories, and story references
|
||||
|
||||
<Preview>
|
||||
<Button>Just a button</Button>
|
||||
<Story name="hello button">
|
||||
<Button>Hello button</Button>
|
||||
</Story>
|
||||
<Story name="two">
|
||||
<Button>Two</Button>
|
||||
</Story>
|
||||
<Story id="welcome--welcome" />
|
||||
</Preview>
|
5
addons/docs/fixtures/story-current.mdx
Normal file
5
addons/docs/fixtures/story-current.mdx
Normal file
@ -0,0 +1,5 @@
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
# Current story
|
||||
|
||||
<Story id="." />
|
7
addons/docs/fixtures/story-def-text-only.mdx
Normal file
7
addons/docs/fixtures/story-def-text-only.mdx
Normal file
@ -0,0 +1,7 @@
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Text" />
|
||||
|
||||
# Story definition
|
||||
|
||||
<Story name="text">Plain text</Story>
|
14
addons/docs/fixtures/story-definitions.mdx
Normal file
14
addons/docs/fixtures/story-definitions.mdx
Normal file
@ -0,0 +1,14 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Button" />
|
||||
|
||||
# Story definition
|
||||
|
||||
<Story name="one">
|
||||
<Button>One</Button>
|
||||
</Story>
|
||||
|
||||
<Story name="hello story">
|
||||
<Button>Hello button</Button>
|
||||
</Story>
|
10
addons/docs/fixtures/story-missing-props.mdx
Normal file
10
addons/docs/fixtures/story-missing-props.mdx
Normal file
@ -0,0 +1,10 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="Button" />
|
||||
|
||||
# Bad story
|
||||
|
||||
<Story>
|
||||
<Button>One</Button>
|
||||
</Story>
|
19
addons/docs/fixtures/story-object.mdx
Normal file
19
addons/docs/fixtures/story-object.mdx
Normal file
@ -0,0 +1,19 @@
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Welcome, Button } from '@storybook/angular/demo';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
|
||||
<Meta title="MDX|Welcome" />
|
||||
|
||||
# Story object
|
||||
|
||||
<Story name="to storybook" height="300px">
|
||||
{{
|
||||
template: `<storybook-welcome-component (showApp)="showApp()"></storybook-welcome-component>`,
|
||||
props: {
|
||||
showApp: linkTo('Button'),
|
||||
},
|
||||
moduleMetadata: {
|
||||
declarations: [Welcome],
|
||||
},
|
||||
}}
|
||||
</Story>
|
5
addons/docs/fixtures/story-references.mdx
Normal file
5
addons/docs/fixtures/story-references.mdx
Normal file
@ -0,0 +1,5 @@
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
# Story reference
|
||||
|
||||
<Story id="welcome--welcome" />
|
7
addons/docs/fixtures/vanilla.mdx
Normal file
7
addons/docs/fixtures/vanilla.mdx
Normal file
@ -0,0 +1,7 @@
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
# Hello MDX
|
||||
|
||||
This is some random content.
|
||||
|
||||
<Button>Hello button</Button>
|
222
addons/docs/mdx-compiler-plugin.js
Normal file
222
addons/docs/mdx-compiler-plugin.js
Normal file
@ -0,0 +1,222 @@
|
||||
const mdxToJsx = require('@mdx-js/mdx/mdx-hast-to-jsx');
|
||||
const parser = require('@babel/parser');
|
||||
const generate = require('@babel/generator').default;
|
||||
const camelCase = require('lodash/camelCase');
|
||||
|
||||
// Generate the MDX as is, but append named exports for every
|
||||
// story in the contents
|
||||
|
||||
const STORY_REGEX = /^<Story[\s>]/;
|
||||
const PREVIEW_REGEX = /^<Preview[\s>]/;
|
||||
const META_REGEX = /^<Meta[\s>]/;
|
||||
const RESERVED = /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|await|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/;
|
||||
|
||||
function getAttr(elt, what) {
|
||||
const attr = elt.attributes.find(n => n.name.name === what);
|
||||
return attr && attr.value;
|
||||
}
|
||||
|
||||
function getStoryFn(name, counter) {
|
||||
if (name) {
|
||||
const storyFn = camelCase(name.replace(/[^a-z0-9-]/g, '-'));
|
||||
if (storyFn.length > 1 && !RESERVED.exec(storyFn)) {
|
||||
return storyFn;
|
||||
}
|
||||
}
|
||||
return `story${counter}`;
|
||||
}
|
||||
|
||||
function genStoryExport(ast, counter) {
|
||||
let storyName = getAttr(ast.openingElement, 'name');
|
||||
let storyId = getAttr(ast.openingElement, 'id');
|
||||
storyName = storyName && storyName.value;
|
||||
storyId = storyId && storyId.value;
|
||||
|
||||
if (!storyId && !storyName) {
|
||||
throw new Error('Expected a story name or ID attribute');
|
||||
}
|
||||
|
||||
// We don't generate exports for story references or the smart "current story"
|
||||
if (storyId || !storyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// console.log('genStoryExport', JSON.stringify(ast, null, 2));
|
||||
|
||||
const statements = [];
|
||||
const storyKey = getStoryFn(storyName, counter);
|
||||
|
||||
let body = ast.children.find(n => n.type !== 'JSXText');
|
||||
let storyCode = null;
|
||||
if (!body) {
|
||||
// plain text node
|
||||
const { code } = generate(ast.children[0], {});
|
||||
storyCode = `'${code}'`;
|
||||
} else {
|
||||
if (body.type === 'JSXExpressionContainer') {
|
||||
// FIXME: handle fragments
|
||||
body = body.expression;
|
||||
}
|
||||
const { code } = generate(body, {});
|
||||
storyCode = code;
|
||||
}
|
||||
statements.push(
|
||||
`export const ${storyKey} = () => (
|
||||
${storyCode}
|
||||
);`
|
||||
);
|
||||
statements.push(`${storyKey}.story = {};`);
|
||||
|
||||
if (storyName !== storyKey) {
|
||||
statements.push(`${storyKey}.story.name = '${storyName}';`);
|
||||
}
|
||||
|
||||
let parameters = getAttr(ast.openingElement, 'parameters');
|
||||
parameters = parameters && parameters.expression;
|
||||
const source = `\`${storyCode.replace(/`/g, '\\`')}\``;
|
||||
if (parameters) {
|
||||
const { code: params } = generate(parameters, {});
|
||||
// FIXME: hack in the story's source as a parameter
|
||||
statements.push(`${storyKey}.story.parameters = { mdxSource: ${source}, ...${params} };`);
|
||||
} else {
|
||||
statements.push(`${storyKey}.story.parameters = { mdxSource: ${source} };`);
|
||||
}
|
||||
|
||||
// console.log(statements);
|
||||
|
||||
return {
|
||||
[storyKey]: statements.join('\n'),
|
||||
};
|
||||
}
|
||||
|
||||
function genPreviewExports(ast, counter) {
|
||||
// console.log('genPreviewExports', JSON.stringify(ast, null, 2));
|
||||
|
||||
let localCounter = counter;
|
||||
const previewExports = {};
|
||||
for (let i = 0; i < ast.children.length; i += 1) {
|
||||
const child = ast.children[i];
|
||||
if (child.type === 'JSXElement' && child.openingElement.name.name === 'Story') {
|
||||
const storyExport = genStoryExport(child, localCounter);
|
||||
if (storyExport) {
|
||||
Object.assign(previewExports, storyExport);
|
||||
localCounter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return previewExports;
|
||||
}
|
||||
|
||||
function genMeta(ast) {
|
||||
let title = getAttr(ast.openingElement, 'title');
|
||||
let parameters = getAttr(ast.openingElement, 'parameters');
|
||||
let decorators = getAttr(ast.openingElement, 'decorators');
|
||||
title = title && `'${title.value}'`;
|
||||
if (parameters && parameters.expression) {
|
||||
const { code: params } = generate(parameters.expression, {});
|
||||
parameters = params;
|
||||
}
|
||||
if (decorators && decorators.expression) {
|
||||
const { code: decos } = generate(decorators.expression, {});
|
||||
decorators = decos;
|
||||
}
|
||||
return {
|
||||
title,
|
||||
parameters,
|
||||
decorators,
|
||||
};
|
||||
}
|
||||
|
||||
function getExports(node, counter) {
|
||||
const { value, type } = node;
|
||||
if (type === 'jsx') {
|
||||
if (STORY_REGEX.exec(value)) {
|
||||
// Single story
|
||||
const ast = parser.parseExpression(value, { plugins: ['jsx'] });
|
||||
const storyExport = genStoryExport(ast, counter);
|
||||
return storyExport && { stories: storyExport };
|
||||
}
|
||||
if (PREVIEW_REGEX.exec(value)) {
|
||||
// Preview, possibly containing multiple stories
|
||||
const ast = parser.parseExpression(value, { plugins: ['jsx'] });
|
||||
return { stories: genPreviewExports(ast, counter) };
|
||||
}
|
||||
if (META_REGEX.exec(value)) {
|
||||
// Preview, possibly containing multiple stories
|
||||
const ast = parser.parseExpression(value, { plugins: ['jsx'] });
|
||||
return { meta: genMeta(ast) };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// insert `mdxKind` into the context so that we can know what "kind" we're rendering into
|
||||
// when we render <Story name="xxx">...</Story>, since this MDX can be attached to any `selectedKind`!
|
||||
const wrapperJs = `
|
||||
const mdxKind = componentMeta.title || componentMeta.displayName;
|
||||
const WrappedMDXContent = ({ context }) => <DocsContainer context={{...context, mdxKind}} content={MDXContent} />;
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = WrappedMDXContent;
|
||||
`.trim();
|
||||
|
||||
function stringifyMeta(meta) {
|
||||
let result = '{ ';
|
||||
Object.entries(meta).forEach(([key, val]) => {
|
||||
if (val) {
|
||||
result += `${key}: ${val}, `;
|
||||
}
|
||||
});
|
||||
result += ' }';
|
||||
return result;
|
||||
}
|
||||
|
||||
function extractExports(node, options) {
|
||||
// we're overriding default export
|
||||
const defaultJsx = mdxToJsx.toJSX(node, {}, { ...options, skipExport: true });
|
||||
const storyExports = [];
|
||||
const includeStories = [];
|
||||
let metaExport = null;
|
||||
let counter = 0;
|
||||
node.children.forEach(n => {
|
||||
const exports = getExports(n, counter);
|
||||
if (exports) {
|
||||
const { stories, meta } = exports;
|
||||
if (stories) {
|
||||
Object.entries(stories).forEach(([key, story]) => {
|
||||
includeStories.push(key);
|
||||
storyExports.push(story);
|
||||
counter += 1;
|
||||
});
|
||||
}
|
||||
if (meta) {
|
||||
if (metaExport) {
|
||||
throw new Error('Meta can only be declared once');
|
||||
}
|
||||
metaExport = meta;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!metaExport) {
|
||||
metaExport = {};
|
||||
}
|
||||
metaExport.includeStories = JSON.stringify(includeStories);
|
||||
|
||||
const fullJsx = [
|
||||
'import { DocsContainer } from "@storybook/addon-docs/blocks";',
|
||||
defaultJsx,
|
||||
...storyExports,
|
||||
`const componentMeta = ${stringifyMeta(metaExport)};`,
|
||||
wrapperJs,
|
||||
'export default componentMeta;',
|
||||
].join('\n\n');
|
||||
|
||||
return fullJsx;
|
||||
}
|
||||
|
||||
function createCompiler(mdxOptions) {
|
||||
return function compiler(options = {}) {
|
||||
this.Compiler = tree => extractExports(tree, options, mdxOptions);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = createCompiler;
|
75
addons/docs/mdx-compiler-plugin.test.js
Normal file
75
addons/docs/mdx-compiler-plugin.test.js
Normal file
@ -0,0 +1,75 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const mdx = require('@mdx-js/mdx');
|
||||
const prettier = require('prettier');
|
||||
const plugin = require('./mdx-compiler-plugin');
|
||||
|
||||
function format(code) {
|
||||
return prettier.format(code, {
|
||||
parser: 'babel',
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
bracketSpacing: true,
|
||||
trailingComma: 'es5',
|
||||
singleQuote: true,
|
||||
});
|
||||
}
|
||||
|
||||
async function generate(filePath) {
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
const result = mdx.sync(content, {
|
||||
filepath: filePath,
|
||||
compilers: [plugin({})],
|
||||
});
|
||||
|
||||
return format(result);
|
||||
}
|
||||
|
||||
describe('docs-mdx-compiler-plugin', () => {
|
||||
it('supports vanilla mdx', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/vanilla.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports story definitions', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/story-definitions.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports text-only story definitions', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/story-def-text-only.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports object-style story definitions', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/story-object.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports story references', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/story-references.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports "smart" current story', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/story-current.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports previews', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/previews.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports decorators', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/decorators.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports parameters', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/parameters.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('supports non-story exports', async () => {
|
||||
const code = await generate(path.resolve(__dirname, './fixtures/non-story-exports.mdx'));
|
||||
expect(code).toMatchSnapshot();
|
||||
});
|
||||
it('errors on missing story props', async () => {
|
||||
await expect(
|
||||
generate(path.resolve(__dirname, './fixtures/story-missing-props.mdx'))
|
||||
).rejects.toThrow('Expected a story name or ID attribute');
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-docs",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Superior documentation for your components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -23,10 +23,23 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23"
|
||||
"@babel/generator": "^7.4.0",
|
||||
"@babel/parser": "^7.4.2",
|
||||
"@mdx-js/loader": "^1.0.0",
|
||||
"@mdx-js/mdx": "^1.0.0",
|
||||
"@mdx-js/react": "^1.0.16",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/router": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"lodash": "^4.17.11",
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/prop-types": "^15.5.9",
|
||||
"@types/util-deprecate": "^1.0.0",
|
||||
"@types/webpack-env": "^1.13.7"
|
||||
},
|
||||
|
1
addons/docs/react/index.js
Normal file
1
addons/docs/react/index.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../common/index');
|
1
addons/docs/react/preset.js
Normal file
1
addons/docs/react/preset.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../common/preset');
|
68
addons/docs/src/blocks/Description.tsx
Normal file
68
addons/docs/src/blocks/Description.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import React from 'react';
|
||||
import { Description, DescriptionProps as PureDescriptionProps } from '@storybook/components';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { Component, CURRENT_SELECTION } from './shared';
|
||||
|
||||
export enum DescriptionType {
|
||||
INFO = 'info',
|
||||
NOTES = 'notes',
|
||||
DOCGEN = 'docgen',
|
||||
AUTO = 'auto',
|
||||
}
|
||||
|
||||
type Notes = string | any;
|
||||
type Info = string | any;
|
||||
|
||||
interface DescriptionProps {
|
||||
of?: '.' | Component;
|
||||
type?: DescriptionType;
|
||||
markdown?: string;
|
||||
}
|
||||
|
||||
const getNotes = (notes?: Notes) =>
|
||||
notes && (typeof notes === 'string' ? notes : notes.markdown || notes.text);
|
||||
|
||||
const getInfo = (info?: Info) => info && (typeof info === 'string' ? info : info.text);
|
||||
|
||||
const getDocgen = (component?: Component) =>
|
||||
(component && component.__docgenInfo && component.__docgenInfo.description) || '';
|
||||
|
||||
export const getDescriptionProps = (
|
||||
{ of, type, markdown }: DescriptionProps,
|
||||
{ parameters }: DocsContextProps
|
||||
): PureDescriptionProps => {
|
||||
if (markdown) {
|
||||
return { markdown };
|
||||
}
|
||||
const { component, notes, info } = parameters;
|
||||
const target = of === CURRENT_SELECTION ? component : of;
|
||||
switch (type) {
|
||||
case DescriptionType.INFO:
|
||||
return { markdown: getInfo(info) };
|
||||
case DescriptionType.NOTES:
|
||||
return { markdown: getNotes(notes) };
|
||||
case DescriptionType.DOCGEN:
|
||||
return { markdown: getDocgen(target) };
|
||||
case DescriptionType.AUTO:
|
||||
default:
|
||||
return {
|
||||
markdown: `
|
||||
${getNotes(notes) || getInfo(info) || ''}
|
||||
|
||||
${getDocgen(target)}
|
||||
`.trim(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const DescriptionContainer: React.FunctionComponent<DescriptionProps> = props => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const { markdown } = getDescriptionProps(props, context);
|
||||
return markdown && <Description markdown={markdown} />;
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
||||
|
||||
export { DescriptionContainer as Description };
|
52
addons/docs/src/blocks/DocsContainer.tsx
Normal file
52
addons/docs/src/blocks/DocsContainer.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
|
||||
import React from 'react';
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Global, createGlobal, ThemeProvider, ensure as ensureTheme } from '@storybook/theming';
|
||||
import { DocumentFormatting, DocsWrapper, DocsContent } from '@storybook/components';
|
||||
import { DocsContextProps, DocsContext } from './DocsContext';
|
||||
|
||||
interface DocsContainerProps {
|
||||
context: DocsContextProps;
|
||||
content: React.ElementType<any>;
|
||||
}
|
||||
|
||||
const defaultComponents = {
|
||||
// p: ({ children }) => <b>{children}</b>,
|
||||
wrapper: DocumentFormatting,
|
||||
};
|
||||
|
||||
const globalWithOverflow = (args: any) => {
|
||||
const global = createGlobal(args);
|
||||
const { body, ...rest } = global;
|
||||
const { overflow, ...bodyRest } = body;
|
||||
return {
|
||||
body: bodyRest,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
||||
export const DocsContainer: React.FunctionComponent<DocsContainerProps> = ({
|
||||
context,
|
||||
content: MDXContent,
|
||||
}) => {
|
||||
const parameters = (context && context.parameters) || {};
|
||||
const options = parameters.options || {};
|
||||
const theme = ensureTheme(options.theme);
|
||||
const { components: userComponents = null } = options.docs || {};
|
||||
const components = { ...defaultComponents, ...userComponents };
|
||||
return (
|
||||
<DocsContext.Provider value={context}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<Global styles={globalWithOverflow} />
|
||||
<MDXProvider components={components}>
|
||||
<DocsWrapper>
|
||||
<DocsContent>
|
||||
<MDXContent components={components} />
|
||||
</DocsContent>
|
||||
</DocsWrapper>
|
||||
</MDXProvider>
|
||||
</ThemeProvider>
|
||||
</DocsContext.Provider>
|
||||
);
|
||||
};
|
23
addons/docs/src/blocks/DocsContext.ts
Normal file
23
addons/docs/src/blocks/DocsContext.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
|
||||
export interface DocsContextProps {
|
||||
id?: string;
|
||||
selectedKind?: string;
|
||||
selectedStory?: string;
|
||||
|
||||
/**
|
||||
* mdxKind is a statically-generated "kind" that corresponds to the
|
||||
* component that's being documented in the MDX file, It's combined
|
||||
* with the MDX story name `<Story name='story name'>...</Story>` to
|
||||
* generate a storyId. In the case that the user is viewing a non-MDX
|
||||
* story, the value of `mdxKind` will be the currently-selected kind.
|
||||
* (I can't remember the corner case in which using the currentl-selected
|
||||
* kind breaks down in MDX-defined stories, but there is one!)
|
||||
*/
|
||||
mdxKind?: string;
|
||||
parameters?: any;
|
||||
storyStore?: any;
|
||||
forceRender?: () => void;
|
||||
}
|
||||
|
||||
export const DocsContext: React.Context<DocsContextProps> = React.createContext({});
|
140
addons/docs/src/blocks/DocsPage.tsx
Normal file
140
addons/docs/src/blocks/DocsPage.tsx
Normal file
@ -0,0 +1,140 @@
|
||||
import React from 'react';
|
||||
|
||||
import { parseKind } from '@storybook/router';
|
||||
import { styled } from '@storybook/theming';
|
||||
import { DocsPage as PureDocsPage, DocsPageProps } from '@storybook/components';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { DocsContainer } from './DocsContainer';
|
||||
import { Description } from './Description';
|
||||
import { Story } from './Story';
|
||||
import { Preview } from './Preview';
|
||||
import { Props } from './Props';
|
||||
|
||||
enum DocsStoriesType {
|
||||
ALL = 'all',
|
||||
PRIMARY = 'primary',
|
||||
REST = 'rest',
|
||||
}
|
||||
|
||||
interface DocsStoriesProps {
|
||||
type?: DocsStoriesType;
|
||||
}
|
||||
|
||||
interface DocsStoryProps {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
expanded?: boolean;
|
||||
}
|
||||
|
||||
interface StoryData {
|
||||
id: string;
|
||||
kind: string;
|
||||
name: string;
|
||||
parameters?: any;
|
||||
}
|
||||
|
||||
const getDocsStories = (type: DocsStoriesType, componentStories: StoryData[]): DocsStoryProps[] => {
|
||||
let stories = componentStories;
|
||||
if (type !== DocsStoriesType.ALL) {
|
||||
const primary = stories.find(s => s.parameters && s.parameters.primary);
|
||||
const [first, ...rest] = stories;
|
||||
if (type === DocsStoriesType.PRIMARY) {
|
||||
stories = [primary || first];
|
||||
} else {
|
||||
stories = primary ? stories.filter(s => !s.parameters || !s.parameters.primary) : rest;
|
||||
}
|
||||
}
|
||||
return stories.map(({ id, name, parameters: { notes, info } }) => ({
|
||||
id,
|
||||
name,
|
||||
description: notes || info || null,
|
||||
}));
|
||||
};
|
||||
|
||||
const StoriesHeading = styled.h2();
|
||||
const StoryHeading = styled.h3();
|
||||
|
||||
const DocsStory: React.FunctionComponent<DocsStoryProps> = ({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
expanded = true,
|
||||
}) => (
|
||||
<>
|
||||
{expanded && <StoryHeading>{name}</StoryHeading>}
|
||||
{expanded && description && <Description markdown={description} />}
|
||||
<Preview>
|
||||
<Story id={id} />
|
||||
</Preview>
|
||||
</>
|
||||
);
|
||||
|
||||
const DocsStories: React.FunctionComponent<DocsStoriesProps> = ({ type = DocsStoriesType.ALL }) => (
|
||||
<DocsContext.Consumer>
|
||||
{({ selectedKind, storyStore }) => {
|
||||
const componentStories = (storyStore.raw() as StoryData[]).filter(
|
||||
s => s.kind === selectedKind
|
||||
);
|
||||
const stories = getDocsStories(type, componentStories);
|
||||
if (stories.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const expanded = type !== DocsStoriesType.PRIMARY;
|
||||
return (
|
||||
<>
|
||||
{expanded && <StoriesHeading>Stories</StoriesHeading>}
|
||||
{stories.map(s => (
|
||||
<DocsStory key={s.id} expanded={expanded} {...s} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
||||
|
||||
const getDocsPageProps = (context: DocsContextProps): DocsPageProps => {
|
||||
const { selectedKind, selectedStory, parameters } = context;
|
||||
const {
|
||||
hierarchyRootSeparator: rootSeparator,
|
||||
hierarchySeparator: groupSeparator,
|
||||
} = (parameters && parameters.options) || {
|
||||
hierarchyRootSeparator: '|',
|
||||
hierarchySeparator: '/',
|
||||
};
|
||||
|
||||
const { groups } = parseKind(selectedKind, { rootSeparator, groupSeparator });
|
||||
const title = (groups && groups[groups.length - 1]) || selectedKind;
|
||||
|
||||
return {
|
||||
title,
|
||||
subtitle: parameters && parameters.componentDescription,
|
||||
};
|
||||
};
|
||||
|
||||
const DocsPage: React.FunctionComponent = () => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const docsPageProps = getDocsPageProps(context);
|
||||
return (
|
||||
<PureDocsPage {...docsPageProps}>
|
||||
<Description of="." />
|
||||
<DocsStories type={DocsStoriesType.PRIMARY} />
|
||||
<Props of="." />
|
||||
<DocsStories type={DocsStoriesType.REST} />
|
||||
</PureDocsPage>
|
||||
);
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
||||
|
||||
interface DocsPageWrapperProps {
|
||||
context: DocsContextProps;
|
||||
}
|
||||
|
||||
const DocsPageWrapper: React.FunctionComponent<DocsPageWrapperProps> = ({ context }) => (
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
<DocsContainer context={{ ...context, mdxKind: context.selectedKind }} content={DocsPage} />
|
||||
);
|
||||
|
||||
export { DocsPageWrapper as DocsPage };
|
16
addons/docs/src/blocks/Meta.tsx
Normal file
16
addons/docs/src/blocks/Meta.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
type Decorator = (...args: any) => any;
|
||||
|
||||
interface MetaProps {
|
||||
title: string;
|
||||
decorators?: [Decorator];
|
||||
parameters?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* This component is used to declare component metadata in docs
|
||||
* and gets transformed into a default export underneath the hood.
|
||||
* It doesn't actually render anything.
|
||||
*/
|
||||
export const Meta: React.FunctionComponent<MetaProps> = props => null;
|
48
addons/docs/src/blocks/Preview.tsx
Normal file
48
addons/docs/src/blocks/Preview.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { ReactNodeArray } from 'react';
|
||||
import { Preview as PurePreview, PreviewProps as PurePreviewProps } from '@storybook/components';
|
||||
import { toId } from '@storybook/router';
|
||||
import { getSourceProps } from './Source';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
|
||||
export enum SourceState {
|
||||
OPEN = 'open',
|
||||
CLOSED = 'closed',
|
||||
NONE = 'none',
|
||||
}
|
||||
|
||||
type PreviewProps = PurePreviewProps & {
|
||||
withSource?: SourceState;
|
||||
};
|
||||
|
||||
const getPreviewProps = (
|
||||
{
|
||||
withSource = SourceState.CLOSED,
|
||||
children,
|
||||
...props
|
||||
}: PreviewProps & { children?: React.ReactNode },
|
||||
{ mdxKind, storyStore }: DocsContextProps
|
||||
): PurePreviewProps => {
|
||||
if (withSource === SourceState.NONE && !children) {
|
||||
return props;
|
||||
}
|
||||
const childArray: ReactNodeArray = Array.isArray(children) ? children : [children];
|
||||
const stories = childArray.filter(
|
||||
(c: React.ReactElement) => c.props && (c.props.id || c.props.name)
|
||||
) as React.ReactElement[];
|
||||
const targetIds = stories.map(s => s.props.id || toId(mdxKind, s.props.name));
|
||||
const sourceProps = getSourceProps({ ids: targetIds }, { storyStore });
|
||||
return {
|
||||
...props, // pass through columns etc.
|
||||
withSource: sourceProps,
|
||||
isExpanded: withSource === SourceState.OPEN,
|
||||
};
|
||||
};
|
||||
|
||||
export const Preview: React.FunctionComponent<PreviewProps> = props => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const previewProps = getPreviewProps(props, context);
|
||||
return <PurePreview {...previewProps}>{props.children}</PurePreview>;
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
57
addons/docs/src/blocks/Props.tsx
Normal file
57
addons/docs/src/blocks/Props.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import { PropsTable, PropsTableError, PropsTableProps, PropDef } from '@storybook/components';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { Component, CURRENT_SELECTION } from './shared';
|
||||
import { getPropDefs as autoPropDefs, PropDefGetter } from '../lib/getPropDefs';
|
||||
|
||||
interface PropsProps {
|
||||
exclude?: string[];
|
||||
of: '.' | Component;
|
||||
}
|
||||
|
||||
const inferPropDefs = (framework: string): PropDefGetter | null => {
|
||||
switch (framework) {
|
||||
case 'react':
|
||||
case 'vue':
|
||||
return autoPropDefs;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const getPropsTableProps = (
|
||||
{ exclude, of }: PropsProps,
|
||||
{ parameters }: DocsContextProps
|
||||
): PropsTableProps => {
|
||||
const { component } = parameters;
|
||||
try {
|
||||
const target = of === CURRENT_SELECTION ? component : of;
|
||||
if (!target) {
|
||||
throw new Error(PropsTableError.NO_COMPONENT);
|
||||
}
|
||||
|
||||
const { framework = null } = parameters || {};
|
||||
const { getPropDefs = inferPropDefs(framework) } =
|
||||
(parameters && parameters.options && parameters.options.docs) || {};
|
||||
|
||||
if (!getPropDefs) {
|
||||
throw new Error(PropsTableError.PROPS_UNSUPPORTED);
|
||||
}
|
||||
const allRows = getPropDefs(target);
|
||||
const rows = !exclude ? allRows : allRows.filter((row: PropDef) => !exclude.includes(row.name));
|
||||
return { rows };
|
||||
} catch (err) {
|
||||
return { error: err.message };
|
||||
}
|
||||
};
|
||||
|
||||
const PropsContainer: React.FunctionComponent<PropsProps> = props => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const propsTableProps = getPropsTableProps(props, context);
|
||||
return <PropsTable {...propsTableProps} />;
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
||||
|
||||
export { PropsContainer as Props };
|
97
addons/docs/src/blocks/Source.tsx
Normal file
97
addons/docs/src/blocks/Source.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import React from 'react';
|
||||
import { Source, SourceProps as PureSourceProps, SourceError } from '@storybook/components';
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
import { CURRENT_SELECTION } from './shared';
|
||||
|
||||
interface CommonProps {
|
||||
language?: string;
|
||||
}
|
||||
|
||||
type SingleSourceProps = {
|
||||
id: string;
|
||||
} & CommonProps;
|
||||
|
||||
type MultiSourceProps = {
|
||||
ids: string[];
|
||||
} & CommonProps;
|
||||
|
||||
type CodeProps = {
|
||||
code: string;
|
||||
} & CommonProps;
|
||||
|
||||
type NoneProps = CommonProps;
|
||||
|
||||
type SourceProps = SingleSourceProps | MultiSourceProps | CodeProps | NoneProps;
|
||||
|
||||
interface Location {
|
||||
line: number;
|
||||
col: number;
|
||||
}
|
||||
|
||||
interface StorySource {
|
||||
source: string;
|
||||
locationsMap: { [id: string]: { startBody: Location; endBody: Location } };
|
||||
}
|
||||
|
||||
const extract = (targetId: string, { source, locationsMap }: StorySource) => {
|
||||
const location = locationsMap[targetId];
|
||||
// FIXME: bad locationsMap generated for module export functions whose titles are overridden
|
||||
if (!location) return null;
|
||||
const { startBody: start, endBody: end } = location;
|
||||
const lines = source.split('\n');
|
||||
if (start.line === end.line) {
|
||||
return lines[start.line - 1].substring(start.col, end.col);
|
||||
}
|
||||
// NOTE: storysource locations are 1-based not 0-based!
|
||||
const startLine = lines[start.line - 1];
|
||||
const endLine = lines[end.line - 1];
|
||||
return [
|
||||
startLine.substring(start.col),
|
||||
...lines.slice(start.line, end.line - 1),
|
||||
endLine.substring(0, end.col),
|
||||
].join('\n');
|
||||
};
|
||||
|
||||
export const getSourceProps = (
|
||||
props: SourceProps,
|
||||
{ id: currentId, storyStore }: DocsContextProps
|
||||
): PureSourceProps => {
|
||||
const codeProps = props as CodeProps;
|
||||
const singleProps = props as SingleSourceProps;
|
||||
const multiProps = props as MultiSourceProps;
|
||||
|
||||
let source = codeProps.code; // prefer user-specified code
|
||||
if (!source) {
|
||||
const targetId = singleProps.id === CURRENT_SELECTION ? currentId : singleProps.id;
|
||||
const targetIds = multiProps.ids || [targetId];
|
||||
source = targetIds
|
||||
.map(sourceId => {
|
||||
const data = storyStore.fromId(sourceId);
|
||||
if (data && data.parameters) {
|
||||
const { mdxSource, storySource } = data.parameters;
|
||||
return mdxSource || (storySource && extract(sourceId, storySource));
|
||||
}
|
||||
return '';
|
||||
})
|
||||
.join('\n\n');
|
||||
}
|
||||
return source
|
||||
? { code: source, language: props.language || 'jsx' }
|
||||
: { error: SourceError.SOURCE_UNAVAILABLE };
|
||||
};
|
||||
|
||||
/**
|
||||
* Story source doc block renders source code if provided,
|
||||
* or the source for a story if `storyId` is provided, or
|
||||
* the source for the current story if nothing is provided.
|
||||
*/
|
||||
const SourceContainer: React.FunctionComponent<SourceProps> = props => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const sourceProps = getSourceProps(props, context);
|
||||
return <Source {...sourceProps} />;
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
||||
|
||||
export { SourceContainer as Source };
|
69
addons/docs/src/blocks/Story.tsx
Normal file
69
addons/docs/src/blocks/Story.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
import { toId } from '@storybook/router';
|
||||
import { Story, StoryProps as PureStoryProps } from '@storybook/components';
|
||||
import { CURRENT_SELECTION } from './shared';
|
||||
|
||||
import { DocsContext, DocsContextProps } from './DocsContext';
|
||||
|
||||
interface CommonProps {
|
||||
height?: string;
|
||||
}
|
||||
|
||||
type StoryDefProps = {
|
||||
name: string;
|
||||
children: React.ReactNode;
|
||||
} & CommonProps;
|
||||
|
||||
type StoryRefProps = {
|
||||
id?: string;
|
||||
} & CommonProps;
|
||||
|
||||
export type StoryProps = StoryDefProps | StoryRefProps;
|
||||
|
||||
const inferInlineStories = (framework: string): boolean => {
|
||||
switch (framework) {
|
||||
case 'react':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getStoryProps = (
|
||||
props: StoryProps,
|
||||
{ id: currentId, storyStore, parameters, mdxKind }: DocsContextProps
|
||||
): PureStoryProps => {
|
||||
const { id } = props as StoryRefProps;
|
||||
const { name } = props as StoryDefProps;
|
||||
const inputId = id === CURRENT_SELECTION ? currentId : id;
|
||||
const previewId = inputId || toId(mdxKind, name);
|
||||
|
||||
const { height } = props;
|
||||
const data = storyStore.fromId(previewId);
|
||||
const { framework = null } = parameters || {};
|
||||
const { inlineStories = inferInlineStories(framework), iframeHeight = undefined } =
|
||||
(parameters && parameters.options && parameters.options.docs) || {};
|
||||
return {
|
||||
inline: inlineStories,
|
||||
id: previewId,
|
||||
storyFn: data && data.getDecorated(),
|
||||
height: height || iframeHeight,
|
||||
title: data && data.name,
|
||||
};
|
||||
};
|
||||
|
||||
const StoryContainer: React.FunctionComponent<StoryProps> = props => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const storyProps = getStoryProps(props, context);
|
||||
return <Story {...storyProps} />;
|
||||
}}
|
||||
</DocsContext.Consumer>
|
||||
);
|
||||
|
||||
StoryContainer.defaultProps = {
|
||||
children: null,
|
||||
name: null,
|
||||
};
|
||||
|
||||
export { StoryContainer as Story };
|
9
addons/docs/src/blocks/Wrapper.tsx
Normal file
9
addons/docs/src/blocks/Wrapper.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
interface WrapperProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Wrapper: React.FunctionComponent<WrapperProps> = ({ children }) => (
|
||||
<div style={{ fontFamily: 'sans-serif' }}>{children}</div>
|
||||
);
|
12
addons/docs/src/blocks/index.ts
Normal file
12
addons/docs/src/blocks/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export { ColorPalette, ColorItem, IconGallery, IconItem, Typeset } from '@storybook/components';
|
||||
|
||||
export * from './Description';
|
||||
export * from './DocsContext';
|
||||
export * from './DocsPage';
|
||||
export * from './DocsContainer';
|
||||
export * from './Meta';
|
||||
export * from './Preview';
|
||||
export * from './Props';
|
||||
export * from './Source';
|
||||
export * from './Story';
|
||||
export * from './Wrapper';
|
2
addons/docs/src/blocks/shared.ts
Normal file
2
addons/docs/src/blocks/shared.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const CURRENT_SELECTION = '.';
|
||||
export type Component = any;
|
88
addons/docs/src/lib/getPropDefs.ts
Normal file
88
addons/docs/src/lib/getPropDefs.ts
Normal file
@ -0,0 +1,88 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { PropDef } from '@storybook/components';
|
||||
import { Component } from '../blocks/shared';
|
||||
|
||||
interface PropDefMap {
|
||||
[p: string]: PropDef;
|
||||
}
|
||||
|
||||
export type PropDefGetter = (type: Component) => PropDef[] | null;
|
||||
|
||||
const propTypesMap = new Map();
|
||||
|
||||
Object.keys(PropTypes).forEach(typeName => {
|
||||
// @ts-ignore
|
||||
const type = PropTypes[typeName];
|
||||
|
||||
propTypesMap.set(type, typeName);
|
||||
propTypesMap.set(type.isRequired, typeName);
|
||||
});
|
||||
|
||||
const hasDocgen = (obj: any) => obj && obj.props && Object.keys(obj.props).length > 0;
|
||||
|
||||
const propsFromDocgen: PropDefGetter = type => {
|
||||
const props: PropDefMap = {};
|
||||
const docgenInfoProps = type.__docgenInfo.props;
|
||||
|
||||
Object.keys(docgenInfoProps).forEach(property => {
|
||||
const docgenInfoProp = docgenInfoProps[property];
|
||||
const defaultValueDesc = docgenInfoProp.defaultValue || {};
|
||||
const propType = docgenInfoProp.flowType || docgenInfoProp.type || 'other';
|
||||
|
||||
props[property] = {
|
||||
name: property,
|
||||
type: propType,
|
||||
required: docgenInfoProp.required,
|
||||
description: docgenInfoProp.description,
|
||||
defaultValue: defaultValueDesc.value,
|
||||
};
|
||||
});
|
||||
|
||||
return Object.values(props);
|
||||
};
|
||||
|
||||
const propsFromPropTypes: PropDefGetter = type => {
|
||||
const props: PropDefMap = {};
|
||||
|
||||
if (type.propTypes) {
|
||||
Object.keys(type.propTypes).forEach(property => {
|
||||
const typeInfo = type.propTypes[property];
|
||||
const required = typeInfo.isRequired === undefined;
|
||||
const docgenInfo =
|
||||
type.__docgenInfo && type.__docgenInfo.props && type.__docgenInfo.props[property];
|
||||
const description = docgenInfo ? docgenInfo.description : null;
|
||||
let propType = propTypesMap.get(typeInfo) || 'other';
|
||||
|
||||
if (propType === 'other') {
|
||||
if (docgenInfo && docgenInfo.type) {
|
||||
propType = docgenInfo.type.name;
|
||||
}
|
||||
}
|
||||
|
||||
props[property] = { name: property, type: propType, required, description };
|
||||
});
|
||||
}
|
||||
|
||||
if (type.defaultProps) {
|
||||
Object.keys(type.defaultProps).forEach(property => {
|
||||
const value = type.defaultProps[property];
|
||||
|
||||
if (value === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props[property]) {
|
||||
props[property] = { name: property, type: 'any', required: false };
|
||||
}
|
||||
|
||||
props[property].defaultValue = value;
|
||||
});
|
||||
}
|
||||
|
||||
return Object.values(props);
|
||||
};
|
||||
|
||||
export const getPropDefs: PropDefGetter = type =>
|
||||
hasDocgen(type.__docgenInfo) ? propsFromDocgen(type) : propsFromPropTypes(type);
|
1
addons/docs/src/typings.d.ts
vendored
Normal file
1
addons/docs/src/typings.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module '@mdx-js/react';
|
1
addons/docs/vue/index.js
Normal file
1
addons/docs/vue/index.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../common/index');
|
1
addons/docs/vue/preset.js
Normal file
1
addons/docs/vue/preset.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../common/preset');
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-events",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Add events to your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,10 +24,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/client-api": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/client-api": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"format-json": "^1.0.3",
|
||||
"lodash": "^4.17.11",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-google-analytics",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook addon for google analytics",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -20,8 +20,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react-ga": "^2.5.7"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-graphql",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook addon to display the GraphiQL IDE",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,8 +22,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"graphiql": "^0.13.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-info",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "A Storybook addon to show additional information for your stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,10 +22,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"jsx-to-string": "^1.4.0",
|
||||
|
@ -1331,7 +1331,7 @@ exports[`addon Info should render component description if story kind matches co
|
||||
bordered={true}
|
||||
className={null}
|
||||
copyable={true}
|
||||
format={true}
|
||||
format={false}
|
||||
language="js"
|
||||
padded={false}
|
||||
>
|
||||
@ -5888,7 +5888,7 @@ exports[`addon Info should render component description if story name matches co
|
||||
bordered={true}
|
||||
className={null}
|
||||
copyable={true}
|
||||
format={true}
|
||||
format={false}
|
||||
language="js"
|
||||
padded={false}
|
||||
>
|
||||
|
@ -5,7 +5,7 @@ import { ThemeProvider, convert } from '@storybook/theming';
|
||||
|
||||
const Code = ({ code, language = 'plaintext', ...rest }) => (
|
||||
<ThemeProvider theme={convert()}>
|
||||
<SyntaxHighlighter bordered copyable language={language} {...rest}>
|
||||
<SyntaxHighlighter bordered copyable format={false} language={language} {...rest}>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
</ThemeProvider>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-jest",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "React storybook addon that show component jest report",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,11 +28,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-knobs",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook Addon Prop Editor Component",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,11 +22,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/client-api": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/client-api": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"core-js": "^3.0.1",
|
||||
"escape-html": "^1.0.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-links",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Story Links addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,9 +22,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/router": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/router": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-notes",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Write notes for your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -23,13 +23,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/router": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/router": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"markdown-to-jsx": "^6.9.3",
|
||||
|
@ -68,7 +68,13 @@ export const SyntaxHighlighter = ({ className, children, ...props }: SyntaxHighl
|
||||
// className: "lang-jsx"
|
||||
const language = className.split('-');
|
||||
return (
|
||||
<SyntaxHighlighterBase language={language[1] || 'plaintext'} bordered copyable {...props}>
|
||||
<SyntaxHighlighterBase
|
||||
language={language[1] || 'plaintext'}
|
||||
bordered
|
||||
format={false}
|
||||
copyable
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</SyntaxHighlighterBase>
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-actions",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Action Logger addon for react-native storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -19,13 +19,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"core-js": "^2.5.7",
|
||||
"fast-deep-equal": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "5.2.0-alpha.23"
|
||||
"@storybook/addon-actions": "5.2.0-alpha.32"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-actions": "*",
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
/* eslint-disable no-nested-ternary */
|
||||
import React from 'react';
|
||||
import { Button, View, Text } from 'react-native';
|
||||
|
||||
@ -22,6 +24,7 @@ const theme = {
|
||||
|
||||
class Inspect extends React.Component<{ name?: string; value: any }, { expanded: boolean }> {
|
||||
state = { expanded: false };
|
||||
|
||||
render() {
|
||||
const { name, value } = this.props;
|
||||
const { expanded } = this.state;
|
||||
@ -52,7 +55,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded:
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
{toggle}
|
||||
{nameComponent}
|
||||
<Text>{': ' + (value.length === 0 ? '[]' : expanded ? '[' : '[...]')}</Text>
|
||||
<Text>{`: ${value.length === 0 ? '[]' : expanded ? '[' : '[...]'}`}</Text>
|
||||
</View>
|
||||
{expanded ? (
|
||||
<View style={{ marginLeft: 40 }}>
|
||||
@ -62,7 +65,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded:
|
||||
</View>
|
||||
))}
|
||||
<View style={{ marginLeft: 20 }}>
|
||||
<Text>{']'}</Text>
|
||||
<Text>]</Text>
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
@ -71,13 +74,13 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded:
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
<Text>{'['}</Text>
|
||||
<Text>[</Text>
|
||||
{value.map((v, i) => (
|
||||
<View key={i} style={{ marginLeft: 20 }}>
|
||||
<Inspect value={v} />
|
||||
</View>
|
||||
))}
|
||||
<Text>{']'}</Text>
|
||||
<Text>]</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@ -89,7 +92,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded:
|
||||
{toggle}
|
||||
{nameComponent}
|
||||
<Text>
|
||||
{': ' + (Object.keys(value).length === 0 ? '{}' : expanded ? '{' : '{...}')}
|
||||
{`: ${Object.keys(value).length === 0 ? '{}' : expanded ? '{' : '{...}'}`}
|
||||
</Text>
|
||||
</View>
|
||||
{expanded ? (
|
||||
@ -124,7 +127,7 @@ class Inspect extends React.Component<{ name?: string; value: any }, { expanded:
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
{toggle}
|
||||
{nameComponent}
|
||||
<Text>{': '}</Text>
|
||||
<Text>: </Text>
|
||||
<Value value={value} />
|
||||
</View>
|
||||
);
|
||||
@ -147,7 +150,7 @@ function Value({ value }: { value: any }) {
|
||||
if (value instanceof RegExp) {
|
||||
return (
|
||||
<Text style={{ color: theme.OBJECT_VALUE_REGEXP_COLOR }}>
|
||||
{'/' + value.source + '/' + value.flags}
|
||||
{`/${value.source}/${value.flags}`}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
@ -166,8 +169,9 @@ function Value({ value }: { value: any }) {
|
||||
);
|
||||
case 'function':
|
||||
return <Text style={{ color: theme.OBJECT_VALUE_FUNCTION_PREFIX_COLOR }}>[Function]</Text>;
|
||||
default:
|
||||
return <Text>{JSON.stringify(value)}</Text>;
|
||||
}
|
||||
return <Text>{JSON.stringify(value)}</Text>;
|
||||
}
|
||||
|
||||
export default Inspect;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-backgrounds",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "A react-native storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -24,7 +24,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/prop-types, react/destructuring-assignment, import/no-extraneous-dependencies */
|
||||
import React, { Component } from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import Events from '@storybook/core-events';
|
||||
@ -36,10 +37,6 @@ const Instructions = () => (
|
||||
);
|
||||
|
||||
export default class BackgroundPanel extends Component {
|
||||
setBackgroundFromSwatch = background => {
|
||||
this.props.channel.emit(Constants.UPDATE_BACKGROUND, background);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.channel.on(Events.SELECT_STORY, this.onStorySelected);
|
||||
}
|
||||
@ -48,6 +45,10 @@ export default class BackgroundPanel extends Component {
|
||||
this.props.channel.removeListener(Events.SELECT_STORY, this.onStorySelected);
|
||||
}
|
||||
|
||||
setBackgroundFromSwatch = background => {
|
||||
this.props.channel.emit(Constants.UPDATE_BACKGROUND, background);
|
||||
};
|
||||
|
||||
onStorySelected = selection => {
|
||||
this.setState({ selection });
|
||||
};
|
||||
|
@ -19,9 +19,9 @@ export default class Container extends React.Component {
|
||||
channel.removeListener(Constants.UPDATE_BACKGROUND, this.onBackgroundChange);
|
||||
}
|
||||
|
||||
onBackgroundChange = (background) => {
|
||||
onBackgroundChange = background => {
|
||||
this.setState({ background });
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { background } = this.state;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-knobs",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Display storybook story knobs on your deviced.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -21,8 +21,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"deep-equal": "^1.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
|
@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
||||
import { View } from 'react-native';
|
||||
import PropField from './PropField';
|
||||
|
||||
export default class propForm extends React.Component {
|
||||
export default class PropForm extends React.Component {
|
||||
makeChangeHandler(name, type) {
|
||||
return value => {
|
||||
const { onFieldChange } = this.props;
|
||||
@ -38,13 +38,13 @@ export default class propForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
propForm.displayName = 'propForm';
|
||||
PropForm.displayName = 'PropForm';
|
||||
|
||||
propForm.defaultProps = {
|
||||
PropForm.defaultProps = {
|
||||
knobs: [],
|
||||
};
|
||||
|
||||
propForm.propTypes = {
|
||||
PropForm.propTypes = {
|
||||
knobs: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-notes",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Write notes for your react-native Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -20,7 +20,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-native-simple-markdown": "^1.1.0"
|
||||
|
@ -1,3 +1,4 @@
|
||||
// eslint-disable-next-line no-undef
|
||||
if (__DEV__) {
|
||||
console.log("import '@storybook/addon-ondevice-notes/register' to register the notes addon");
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import Markdown from 'react-native-simple-markdown';
|
||||
@ -7,10 +10,6 @@ import Events from '@storybook/core-events';
|
||||
export const PARAM_KEY = `notes`;
|
||||
|
||||
class Notes extends React.Component {
|
||||
setBackgroundFromSwatch = background => {
|
||||
this.props.channel.emit(Constants.UPDATE_BACKGROUND, background);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.channel.on(Events.SELECT_STORY, this.onStorySelected);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-options",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Options addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,7 +22,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
|
@ -1,19 +1,19 @@
|
||||
{
|
||||
"name": "@storybook/addon-queryparams",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "parameter addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook",
|
||||
"query"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook#readme",
|
||||
"homepage": "https://github.com/storybookjs/storybook#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
"url": "https://github.com/storybookjs/storybook/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/storybooks/storybook.git",
|
||||
"url": "git+https://github.com/storybookjs/storybook.git",
|
||||
"directory": "addons/addon-queryparams"
|
||||
},
|
||||
"license": "MIT",
|
||||
@ -23,14 +23,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/api": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.5",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"qs": "^6.6.0",
|
||||
"react": "^16.8.3"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -25,7 +25,7 @@
|
||||
"storybook": "start-storybook -p 6006"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"glob": "^7.1.3",
|
||||
"global": "^4.3.2",
|
||||
|
@ -16,7 +16,8 @@ function integrityTest(integrityOptions, stories2snapsConverter) {
|
||||
const possibleStoriesFiles = stories2snapsConverter.getPossibleStoriesFiles(fileName);
|
||||
return !possibleStoriesFiles.some(fs.existsSync);
|
||||
});
|
||||
expect(abandonedStoryshots.length).toBe(0);
|
||||
|
||||
expect(abandonedStoryshots).toEqual([]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ import { action } from '@storybook/addon-actions';
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
storiesOf('Button', module)
|
||||
.addParameters({
|
||||
component: Button,
|
||||
})
|
||||
.add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
|
||||
.add('with some emoji', () => (
|
||||
<Button onClick={action('clicked')}>
|
||||
|
@ -4,4 +4,8 @@ import { storiesOf } from '@storybook/react';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
import { Welcome } from '@storybook/react/demo';
|
||||
|
||||
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
||||
storiesOf('Welcome', module)
|
||||
.addParameters({
|
||||
component: Welcome,
|
||||
})
|
||||
.add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots-puppeteer",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Image snappshots addition to StoryShots base on puppeteer",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,8 +22,8 @@
|
||||
"prepare": "node ../../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/node-logger": "5.2.0-alpha.23",
|
||||
"@storybook/router": "5.2.0-alpha.23",
|
||||
"@storybook/node-logger": "5.2.0-alpha.32",
|
||||
"@storybook/router": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"jest-image-snapshot": "^2.8.2",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storysource",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Stories addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,10 +22,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/router": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/router": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"estraverse": "^4.2.0",
|
||||
"loader-utils": "^1.2.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-viewport",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook addon to change the viewport size to mobile",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -21,11 +21,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.2.0-alpha.23",
|
||||
"@storybook/client-logger": "5.2.0-alpha.23",
|
||||
"@storybook/components": "5.2.0-alpha.23",
|
||||
"@storybook/core-events": "5.2.0-alpha.23",
|
||||
"@storybook/theming": "5.2.0-alpha.23",
|
||||
"@storybook/addons": "5.2.0-alpha.32",
|
||||
"@storybook/api": "5.2.0-alpha.32",
|
||||
"@storybook/client-logger": "5.2.0-alpha.32",
|
||||
"@storybook/components": "5.2.0-alpha.32",
|
||||
"@storybook/core-events": "5.2.0-alpha.32",
|
||||
"@storybook/theming": "5.2.0-alpha.32",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"memoizerific": "^1.11.3",
|
||||
@ -37,5 +38,8 @@
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/util-deprecate": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import memoize from 'memoizerific';
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
@ -10,23 +9,37 @@ import { SET_STORIES } from '@storybook/core-events';
|
||||
|
||||
import { PARAM_KEY } from './constants';
|
||||
import { INITIAL_VIEWPORTS, DEFAULT_VIEWPORT } from './defaults';
|
||||
import { ViewportAddonParameter, ViewportMap, ViewportStyles } from './models';
|
||||
|
||||
const toList = memoize(50)(items =>
|
||||
const toList = memoize(50)((items: ViewportMap) =>
|
||||
items ? Object.entries(items).map(([id, value]) => ({ ...value, id })) : []
|
||||
);
|
||||
const iframeId = 'storybook-preview-iframe';
|
||||
|
||||
const createItem = memoize(1000)((id, name, value, change) => ({
|
||||
id: id || name,
|
||||
title: name,
|
||||
onClick: () => {
|
||||
change({ selected: id, expanded: false });
|
||||
},
|
||||
right: `${value.width.replace('px', '')}x${value.height.replace('px', '')}`,
|
||||
value,
|
||||
}));
|
||||
interface ViewportVM {
|
||||
id: string;
|
||||
title: string;
|
||||
onClick: () => void;
|
||||
right: string;
|
||||
value: ViewportStyles;
|
||||
}
|
||||
|
||||
const flip = ({ width, height }) => ({ height: width, width: height });
|
||||
const createItem = memoize(1000)(
|
||||
(id: string, name: string, value: ViewportStyles, change: (...args: unknown[]) => void) => {
|
||||
const result: ViewportVM = {
|
||||
id: id || name,
|
||||
title: name,
|
||||
onClick: () => {
|
||||
change({ selected: id, expanded: false });
|
||||
},
|
||||
right: `${value.width.replace('px', '')}x${value.height.replace('px', '')}`,
|
||||
value,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
);
|
||||
|
||||
const flip = ({ width, height }: ViewportStyles) => ({ height: width, width: height });
|
||||
|
||||
const deprecatedViewportString = deprecate(
|
||||
() => 0,
|
||||
@ -37,56 +50,69 @@ const deprecateOnViewportChange = deprecate(
|
||||
'The viewport parameter `onViewportChange` is no longer supported'
|
||||
);
|
||||
|
||||
const getState = memoize(10)((props, state, change) => {
|
||||
const data = props.api.getCurrentStoryData();
|
||||
const parameters = data && data.parameters && data.parameters[PARAM_KEY];
|
||||
const getState = memoize(10)(
|
||||
(
|
||||
props: ViewportToolProps,
|
||||
state: ViewportToolState,
|
||||
change: (statePatch: Partial<ViewportToolState>) => void
|
||||
) => {
|
||||
const data = props.api.getCurrentStoryData();
|
||||
const parameters: ViewportAddonParameter =
|
||||
data && (data as any).parameters && (data as any).parameters[PARAM_KEY];
|
||||
|
||||
if (parameters && typeof parameters !== 'object') {
|
||||
deprecatedViewportString();
|
||||
}
|
||||
if (parameters && typeof parameters !== 'object') {
|
||||
deprecatedViewportString();
|
||||
}
|
||||
|
||||
const { disable, viewports, defaultViewport, onViewportChange } = parameters || {};
|
||||
const { disable, viewports, defaultViewport, onViewportChange } = parameters || ({} as any);
|
||||
|
||||
if (onViewportChange) {
|
||||
deprecateOnViewportChange();
|
||||
}
|
||||
if (onViewportChange) {
|
||||
deprecateOnViewportChange();
|
||||
}
|
||||
|
||||
const list = disable ? [] : toList(viewports || INITIAL_VIEWPORTS);
|
||||
const list = disable ? [] : toList(viewports || INITIAL_VIEWPORTS);
|
||||
const viewportVMList = list.map(({ id, name, styles: value }) =>
|
||||
createItem(id, name, value, change)
|
||||
);
|
||||
|
||||
const selected =
|
||||
state.selected === 'responsive' || list.find(i => i.id === state.selected)
|
||||
? state.selected
|
||||
: list.find(i => i.default) || defaultViewport || DEFAULT_VIEWPORT;
|
||||
const selected =
|
||||
state.selected === 'responsive' || list.find(i => i.id === state.selected)
|
||||
? state.selected
|
||||
: list.find(i => i.default) || defaultViewport || DEFAULT_VIEWPORT;
|
||||
|
||||
const resets =
|
||||
selected !== 'responsive'
|
||||
? [
|
||||
{
|
||||
id: 'reset',
|
||||
title: 'Reset viewport',
|
||||
onClick: () => {
|
||||
change({ selected: undefined, expanded: false });
|
||||
const resets: ViewportVM[] =
|
||||
selected !== 'responsive'
|
||||
? [
|
||||
{
|
||||
id: 'reset',
|
||||
title: 'Reset viewport',
|
||||
onClick: () => {
|
||||
change({ selected: undefined, expanded: false });
|
||||
},
|
||||
right: undefined,
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'rotate',
|
||||
title: 'Rotate viewport',
|
||||
onClick: () => {
|
||||
change({ isRotated: !state.isRotated, expanded: false });
|
||||
{
|
||||
id: 'rotate',
|
||||
title: 'Rotate viewport',
|
||||
onClick: () => {
|
||||
change({ isRotated: !state.isRotated, expanded: false });
|
||||
},
|
||||
right: undefined,
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
]
|
||||
: [];
|
||||
const items = list.length
|
||||
? resets.concat(list.map(({ id, name, styles: value }) => createItem(id, name, value, change)))
|
||||
: list;
|
||||
]
|
||||
: [];
|
||||
|
||||
return {
|
||||
isRotated: state.isRotated,
|
||||
items,
|
||||
selected,
|
||||
};
|
||||
});
|
||||
const items = viewportVMList.length !== 0 ? resets.concat(viewportVMList) : [];
|
||||
|
||||
return {
|
||||
isRotated: state.isRotated,
|
||||
items,
|
||||
selected,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ActiveViewportSize = styled.div(() => ({
|
||||
display: 'inline-flex',
|
||||
@ -116,8 +142,20 @@ const IconButtonLabel = styled.div(({ theme }) => ({
|
||||
marginLeft: '10px',
|
||||
}));
|
||||
|
||||
export default class ViewportTool extends Component {
|
||||
constructor(props) {
|
||||
interface ViewportToolState {
|
||||
isRotated: boolean;
|
||||
items: any[];
|
||||
selected: string;
|
||||
expanded: boolean;
|
||||
}
|
||||
interface ViewportToolProps {
|
||||
api: any;
|
||||
}
|
||||
|
||||
export class ViewportTool extends Component<ViewportToolProps, ViewportToolState> {
|
||||
listener: () => void;
|
||||
|
||||
constructor(props: ViewportToolProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@ -144,12 +182,16 @@ export default class ViewportTool extends Component {
|
||||
api.off(SET_STORIES, this.listener);
|
||||
}
|
||||
|
||||
change = (...args) => this.setState(...args);
|
||||
// @ts-ignore
|
||||
change = (...args: any[]) => this.setState(...args);
|
||||
|
||||
flipViewport = () =>
|
||||
this.setState(({ isRotated }) => ({ isRotated: !isRotated, expanded: false }));
|
||||
this.setState(({ isRotated }: { isRotated: boolean }) => ({
|
||||
isRotated: !isRotated,
|
||||
expanded: false,
|
||||
}));
|
||||
|
||||
resetViewport = e => {
|
||||
resetViewport = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
e.stopPropagation();
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
|
||||
@ -161,8 +203,8 @@ export default class ViewportTool extends Component {
|
||||
const { items, selected, isRotated } = getState(this.props, this.state, this.change);
|
||||
const item = items.find(i => i.id === selected);
|
||||
|
||||
let viewportX = 0;
|
||||
let viewportY = 0;
|
||||
let viewportX = '0';
|
||||
let viewportY = '0';
|
||||
let viewportTitle = '';
|
||||
if (item) {
|
||||
const height = item.value.height.replace('px', '');
|
||||
@ -188,7 +230,7 @@ export default class ViewportTool extends Component {
|
||||
boxShadow: '0 4px 8px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.08);',
|
||||
boxSizing: 'content-box',
|
||||
|
||||
...(isRotated ? flip(item.value || {}) : item.value || {}),
|
||||
...(isRotated ? flip(item.value) : item.value),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@ -224,9 +266,3 @@ export default class ViewportTool extends Component {
|
||||
) : null;
|
||||
}
|
||||
}
|
||||
|
||||
ViewportTool.propTypes = {
|
||||
api: PropTypes.shape({
|
||||
on: PropTypes.func,
|
||||
}).isRequired,
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
export const ADDON_ID = 'storybook/viewport';
|
||||
export const PARAM_KEY = 'viewport';
|
||||
|
||||
export default {
|
||||
UPDATE: `${ADDON_ID}/update`,
|
||||
CONFIGURE: `${ADDON_ID}/configure`,
|
||||
SET: `${ADDON_ID}/setStoryDefaultViewport`,
|
||||
CHANGED: `${ADDON_ID}/viewportChanged`,
|
||||
};
|
7
addons/viewport/src/constants.ts
Normal file
7
addons/viewport/src/constants.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export const ADDON_ID = 'storybook/viewport';
|
||||
export const PARAM_KEY = 'viewport';
|
||||
|
||||
export const UPDATE = `${ADDON_ID}/update`;
|
||||
export const CONFIGURE = `${ADDON_ID}/configure`;
|
||||
export const SET = `${ADDON_ID}/setStoryDefaultViewport`;
|
||||
export const CHANGED = `${ADDON_ID}/viewportChanged`;
|
@ -1,4 +1,6 @@
|
||||
export const INITIAL_VIEWPORTS = {
|
||||
import { ViewportMap } from './models';
|
||||
|
||||
export const INITIAL_VIEWPORTS: ViewportMap = {
|
||||
iphone5: {
|
||||
name: 'iPhone 5',
|
||||
styles: {
|
@ -1,7 +1,6 @@
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
export { INITIAL_VIEWPORTS, DEFAULT_VIEWPORT } from '../defaults';
|
||||
export { default as withViewport } from './withViewport';
|
||||
|
||||
export const configureViewport = deprecate(() => {},
|
||||
'configureViewport is no longer supported, use .addParameters({ viewport }) instead');
|
@ -1,11 +1,11 @@
|
||||
import { makeDecorator } from '@storybook/addons';
|
||||
import { makeDecorator, StoryGetter, StoryContext } from '@storybook/addons';
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
const withViewport = makeDecorator({
|
||||
name: 'withViewport',
|
||||
parameterName: 'viewport',
|
||||
wrapper: deprecate(
|
||||
(getStory, context) => getStory(context),
|
||||
(getStory: StoryGetter, context: StoryContext) => getStory(context),
|
||||
'withViewport is no longer supported, use .addParameters({ viewport }) instead'
|
||||
),
|
||||
});
|
19
addons/viewport/src/models/Viewport.ts
Normal file
19
addons/viewport/src/models/Viewport.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export interface Viewport {
|
||||
name: string;
|
||||
styles: ViewportStyles;
|
||||
type: 'desktop' | 'mobile' | 'tablet';
|
||||
/*
|
||||
* @deprecated
|
||||
* Deprecated option?
|
||||
*/
|
||||
default?: boolean;
|
||||
}
|
||||
|
||||
export interface ViewportStyles {
|
||||
height: string;
|
||||
width: string;
|
||||
}
|
||||
|
||||
export interface ViewportMap {
|
||||
[key: string]: Viewport;
|
||||
}
|
12
addons/viewport/src/models/ViewportAddonParameter.ts
Normal file
12
addons/viewport/src/models/ViewportAddonParameter.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { ViewportMap } from './Viewport';
|
||||
|
||||
export interface ViewportAddonParameter {
|
||||
disable: boolean;
|
||||
defaultViewport: string;
|
||||
viewports: ViewportMap;
|
||||
/*
|
||||
* @deprecated
|
||||
* The viewport parameter `onViewportChange` is no longer supported
|
||||
*/
|
||||
onViewportChange?: never;
|
||||
}
|
2
addons/viewport/src/models/index.ts
Normal file
2
addons/viewport/src/models/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './Viewport';
|
||||
export * from './ViewportAddonParameter';
|
@ -3,13 +3,13 @@ import addons, { types } from '@storybook/addons';
|
||||
|
||||
import { ADDON_ID } from './constants';
|
||||
|
||||
import Tool from './Tool';
|
||||
import { ViewportTool } from './Tool';
|
||||
|
||||
addons.register(ADDON_ID, api => {
|
||||
addons.add(ADDON_ID, {
|
||||
title: 'viewport / media-queries',
|
||||
type: types.TOOL,
|
||||
match: ({ viewMode }) => viewMode === 'story',
|
||||
render: () => <Tool api={api} />,
|
||||
render: () => <ViewportTool api={api} />,
|
||||
});
|
||||
});
|
13
addons/viewport/tsconfig.json
Normal file
13
addons/viewport/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"types": ["webpack-env"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/__tests__/**/*"
|
||||
]
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/angular",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,8 +26,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/node-logger": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"@storybook/node-logger": "5.2.0-alpha.32",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"core-js": "^3.0.1",
|
||||
"fork-ts-checker-webpack-plugin": "^1.3.4",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/ember",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
||||
"homepage": "https://github.com/storybookjs/storybook/tree/master/app/ember",
|
||||
"bugs": {
|
||||
@ -24,7 +24,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/test-helpers": "^1.5.0",
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/html",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,7 +25,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/marko",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Marko: Develop Marko Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -26,7 +26,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/mithril",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Mithril: Develop Mithril Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -27,7 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/polymer",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Polymer: Develop Polymer components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,7 +25,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"@webcomponents/webcomponentsjs": "^1.2.0",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/preact",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Preact: Develop Preact Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -27,7 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -3,7 +3,7 @@
|
||||
Storybook for Rax is a UI development environment for your Rax components.
|
||||
With it, you can visualize different states of your UI components and develop them interactively.
|
||||
|
||||

|
||||

|
||||
|
||||
Storybook runs outside of your app.
|
||||
So you can develop UI components in isolation without worrying about app specific dependencies and requirements.
|
||||
|
@ -1,18 +1,18 @@
|
||||
{
|
||||
"name": "@storybook/rax",
|
||||
"version": "5.2.0-alpha.23",
|
||||
"version": "5.2.0-alpha.32",
|
||||
"description": "Storybook for Rax: Develop Rax Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook",
|
||||
"rax"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/rax",
|
||||
"homepage": "https://github.com/storybookjs/storybook/tree/master/app/rax",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
"url": "https://github.com/storybookjs/storybook/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/storybooks/storybook.git",
|
||||
"url": "https://github.com/storybookjs/storybook.git",
|
||||
"directory": "app/rax"
|
||||
},
|
||||
"license": "MIT",
|
||||
@ -27,8 +27,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.2.0-alpha.32",
|
||||
"babel-preset-rax": "^1.0.0-beta.0",
|
||||
"@storybook/core": "5.2.0-alpha.23",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.6.2",
|
||||
"global": "^4.3.2",
|
||||
|
@ -7,4 +7,5 @@ export {
|
||||
getStorybook,
|
||||
forceReRender,
|
||||
raw,
|
||||
load,
|
||||
} from './preview';
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user