mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-17 05:02:23 +08:00
Merge branch 'release/4.1'
This commit is contained in:
commit
bc54bbd143
53
.babelrc
53
.babelrc
@ -1,53 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-flow"
|
||||
],
|
||||
"plugins": [
|
||||
"babel-plugin-emotion",
|
||||
"babel-plugin-macros",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
[
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
"regenerator": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"plugins": ["babel-plugin-require-context-hook"]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"test": "./examples/vue-kitchen-sink",
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"babel-preset-vue"
|
||||
]
|
||||
},
|
||||
{
|
||||
"test": [
|
||||
"./lib/core/src/server",
|
||||
"./lib/node-logger",
|
||||
"./lib/codemod",
|
||||
"./addons/storyshots",
|
||||
"./addons/storysource/src/loader",
|
||||
"./app/**/src/server/**"
|
||||
],
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": "8.11"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
50
.babelrc.js
Normal file
50
.babelrc.js
Normal file
@ -0,0 +1,50 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage' }],
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-flow',
|
||||
],
|
||||
plugins: [
|
||||
'babel-plugin-emotion',
|
||||
'babel-plugin-macros',
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
'@babel/plugin-proposal-export-default-from',
|
||||
],
|
||||
env: {
|
||||
test: {
|
||||
presets: [['@babel/preset-env', { shippedProposals: true, useBuiltIns: 'usage' }]],
|
||||
plugins: ['babel-plugin-require-context-hook', 'babel-plugin-dynamic-import-node'],
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
test: './examples/vue-kitchen-sink',
|
||||
presets: ['babel-preset-vue'],
|
||||
},
|
||||
{
|
||||
test: [
|
||||
'./lib/core/src/server',
|
||||
'./lib/node-logger',
|
||||
'./lib/codemod',
|
||||
'./addons/storyshots',
|
||||
'./addons/storysource/src/loader',
|
||||
'./app/**/src/server/**',
|
||||
'./app/**/src/bin/**',
|
||||
'./dangerfile.js',
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
shippedProposals: true,
|
||||
useBuiltIns: 'usage',
|
||||
targets: {
|
||||
node: '8.11',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
@ -120,52 +120,52 @@ jobs:
|
||||
name: Run react kitchen-sink (smoke test)
|
||||
command: |
|
||||
cd examples/cra-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run vue kitchen-sink (smoke test)
|
||||
command: |
|
||||
cd examples/vue-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run svelte kitchen-sink (smoke test)
|
||||
command: |
|
||||
cd examples/svelte-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run angular-cli (smoke test)
|
||||
command: |
|
||||
cd examples/angular-cli
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run ember-cli (smoke test)
|
||||
command: |
|
||||
cd examples/ember-cli
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run polymer-cli (smoke test)
|
||||
command: |
|
||||
cd examples/polymer-cli
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run marko-cli (smoke test)
|
||||
command: |
|
||||
cd examples/marko-cli
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run official-storybook (smoke test)
|
||||
command: |
|
||||
cd examples/official-storybook
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run mithril kitchen-sink (smoke test)
|
||||
command: |
|
||||
cd examples/mithril-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
- run:
|
||||
name: Run riot kitchen-sink (smoke test)
|
||||
command: |
|
||||
cd examples/riot-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
native-smoke-tests:
|
||||
<<: *defaults
|
||||
steps:
|
||||
|
@ -1,4 +1,5 @@
|
||||
dist
|
||||
lib/**/dll
|
||||
build
|
||||
coverage
|
||||
node_modules
|
||||
|
@ -123,6 +123,12 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/__tests__/**', '**/*.test.js/**', '**/*.spec.js/**'],
|
||||
rules: {
|
||||
'import/no-extraneous-dependencies': ignore,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/react-native*/**', '**/REACT_NATIVE*/**', '**/crna*/**'],
|
||||
rules: {
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,3 +23,4 @@ integration/__image_snapshots__/__diff_output__
|
||||
.jest-test-results.json
|
||||
/examples/cra-kitchen-sink/src/__image_snapshots__/__diff_output__/
|
||||
lib/*.jar
|
||||
lib/**/dll
|
||||
|
@ -17,6 +17,7 @@ object OpenSourceProjects_Storybook_Bootstrap : BuildType({
|
||||
addons/storyshots/*/dist/** => dist.zip/addons/storyshots
|
||||
app/*/dist/** => dist.zip/app
|
||||
lib/*/dist/** => dist.zip/lib
|
||||
lib/core/dll/** => dist.zip/lib/core/dll
|
||||
""".trimIndent()
|
||||
|
||||
vcs {
|
||||
|
@ -12,10 +12,10 @@ object OpenSourceProjects_Storybook_Examples : BuildType({
|
||||
name = "Examples"
|
||||
|
||||
artifactRules = """
|
||||
${StorybookApp.values().map { it.artifactPath }.joinToString("\n")}
|
||||
examples/official-storybook/storybook-static => official.zip
|
||||
examples/official-storybook/image-snapshots/__image_snapshots__ => image-snapshots
|
||||
""".trimIndent()
|
||||
${StorybookApp.values().map { it.artifactPath }.joinToString("\n")}
|
||||
examples/official-storybook/storybook-static => official.zip
|
||||
examples/official-storybook/image-snapshots/__image_snapshots__ => image-snapshots
|
||||
""".trimIndent()
|
||||
|
||||
vcs {
|
||||
root(OpenSourceProjects_Storybook.vcsRoots.OpenSourceProjects_Storybook_HttpsGithubComStorybooksStorybookRefsHeadsMaster)
|
||||
|
@ -30,7 +30,7 @@ object OpenSourceProjects_Storybook_SmokeTests : BuildType({
|
||||
set -e -x
|
||||
|
||||
cd examples/$exampleDir
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
""".trimIndent()
|
||||
dockerImage = "node:%docker.node.version%"
|
||||
}
|
||||
@ -44,7 +44,7 @@ object OpenSourceProjects_Storybook_SmokeTests : BuildType({
|
||||
set -e -x
|
||||
|
||||
cd examples/official-storybook
|
||||
yarn storybook --smoke-test
|
||||
yarn storybook --smoke-test --quiet
|
||||
""".trimIndent()
|
||||
dockerImage = "node:%docker.node.version%"
|
||||
}
|
||||
|
@ -83,7 +83,9 @@ enum class StorybookApp(val appName: String, val exampleDir: String, val merged:
|
||||
}
|
||||
|
||||
artifacts {
|
||||
artifactRules = "dist.zip!**"
|
||||
artifactRules = """
|
||||
dist.zip!**
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|[links](addons/links) |+|+|+|+|+|+|+| |+|+|+|
|
||||
|[notes](addons/notes) |+|+*|+|+|+|+|+| |+|+|+|
|
||||
|[options](addons/options) |+|+|+|+|+|+|+| |+|+|+|
|
||||
|[cssresources](addons/cssresources) |+| |+|+|+|+|+|+|+|+|+|
|
||||
|[storyshots](addons/storyshots) |+|+|+|+| | |+| |+|+| |
|
||||
|[storysource](addons/storysource) |+| |+|+|+|+|+|+|+|+|+|
|
||||
|[viewport](addons/viewport) |+| |+|+|+|+|+|+|+|+|+|
|
||||
|
672
CHANGELOG.md
672
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Norbert de Langen ndelangen@me.com
|
||||
Copyright (c) 2017 Kadira Inc. <hello@kadira.io>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
65
README.md
65
README.md
@ -1,17 +1,20 @@
|
||||
# Storybook
|
||||
|
||||
[](https://teamcity.jetbrains.com/viewType.html?buildTypeId=OpenSourceProjects_Storybook_Build_2&branch_OpenSourceProjects_Storybook=%3Cdefault%3E&tab=buildTypeStatusDiv)
|
||||
[](https://circleci.com/gh/storybooks/storybook)
|
||||
[](https://www.codefactor.io/repository/github/storybooks/storybook)
|
||||
[](https://snyk.io/test/github/storybooks/storybook)
|
||||
[](https://bettercodehub.com/results/storybooks/storybook)
|
||||
[](https://codecov.io/gh/storybooks/storybook)
|
||||
[](https://now-examples-slackin-rrirkqohko.now.sh/)
|
||||
[](#backers)
|
||||
[](#sponsors)
|
||||
[](https://github.com/storybooks/storybook/blob/master/LICENSE)
|
||||
|
||||
<!-- [](https://www.browserstack.com/automate/public-build/<badge_key>) -->
|
||||
<p align="center">
|
||||
<a href="https://teamcity.jetbrains.com/viewType.html?buildTypeId=OpenSourceProjects_Storybook_Build_2&branch_OpenSourceProjects_Storybook=%3Cdefault%3E&tab=buildTypeStatusDiv"><img src="https://teamcity.jetbrains.com/app/rest/builds/buildType:OpenSourceProjects_Storybook_Build_2/statusIcon.svg" alt="Build Status on TeamCity" /></a>
|
||||
<a href="https://circleci.com/gh/storybooks/storybook"><img src="https://circleci.com/gh/storybooks/storybook.svg?style=shield" alt="Build Status on CircleCI" /></a>
|
||||
<a href="https://www.codefactor.io/repository/github/storybooks/storybook"><img src="https://www.codefactor.io/repository/github/storybooks/storybook/badge" alt="CodeFactor" /></a>
|
||||
<a href="https://snyk.io/test/github/storybooks/storybook"><img src="https://snyk.io/test/github/storybooks/storybook/badge.svg" alt="Known Vulnerabilities" /></a>
|
||||
<a href="https://bettercodehub.com/results/storybooks/storybook"><img src="https://bettercodehub.com/edge/badge/storybooks/storybook" alt="BCH compliance" /></a>
|
||||
<a href="https://codecov.io/gh/storybooks/storybook"><img src="https://codecov.io/gh/storybooks/storybook/branch/master/graph/badge.svg" alt="codecov" /></a>
|
||||
<a href="https://github.com/storybooks/storybook/blob/master/LICENSE"><img src="https://img.shields.io/github/license/storybooks/storybook.svg" alt="License" /></a></p>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/sMFvFsG"><img src="https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat" /></a>
|
||||
<a href="https://now-examples-slackin-rrirkqohko.now.sh/"><img src="https://now-examples-slackin-rrirkqohko.now.sh/badge.svg?logo=slack" alt="Storybook Slack" /></a>
|
||||
<a href="#backers"><img src="https://opencollective.com/storybook/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||
<a href="#sponsors"><img src="https://opencollective.com/storybook/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
@ -21,13 +24,14 @@ It allows you to browse a component library, view the different states of each c
|
||||
## Intro
|
||||
|
||||
<center>
|
||||
<img src="media/storybook-intro.gif" width="100%" />
|
||||
<img src="media/storybook-intro.gif" width="100%" />
|
||||
</center>
|
||||
|
||||
README for:
|
||||
|
||||
- [](https://github.com/storybooks/storybook)
|
||||
- [](https://github.com/storybooks/storybook/tree/master)
|
||||
<p align="center">
|
||||
README for:<br/>
|
||||
<a href="https://img.shields.io/npm/v/@storybook/core/latest.svg" title="latest"><img alt="latest" src="https://img.shields.io/npm/v/@storybook/core/latest.svg" /></a>
|
||||
<a href="https://img.shields.io/npm/v/@storybook/core/next.svg" title="next"><img alt="next" src="https://img.shields.io/npm/v/@storybook/core/next.svg" /></a>
|
||||
</p>
|
||||
|
||||
Storybook runs outside of your app. This allows you to develop UI components in isolation, which can improve component reuse, testability, and development speed. You can build quickly without having to worry about application-specific dependencies.
|
||||
|
||||
@ -79,19 +83,19 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl
|
||||
|
||||
### Supported Frameworks
|
||||
|
||||
| Framework | Demo latest | Demo prerelease | |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| [React](app/react) | [v3.4.x](https://release-3-4--storybooks-official.netlify.com), [v3.3.x](https://release-3-3--storybooks-official.netlify.com) | [v4.0.0](https://storybooks-official.netlify.com) | [](app/react) |
|
||||
| [React Native](app/react-native) | - | - | [](app/react-native) |
|
||||
| [Vue](app/vue) | [v3.4.x](https://release-3-4--storybooks-vue.netlify.com/), [v3.3.x](https://release-3-3--storybooks-vue.netlify.com/) | [v4.0.0](https://storybooks-vue.netlify.com/) | [](app/vue) |
|
||||
| [Angular](app/angular) | [v3.4.x](https://release-3-4--storybooks-angular.netlify.com/), [v3.3.x](https://release-3-3--storybooks-angular.netlify.com/) | [v4.0.0](https://storybooks-angular.netlify.com/) | [](app/angular) |
|
||||
| [Polymer](app/polymer) | [v3.4.x](https://release-3-4--storybooks-polymer.netlify.com/) | [v4.0.0](https://storybooks-polymer.netlify.com/) | [](app/polymer) |
|
||||
| [Mithril](app/mithril) | - | [v4.0.0](https://storybooks-mithril.netlify.com/) | [](app/mithril) |
|
||||
| [Marko](app/marko) | - | [v4.0.0](https://storybooks-marko.netlify.com/) | [](app/marko) |
|
||||
| [HTML](app/html) | - | [v4.0.0](https://storybooks-html.netlify.com/) | [](app/html) |
|
||||
| [Svelte](app/svelte) | - | [v4.0.0](https://storybooks-svelte.netlify.com/) | [](app/svelte) |
|
||||
| [Riot](app/riot) | - | [v4.0.0](https://storybooks-riot.netlify.com/) | [](app/riot) |
|
||||
| [Ember](app/ember) | - | [v4.0.0](https://storybooks-ember.netlify.com/) | [](app/ember) |
|
||||
| Framework | Demo | |
|
||||
| -------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| [React](app/react) | [v4.0.0](https://storybooks-official.netlify.com) | [](app/react) |
|
||||
| [React Native](app/react-native) | - | [](app/react-native) |
|
||||
| [Vue](app/vue) | [v4.0.0](https://storybooks-vue.netlify.com/) | [](app/vue) |
|
||||
| [Angular](app/angular) | [v4.0.0](https://storybooks-angular.netlify.com/) | [](app/angular) |
|
||||
| [Polymer](app/polymer) | [v4.0.0](https://storybooks-polymer.netlify.com/) | [](app/polymer) |
|
||||
| [Mithril](app/mithril) | [v4.0.0](https://storybooks-mithril.netlify.com/) | [](app/mithril) |
|
||||
| [Marko](app/marko) | [v4.0.0](https://storybooks-marko.netlify.com/) | [](app/marko) |
|
||||
| [HTML](app/html) | [v4.0.0](https://storybooks-html.netlify.com/) | [](app/html) |
|
||||
| [Svelte](app/svelte) | [v4.0.0](https://storybooks-svelte.netlify.com/) | [](app/svelte) |
|
||||
| [Riot](app/riot) | [v4.0.0](https://storybooks-riot.netlify.com/) | [](app/riot) |
|
||||
| [Ember](app/ember) | [v4.0.0](https://storybooks-ember.netlify.com/) | [](app/ember) |
|
||||
|
||||
### Sub Projects
|
||||
|
||||
@ -106,6 +110,7 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl
|
||||
| [actions](addons/actions/) | Log actions as users interact with components in the Storybook UI |
|
||||
| [backgrounds](addons/backgrounds/) | Let users choose backgrounds in the Storybook UI |
|
||||
| [centered](addons/centered/) | Center the alignment of your components within the Storybook UI |
|
||||
| [cssresources](addons/cssresources/) | Dynamically add/remove css resources to the component iframe |
|
||||
| [events](addons/events/) | Interactively fire events to components that respond to EventEmitter |
|
||||
| [graphql](addons/graphql/) | Query a GraphQL server within Storybook stories |
|
||||
| [google-analytics](addons/google-analytics) | Reports google analytics on stories |
|
||||
|
@ -1,6 +1,6 @@
|
||||
# storybook-addon-a11y
|
||||
|
||||
This storybook addon can be helpfull to make your UI components more accessibile.
|
||||
This storybook addon can be helpful to make your UI components more accessible.
|
||||
|
||||
[Framework Support](https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-a11y",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "a11y addon for storybook",
|
||||
"keywords": [
|
||||
"a11y",
|
||||
@ -11,9 +11,6 @@
|
||||
"verify"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook#readme",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -29,10 +26,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/client-logger": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/client-logger": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"axe-core": "^3.1.2",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2"
|
||||
@ -40,5 +37,8 @@
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,14 @@ export const configureA11y = (options = {}) => {
|
||||
|
||||
const runA11yCheck = () => {
|
||||
const channel = addons.getChannel();
|
||||
const infoWrapper = document.getElementById('story-root').children;
|
||||
const wrapper = document.getElementById('root');
|
||||
|
||||
axe.reset();
|
||||
axe.configure(axeOptions);
|
||||
axe.run(wrapper).then(results => channel.emit(CHECK_EVENT_ID, results), logger.error);
|
||||
axe
|
||||
.run(infoWrapper || wrapper)
|
||||
.then(results => channel.emit(CHECK_EVENT_ID, results), logger.error);
|
||||
};
|
||||
|
||||
const a11ySubscription = () => {
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/addon-actions",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Action Logger addon for storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/actions",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -26,9 +23,9 @@
|
||||
"@emotion/core": "^0.13.1",
|
||||
"@emotion/provider": "^0.11.2",
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"deep-equal": "^1.0.1",
|
||||
"global": "^4.3.2",
|
||||
"lodash": "^4.17.11",
|
||||
@ -39,5 +36,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-backgrounds",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -9,9 +9,6 @@
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/backgrounds",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,13 +25,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"eventemitter3": "^3.1.0",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import EventEmitter from 'events';
|
||||
import EventEmitter from 'eventemitter3';
|
||||
|
||||
import BackgroundPanel from '../BackgroundPanel';
|
||||
import Events from '../constants';
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-centered",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook decorator to center components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/centered",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -26,5 +23,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"global": "^4.3.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
63
addons/cssresources/README.md
Normal file
63
addons/cssresources/README.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Storybook Addon Cssresources
|
||||
|
||||
Storybook Addon Cssresources to switch between css resources at runtime for your story [Storybook](https://storybook.js.org).
|
||||
|
||||
[Framework Support](https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md)
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
yarn add -D @storybook/addon-cssresources
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Then create a file called `addons.js` in your storybook config.
|
||||
|
||||
Add following content to it:
|
||||
|
||||
```js
|
||||
import '@storybook/addon-cssresources/register';
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
You need add the all the css resources at compile time using the `withCssResources` decorator. They can be added globally or per story. You can then choose which ones to load from the cssresources addon ui:
|
||||
|
||||
```js
|
||||
// Import from @storybook/X where X is your framework
|
||||
import { configure, addDecorator, storiesOf } from '@storybook/react';
|
||||
import { withCssResources } from '@storybook/addon-cssresources';
|
||||
|
||||
// global
|
||||
addDecorator(
|
||||
withCssResources({
|
||||
cssresources: [{
|
||||
name: `bluetheme`,
|
||||
code: `<style>body { background-color: lightblue; }</style>`,
|
||||
picked: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// per story
|
||||
storiesOf('Addons|Cssresources', module)
|
||||
.addDecorator(
|
||||
withCssResources({
|
||||
cssresources: [{
|
||||
name: `fontawesome`,
|
||||
code: `<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"></link>`,
|
||||
picked: true,
|
||||
}, {
|
||||
name: `whitetheme`,
|
||||
code: `<style>.fa { color: #fff }</style>`,
|
||||
picked: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
.add('Camera Icon', () => <i className="fa fa-camera-retro"> Camera Icon</i>);
|
||||
```
|
BIN
addons/cssresources/docs/demo.gif
Normal file
BIN
addons/cssresources/docs/demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 MiB |
42
addons/cssresources/package.json
Normal file
42
addons/cssresources/package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "@storybook/addon-cssresources",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "A storybook addon to switch between css resources at runtime for your story",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"cssresources",
|
||||
"react",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://storybook.js.org",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/storybooks/storybook.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "nm123github",
|
||||
"main": "dist/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"scripts": {
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "0.10.6",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-syntax-highlighter": "^10.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
1
addons/cssresources/register.js
Normal file
1
addons/cssresources/register.js
Normal file
@ -0,0 +1 @@
|
||||
require('./dist/register.js');
|
147
addons/cssresources/src/CssResourcePanel.js
Normal file
147
addons/cssresources/src/CssResourcePanel.js
Normal file
@ -0,0 +1,147 @@
|
||||
import { document, DOMParser } from 'global';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { monoFonts } from '@storybook/components';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import css from 'react-syntax-highlighter/dist/esm/languages/prism/css';
|
||||
import { darcula } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light';
|
||||
|
||||
SyntaxHighlighter.registerLanguage('css', css);
|
||||
|
||||
const storybookIframe = 'storybook-preview-iframe';
|
||||
const addedElAttr = 'addedbycssresourcesaddon';
|
||||
|
||||
// Taken from StoryPanel.js
|
||||
const highlighterTheme = {
|
||||
...darcula,
|
||||
'pre[class*="language-"]': {
|
||||
...darcula['pre[class*="language-"]'],
|
||||
margin: 'auto',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
minHeight: '100%',
|
||||
overflow: 'hidden',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
fontFamily: monoFonts.fontFamily,
|
||||
fontSize: 'inherit',
|
||||
},
|
||||
'code[class*="language-"]': {
|
||||
...darcula['code[class*="language-"]'],
|
||||
margin: 0,
|
||||
fontFamily: 'inherit',
|
||||
},
|
||||
};
|
||||
|
||||
const PanelWrapper = styled.div({
|
||||
position: 'absolute',
|
||||
top: '10px',
|
||||
left: '10px',
|
||||
fontFamily: monoFonts.fontFamily,
|
||||
});
|
||||
|
||||
export default class CssResourcePanel extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { cssresources: `` };
|
||||
this.onAddCssresources = this.onAddCssresources.bind(this);
|
||||
this.parser = new DOMParser();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { channel } = this.props;
|
||||
this.iframe = document.getElementById(storybookIframe);
|
||||
if (!this.iframe) {
|
||||
throw new Error('Cannot find Storybook iframe');
|
||||
}
|
||||
channel.on('storybook/resources/add_cssresources', this.onAddCssresources);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { channel } = this.props;
|
||||
channel.removeListener('storybook/resources/add_cssresources', this.onAddCssresources);
|
||||
}
|
||||
|
||||
onAddCssresources(cssresources) {
|
||||
this.loadCssresources(cssresources.filter(res => res.picked));
|
||||
this.setState(prevState => ({ ...prevState, cssresources }));
|
||||
}
|
||||
|
||||
handleChange(i, { target }) {
|
||||
const { channel } = this.props;
|
||||
const { cssresources = [] } = this.state;
|
||||
cssresources[i].picked = target.checked;
|
||||
channel.emit('storybook/resources/add_cssresources', cssresources);
|
||||
}
|
||||
|
||||
loadCssresources(cssresources) {
|
||||
// remove previously added elements!
|
||||
this.iframe.contentDocument.head.querySelectorAll(`[${addedElAttr}]`).forEach(eL => {
|
||||
if (eL) {
|
||||
eL.parentNode.removeChild(eL);
|
||||
}
|
||||
});
|
||||
|
||||
// add new elements!
|
||||
const str = cssresources.map(res => res.code).join('');
|
||||
const parsedHtml = this.parser.parseFromString(str, 'text/html');
|
||||
const elements = parsedHtml.querySelectorAll('head > *');
|
||||
elements.forEach(eL => {
|
||||
// add addedElAttr to css elements
|
||||
eL.setAttribute(addedElAttr, '');
|
||||
this.iframe.contentDocument.head.appendChild(eL);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { cssresources = [] } = this.state;
|
||||
const { active } = this.props;
|
||||
|
||||
if (!active) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<PanelWrapper className="addon-cssresources-container">
|
||||
{cssresources &&
|
||||
cssresources.map(({ name, code, picked }, i) => (
|
||||
<div key={name} style={{ padding: 10 }}>
|
||||
<div style={{ fontSize: '1.1em', marginBottom: 10 }}>
|
||||
<input
|
||||
id={`cssresource${i}`}
|
||||
style={{ fontSize: '1.5em' }}
|
||||
type="checkbox"
|
||||
checked={picked}
|
||||
onChange={this.handleChange.bind(this, i)}
|
||||
/>
|
||||
<label htmlFor={`cssresource${i}`}>#{name}</label>
|
||||
</div>
|
||||
<SyntaxHighlighter
|
||||
language="css"
|
||||
style={highlighterTheme}
|
||||
customStyle={{ opacity: picked ? 1 : 0.5 }}
|
||||
>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
))}
|
||||
</PanelWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CssResourcePanel.propTypes = {
|
||||
active: PropTypes.bool.isRequired,
|
||||
channel: PropTypes.shape({
|
||||
on: PropTypes.func,
|
||||
emit: PropTypes.func,
|
||||
removeListener: PropTypes.func,
|
||||
}).isRequired,
|
||||
api: PropTypes.shape({
|
||||
onStory: PropTypes.func,
|
||||
getQueryParam: PropTypes.func,
|
||||
setQueryParams: PropTypes.func,
|
||||
}).isRequired,
|
||||
};
|
23
addons/cssresources/src/index.js
Normal file
23
addons/cssresources/src/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import addons, { makeDecorator } from '@storybook/addons';
|
||||
|
||||
export const withCssResources = makeDecorator({
|
||||
name: 'withCssResources',
|
||||
parameterName: 'cssresources',
|
||||
skipIfNoParametersOrOptions: true,
|
||||
allowDeprecatedUsage: false,
|
||||
wrapper: (getStory, context, { options, parameters }) => {
|
||||
const channel = addons.getChannel();
|
||||
const storyOptions = parameters || options;
|
||||
|
||||
if (!Array.isArray(storyOptions) && !Array.isArray(storyOptions.cssresources)) {
|
||||
throw new Error('The `cssresources` parameter needs to be an Array');
|
||||
}
|
||||
|
||||
channel.emit(
|
||||
'storybook/resources/add_cssresources',
|
||||
Array.isArray(storyOptions) ? storyOptions : storyOptions.cssresources
|
||||
);
|
||||
|
||||
return getStory(context);
|
||||
},
|
||||
});
|
12
addons/cssresources/src/register.js
Normal file
12
addons/cssresources/src/register.js
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import addons from '@storybook/addons';
|
||||
import CssResourcePanel from './CssResourcePanel';
|
||||
|
||||
addons.register('storybook/cssresources', api => {
|
||||
const channel = addons.getChannel();
|
||||
addons.addPanel('storybook/cssresources/panel', {
|
||||
title: 'Cssresources',
|
||||
// eslint-disable-next-line react/prop-types
|
||||
render: ({ active }) => <CssResourcePanel channel={channel} api={api} active={active} />,
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-events",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Add events to your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -9,9 +9,6 @@
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/events",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -27,8 +24,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"format-json": "^1.0.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
@ -37,5 +34,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/addon-google-analytics",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook addon for google analytics",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/google-analytics",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
@ -24,8 +21,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"global": "^4.3.2",
|
||||
"react-ga": "^2.5.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-graphql",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook addon to display the GraphiQL IDE",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/graphql",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -31,5 +28,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-info",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "A Storybook addon to show additional information for your stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/info",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -25,10 +22,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/client-logger": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"core-js": "2.5.7",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/client-logger": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"global": "^4.3.2",
|
||||
"marksy": "^6.1.0",
|
||||
"nested-object-assign": "^1.0.1",
|
||||
@ -42,5 +38,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -2880,6 +2880,7 @@ exports[`addon Info should render component description 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="story-root"
|
||||
style={Object {}}
|
||||
>
|
||||
<div>
|
||||
|
@ -1,6 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import 'core-js/fn/array/includes';
|
||||
|
||||
import { Table, Td, Th } from '@storybook/components';
|
||||
import PropVal from './PropVal';
|
||||
|
@ -117,7 +117,11 @@ class Story extends Component {
|
||||
const { stylesheet } = this.state;
|
||||
const { children } = this.props;
|
||||
|
||||
return <div style={stylesheet.infoStory}>{children}</div>;
|
||||
return (
|
||||
<div id="story-root" style={stylesheet.infoStory}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_renderInline() {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.9 MiB After Width: | Height: | Size: 831 KiB |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-jest",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "React storybook addon that show component jest report",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -12,9 +12,6 @@
|
||||
"unit-testing"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/jest",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -31,8 +28,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"upath": "^1.1.0",
|
||||
@ -40,5 +37,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -140,24 +140,22 @@ const Message = ({ msg }) => {
|
||||
.join('')
|
||||
.split(/\[22m/)
|
||||
.reduce((acc, item) => acc.concat(item), [])
|
||||
.map(
|
||||
(item, li) =>
|
||||
typeof item === 'string'
|
||||
? item
|
||||
.split(/\[32m(.*?)\[39m/)
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
.map((i, index) => (index % 2 ? <Positive key={`p_${li}_${i}`}>{i}</Positive> : i))
|
||||
: item
|
||||
.map((item, li) =>
|
||||
typeof item === 'string'
|
||||
? item
|
||||
.split(/\[32m(.*?)\[39m/)
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
.map((i, index) => (index % 2 ? <Positive key={`p_${li}_${i}`}>{i}</Positive> : i))
|
||||
: item
|
||||
)
|
||||
.reduce((acc, item) => acc.concat(item), [])
|
||||
.map(
|
||||
(item, li) =>
|
||||
typeof item === 'string'
|
||||
? item
|
||||
.split(/\[31m(.*?)\[39m/)
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
.map((i, index) => (index % 2 ? <Negative key={`n_${li}_${i}`}>{i}</Negative> : i))
|
||||
: item
|
||||
.map((item, li) =>
|
||||
typeof item === 'string'
|
||||
? item
|
||||
.split(/\[31m(.*?)\[39m/)
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
.map((i, index) => (index % 2 ? <Negative key={`n_${li}_${i}`}>{i}</Negative> : i))
|
||||
: item
|
||||
)
|
||||
.reduce((acc, item) => acc.concat(item), [])
|
||||
.reduce(createSubgroup, {
|
||||
|
@ -55,6 +55,39 @@ stories.add('as dynamic variables', () => {
|
||||
});
|
||||
```
|
||||
|
||||
### With Vue.js
|
||||
```js
|
||||
import { storiesOf } from '@storybook/vue';
|
||||
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
|
||||
|
||||
import MyButton from './Button.vue';
|
||||
|
||||
const stories = storiesOf('Storybook Knobs', module);
|
||||
|
||||
// Add the `withKnobs` decorator to add knobs support to your stories.
|
||||
// You can also configure `withKnobs` as a global decorator.
|
||||
stories.addDecorator(withKnobs);
|
||||
|
||||
// Knobs for Vue props
|
||||
// Knobs for Vue props
|
||||
stories.add('with a button', () => ({
|
||||
components: { MyButton },
|
||||
template:
|
||||
`<button disabled="${boolean('Disabled', false)}" >
|
||||
${text('Label', 'Hello Storybook')}
|
||||
</button>`
|
||||
}));
|
||||
|
||||
// Knobs as dynamic variables.
|
||||
stories.add('as dynamic variables', () => {
|
||||
const name = text('Name', 'Arunoda Susiripala');
|
||||
const age = number('Age', 89);
|
||||
|
||||
const content = `I am ${name} and I'm ${age} years old.`;
|
||||
return `<div>${content}</div>`;
|
||||
});
|
||||
```
|
||||
|
||||
### With Angular
|
||||
```js
|
||||
import { storiesOf } from '@storybook/angular';
|
||||
@ -344,8 +377,8 @@ stories.addDecorator(withKnobs)
|
||||
stories.add('story name', () => ..., {
|
||||
knobs: {
|
||||
timestamps: true, // Doesn't emit events while user is typing.
|
||||
escapeHTML: true // Escapes strings to be safe for inserting as innerHTML. This option is true by default in storybook for Vue, Angular, and Polymer, because those frameworks allow rendering plain HTML.
|
||||
// You can still set it to false, but it's strongly unrecommendend in cases when you host your storybook on some route of your main site or web app.
|
||||
escapeHTML: true // Escapes strings to be safe for inserting as innerHTML. This option is true by default. It's safe to set it to `false` with frameworks like React which do escaping on their side.
|
||||
// You can still set it to false, but it's strongly unrecommendend in cases when you host your storybook on some route of your main site or web app.
|
||||
}
|
||||
});
|
||||
```
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-knobs",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook Addon Prop Editor Component",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/knobs",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -25,9 +22,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"escape-html": "^1.0.3",
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
@ -40,5 +37,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -138,22 +138,24 @@ export default class Panel extends PureComponent {
|
||||
|
||||
let knobsArray = Object.keys(knobs).filter(key => knobs[key].used);
|
||||
|
||||
knobsArray.filter(key => knobs[key].groupId).forEach(key => {
|
||||
const knobKeyGroupId = knobs[key].groupId;
|
||||
groupIds.push(knobKeyGroupId);
|
||||
groups[knobKeyGroupId] = {
|
||||
render: ({ active: groupActive, selected }) => (
|
||||
<TabWrapper active={groupActive || selected === DEFAULT_GROUP_ID}>
|
||||
<PropForm
|
||||
knobs={knobsArray.filter(knob => knob.groupId === knobKeyGroupId)}
|
||||
onFieldChange={this.handleChange}
|
||||
onFieldClick={this.handleClick}
|
||||
/>
|
||||
</TabWrapper>
|
||||
),
|
||||
title: knobKeyGroupId,
|
||||
};
|
||||
});
|
||||
knobsArray
|
||||
.filter(key => knobs[key].groupId)
|
||||
.forEach(key => {
|
||||
const knobKeyGroupId = knobs[key].groupId;
|
||||
groupIds.push(knobKeyGroupId);
|
||||
groups[knobKeyGroupId] = {
|
||||
render: ({ active: groupActive, selected }) => (
|
||||
<TabWrapper active={groupActive || selected === DEFAULT_GROUP_ID}>
|
||||
<PropForm
|
||||
knobs={knobsArray.filter(knob => knob.groupId === knobKeyGroupId)}
|
||||
onFieldChange={this.handleChange}
|
||||
onFieldClick={this.handleClick}
|
||||
/>
|
||||
</TabWrapper>
|
||||
),
|
||||
title: knobKeyGroupId,
|
||||
};
|
||||
});
|
||||
|
||||
groups[DEFAULT_GROUP_ID] = {
|
||||
render: () => null,
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-links",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Story Links addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/links",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -24,13 +21,16 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-notes",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Write notes for your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -8,9 +8,6 @@
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/notes",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -26,11 +23,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"marked": "^0.5.1",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-backgrounds",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -9,9 +9,6 @@
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://storybook.js.org",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -26,11 +23,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-knobs",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Display storybook story knobs on your deviced.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -9,9 +9,6 @@
|
||||
"react-native",
|
||||
"storybook"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/storybooks/storybook.git"
|
||||
@ -23,7 +20,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"deep-equal": "^1.0.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-native-color-picker": "^0.4.0",
|
||||
@ -32,8 +29,11 @@
|
||||
"react-native-switch": "^1.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-knobs": "4.0.0",
|
||||
"@storybook/addon-knobs": "4.1.0-alpha.1",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -103,14 +103,16 @@ export default class Panel extends React.Component {
|
||||
|
||||
let knobsArray = Object.keys(knobs);
|
||||
|
||||
knobsArray.filter(key => knobs[key].groupId).forEach(key => {
|
||||
const knobKeyGroupId = knobs[key].groupId;
|
||||
groupIds.push(knobKeyGroupId);
|
||||
groups[knobKeyGroupId] = {
|
||||
render: () => <Text id={knobKeyGroupId}>{knobKeyGroupId}</Text>,
|
||||
title: knobKeyGroupId,
|
||||
};
|
||||
});
|
||||
knobsArray
|
||||
.filter(key => knobs[key].groupId)
|
||||
.forEach(key => {
|
||||
const knobKeyGroupId = knobs[key].groupId;
|
||||
groupIds.push(knobKeyGroupId);
|
||||
groups[knobKeyGroupId] = {
|
||||
render: () => <Text id={knobKeyGroupId}>{knobKeyGroupId}</Text>,
|
||||
title: knobKeyGroupId,
|
||||
};
|
||||
});
|
||||
|
||||
if (groupIds.length > 0) {
|
||||
groups[DEFAULT_GROUP_ID] = {
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-notes",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Write notes for your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"notes",
|
||||
"storybook"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/storybooks/storybook.git"
|
||||
@ -21,12 +18,15 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-native-simple-markdown": "^1.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,9 @@ Add this line to your `addons.js` file (create this file inside your storybook c
|
||||
import '@storybook/addon-options/register';
|
||||
```
|
||||
|
||||
Import and use the `withOptions` decorator in your config.js file.
|
||||
###Set options globally
|
||||
|
||||
Import and use the `withOptions` decorator in your `config.js` file.
|
||||
|
||||
```js
|
||||
import { addDecorator, configure } from '@storybook/react';
|
||||
@ -113,27 +115,29 @@ configure(() => require('./stories'), module);
|
||||
The options-addon accepts story parameters on the `options` key:
|
||||
|
||||
```js
|
||||
import { storiesOf } from '@storybook/marko';
|
||||
import { withKnobs, text, number } from '@storybook/addon-knobs';
|
||||
import Hello from '../components/hello/index.marko';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import MyComponent from './my-component';
|
||||
|
||||
storiesOf('Addons|Knobs/Hello', module)
|
||||
storiesOf('Addons|Custom options', module)
|
||||
// If you want to set the option for all stories in of this kind
|
||||
.addParameters({ options: { addonPanelInRight: true } })
|
||||
.addDecorator(withKnobs)
|
||||
.add(
|
||||
'Simple',
|
||||
() => {
|
||||
const name = text('Name', 'John Doe');
|
||||
const age = number('Age', 44);
|
||||
return Hello.renderSync({
|
||||
name,
|
||||
age,
|
||||
});
|
||||
},
|
||||
'Story for MyComponent',
|
||||
() => <MyComponent />,
|
||||
// If you want to set the options for a specific story
|
||||
{ options: { addonPanelInRight: false } }
|
||||
);
|
||||
```
|
||||
|
||||
_NOTE_ that you must attach `withOptions` as a decorator (at the top-level) for this to work.
|
||||
|
||||
## Typescript
|
||||
|
||||
To install type definitions: `npm install -D @types/storybook__addon-options`
|
||||
|
||||
Make sure you also have the type definitions installed for the following libs:
|
||||
|
||||
- node
|
||||
- react
|
||||
|
||||
You can install them using `npm install -D @types/node @types/react`, assuming you are using Typescript >2.0.
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-options",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Options addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/options",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -23,10 +20,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.8",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/storyshorts/storyshots-core",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -27,19 +24,23 @@
|
||||
"storybook": "start-storybook -p 6006"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"core-js": "^2.5.7",
|
||||
"glob": "^7.1.3",
|
||||
"global": "^4.3.2",
|
||||
"jest-specific-snapshot": "^1.0.0",
|
||||
"read-pkg-up": "^4.0.0"
|
||||
"read-pkg-up": "^4.0.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "4.0.12",
|
||||
"@storybook/addon-links": "4.0.12",
|
||||
"@storybook/addons": "4.0.0",
|
||||
"@storybook/react": "4.0.12",
|
||||
"@storybook/addon-actions": "4.1.0-alpha.12",
|
||||
"@storybook/addon-links": "4.1.0-alpha.12",
|
||||
"@storybook/addons": "4.1.0-alpha.1",
|
||||
"@storybook/react": "4.1.0-alpha.12",
|
||||
"enzyme-to-json": "^3.3.4",
|
||||
"react": "^16.6.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,9 @@ import hasDependency from '../hasDependency';
|
||||
import configure from '../configure';
|
||||
|
||||
function setupAngularJestPreset() {
|
||||
// Needed to prevent "Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten."
|
||||
require.requireActual('core-js/modules/es6.promise');
|
||||
|
||||
// Angular + Jest + Storyshots = Crazy Shit:
|
||||
// We need to require 'jest-preset-angular/setupJest' before any storybook code
|
||||
// is running inside jest - one of the things that `jest-preset-angular/setupJest` does is
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots-puppeteer",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Image snappshots addition to StoryShots base on puppeteer",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/storyshorts/storyshots-puppeteer",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -24,12 +21,16 @@
|
||||
"prepare": "node ../../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/node-logger": "4.0.12",
|
||||
"@storybook/node-logger": "4.1.0-alpha.12",
|
||||
"core-js": "^2.5.7",
|
||||
"jest-image-snapshot": "^2.6.0",
|
||||
"puppeteer": "^1.9.0"
|
||||
"puppeteer": "^1.9.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-storyshots": "^4.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-storysource",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Stories addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/storysource",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -24,16 +21,20 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"core-js": "^2.5.7",
|
||||
"estraverse": "^4.2.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"prettier": "^1.14.3",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-syntax-highlighter": "^10.0.0"
|
||||
"react-syntax-highlighter": "^10.0.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -216,11 +216,11 @@ Object {
|
||||
"Custom|ng-content@Default": Object {
|
||||
"endLoc": Object {
|
||||
"col": 2,
|
||||
"line": 15,
|
||||
"line": 17,
|
||||
},
|
||||
"startLoc": Object {
|
||||
"col": 43,
|
||||
"line": 10,
|
||||
"line": 12,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@storybook/addon-viewport",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook addon to change the viewport size to mobile",
|
||||
"keywords": [
|
||||
"addon",
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/viewport",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -24,14 +21,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/components": "4.0.12",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/components": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/angular",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/angular",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,20 +25,23 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/node-logger": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"@storybook/node-logger": "4.1.0-alpha.12",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"core-js": "^2.5.7",
|
||||
"fork-ts-checker-webpack-plugin": "^0.4.14",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"sass-loader": "^7.1.0",
|
||||
"ts-loader": "^5.2.2",
|
||||
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
||||
"webpack": "^4.23.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"zone.js": "^0.8.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular-devkit/core": "^0.6.1 || >=7.0.0",
|
||||
"@angular/common": ">=6.0.0",
|
||||
@ -53,7 +53,7 @@
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"zone.js": "^0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"zone.js": "^0.8.26"
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
@Component({
|
||||
selector: 'storybook-button-component',
|
||||
template: `
|
||||
<button (click)="onClick.emit($event);">{{ text }}</button>
|
||||
<button (click)="onClick.emit($event)">{{ text }}</button>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
|
@ -3,46 +3,45 @@ import { Component, Output, EventEmitter } from '@angular/core';
|
||||
@Component({
|
||||
selector: 'storybook-welcome-component',
|
||||
template: `
|
||||
<main>
|
||||
<h1>Welcome to storybook</h1>
|
||||
<p>This is a UI component dev environment for your app.</p>
|
||||
<p>
|
||||
We've added some basic stories inside the <span class="inline-code">src/stories</span> directory.
|
||||
<br/>
|
||||
A story is a single state of one or more UI components. You can have as many stories as
|
||||
you want.
|
||||
<br/>
|
||||
(Basically a story is like a visual test case.)
|
||||
</p>
|
||||
<p>
|
||||
See these sample <a (click)="showApp.emit($event);" role="button" tabIndex="0">stories</a> for a component called
|
||||
<span class="inline-code">Button</span> .
|
||||
</p>
|
||||
<p>
|
||||
Just like that, you can add your own components as stories.
|
||||
<br />
|
||||
You can also edit those components and see changes right away.
|
||||
<br />
|
||||
(Try editing the <span class="inline-code">Button</span> stories
|
||||
located at <span class="inline-code">src/stories/index.js</span>.)
|
||||
</p>
|
||||
<p>
|
||||
Usually we create stories with smaller UI components in the app.<br />
|
||||
Have a look at the <a
|
||||
href="https://storybook.js.org/basics/writing-stories"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Writing Stories
|
||||
</a> section in our documentation.
|
||||
</p>
|
||||
<p class="note">
|
||||
<b>NOTE:</b>
|
||||
<br />
|
||||
Have a look at the <span class="inline-code">.storybook/webpack.config.js</span>
|
||||
to add webpack loaders and plugins you are using in this project.
|
||||
</p>
|
||||
</main>
|
||||
<main>
|
||||
<h1>Welcome to storybook</h1>
|
||||
<p>This is a UI component dev environment for your app.</p>
|
||||
<p>
|
||||
We've added some basic stories inside the
|
||||
<span class="inline-code">src/stories</span> directory. <br />
|
||||
A story is a single state of one or more UI components. You can have as many stories as you
|
||||
want. <br />
|
||||
(Basically a story is like a visual test case.)
|
||||
</p>
|
||||
<p>
|
||||
See these sample
|
||||
<a (click)="showApp.emit($event)" role="button" tabIndex="0">stories</a> for a component
|
||||
called <span class="inline-code">Button</span> .
|
||||
</p>
|
||||
<p>
|
||||
Just like that, you can add your own components as stories. <br />
|
||||
You can also edit those components and see changes right away. <br />
|
||||
(Try editing the <span class="inline-code">Button</span> stories located at
|
||||
<span class="inline-code">src/stories/index.js</span>.)
|
||||
</p>
|
||||
<p>
|
||||
Usually we create stories with smaller UI components in the app.<br />
|
||||
Have a look at the
|
||||
<a
|
||||
href="https://storybook.js.org/basics/writing-stories"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Writing Stories
|
||||
</a>
|
||||
section in our documentation.
|
||||
</p>
|
||||
<p class="note">
|
||||
<b>NOTE:</b> <br />
|
||||
Have a look at the <span class="inline-code">.storybook/webpack.config.js</span> to add
|
||||
webpack loaders and plugins you are using in this project.
|
||||
</p>
|
||||
</main>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
|
8
app/angular/src/server/angular-cli_config.js
vendored
8
app/angular/src/server/angular-cli_config.js
vendored
@ -103,12 +103,10 @@ export function applyAngularCliWebpackConfig(baseConfig, cliWebpackConfigOptions
|
||||
const rulesExcludingStyles = filterOutStylingRules(baseConfig);
|
||||
|
||||
// cliStyleConfig.entry adds global style files to the webpack context
|
||||
const entry = {
|
||||
const entry = [
|
||||
...baseConfig.entry,
|
||||
iframe: []
|
||||
.concat(baseConfig.entry.iframe)
|
||||
.concat(Object.values(cliStyleConfig.entry).reduce((acc, item) => acc.concat(item), [])),
|
||||
};
|
||||
...Object.values(cliStyleConfig.entry).reduce((acc, item) => acc.concat(item), []),
|
||||
];
|
||||
|
||||
const module = {
|
||||
...baseConfig.module,
|
||||
|
@ -38,13 +38,13 @@ export function webpack(config, { configDir }) {
|
||||
},
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
extensions: [...config.resolve.extensions, '.ts', '.tsx'],
|
||||
extensions: ['.ts', '.tsx', ...config.resolve.extensions],
|
||||
},
|
||||
plugins: [
|
||||
...config.plugins,
|
||||
// See https://github.com/angular/angular/issues/11580#issuecomment-401127742
|
||||
new ContextReplacementPlugin(
|
||||
/@angular(\\|\/)core(\\|\/)fesm5/,
|
||||
/@angular(\\|\/)core(\\|\/)(fesm5|bundles)/,
|
||||
path.resolve(__dirname, '..')
|
||||
),
|
||||
createForkTsCheckerInstance(tsLoaderOptions),
|
||||
|
@ -1,11 +1,8 @@
|
||||
{
|
||||
"name": "@storybook/ember",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/ember",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -25,18 +22,22 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@ember/test-helpers": "^1.0.0",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"babel-plugin-ember-modules-api-polyfill": "^2.4.0",
|
||||
"ember-cli-htmlbars-inline-precompile": "^1.0.3",
|
||||
"ember-source": "^3.4.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/html",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/html",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -27,15 +24,19 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"html-loader": "^0.5.5",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,24 @@ import { stripIndents } from 'common-tags';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
export default function renderMain({ story, selectedKind, selectedStory, showMain, showError }) {
|
||||
export default function renderMain({
|
||||
story,
|
||||
selectedKind,
|
||||
selectedStory,
|
||||
showMain,
|
||||
showError,
|
||||
forceRender,
|
||||
}) {
|
||||
const component = story();
|
||||
|
||||
showMain();
|
||||
if (typeof component === 'string') {
|
||||
rootElement.innerHTML = component;
|
||||
} else if (component instanceof Node) {
|
||||
if (forceRender === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
rootElement.innerHTML = '';
|
||||
rootElement.appendChild(component);
|
||||
} else {
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/marko",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Marko: Develop Marko Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/marko",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,18 +25,22 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"marko-loader": "^1.3.3",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"marko": "^4.10.0",
|
||||
"marko-widgets": "^7.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/mithril",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Mithril: Develop Mithril Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/mithril",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,13 +25,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.0.0",
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@babel/plugin-transform-react-jsx": "^7.2.0",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mithril": "^1.1.6"
|
||||
@ -42,5 +40,8 @@
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"mithril": "^1.1.6"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/polymer",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Polymer: Develop Polymer components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/polymer",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -27,14 +24,14 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"@webcomponents/webcomponentsjs": "^1.2.0",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"webpack": "^4.23.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -45,5 +42,8 @@
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"lit-html": "0.10.0",
|
||||
"polymer-webpack-loader": "^2.0.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import '@webcomponents/webcomponentsjs/webcomponents-lite';
|
||||
import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter';
|
||||
import '@babel/polyfill';
|
||||
|
||||
import { window } from 'global';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/react-native",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "A better way to develop React Native Components for your app",
|
||||
"keywords": [
|
||||
"react",
|
||||
@ -8,9 +8,6 @@
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/react-native",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,12 +25,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "4.0.12",
|
||||
"@storybook/channel-websocket": "4.0.12",
|
||||
"@storybook/channels": "4.0.12",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core-events": "4.0.12",
|
||||
"@storybook/ui": "4.0.12",
|
||||
"@storybook/addons": "4.1.0-alpha.12",
|
||||
"@storybook/channel-websocket": "4.1.0-alpha.12",
|
||||
"@storybook/channels": "4.1.0-alpha.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"@storybook/core-events": "4.1.0-alpha.12",
|
||||
"@storybook/ui": "4.1.0-alpha.12",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-plugin-macros": "^2.4.2",
|
||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||
@ -43,7 +40,7 @@
|
||||
"babel-plugin-transform-regenerator": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-minify": "^0.5.0",
|
||||
"babel-preset-minify": "^0.5.0 || 0.6.0-alpha.5",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
@ -76,5 +73,8 @@
|
||||
"babel-runtime": ">=6.0.0",
|
||||
"react": "*",
|
||||
"react-native": ">=0.51.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -22,16 +22,16 @@ The next thing you need to do is make Storybook UI visible in your app.
|
||||
The easiest way to use Storybook is to simply replace your App with the Storybook UI, which is possible by replacing `App.js` with a single line of code:
|
||||
|
||||
```js
|
||||
export default from "./storybook";
|
||||
export default from './storybook';
|
||||
```
|
||||
|
||||
This will get you up and running quickly, but then you lose your app!
|
||||
There are multiple options here. for example, you can export conditionally:
|
||||
|
||||
```js
|
||||
import StorybookUI from "./storybook";
|
||||
import StorybookUI from './storybook';
|
||||
|
||||
import App from "./app";
|
||||
import App from './app';
|
||||
|
||||
module.exports = __DEV__ ? StorybookUI : App;
|
||||
```
|
||||
@ -121,6 +121,14 @@ You can pass these parameters to getStorybookUI call in your storybook entry poi
|
||||
-- should the ui be closed initialy.
|
||||
tabOpen: Number (0)
|
||||
-- which tab should be open. -1 Navigator, 0 Preview, 1 Addons
|
||||
initialSelection: Object (null)
|
||||
-- initialize storybook with a specific story. In case a valid object is passed, it will take precedence over `shouldPersistSelection. ex: `{ kind: 'Knobs', story: 'with knobs' }`
|
||||
shouldPersistSelection: Boolean (true)
|
||||
-- initialize storybook with the last selected story.
|
||||
shouldDisableKeyboardAvoidingView: Boolean (false)
|
||||
-- Disable KeyboardAvoidingView wrapping Storybook's view
|
||||
keyboardAvoidingViewVerticalOffset: Number (0)
|
||||
-- With shouldDisableKeyboardAvoidingView=true, this will set the keyboardverticaloffset (https://facebook.github.io/react-native/docs/keyboardavoidingview#keyboardverticaloffset) value for KeyboardAvoidingView wrapping Storybook's view
|
||||
}
|
||||
```
|
||||
|
||||
|
1
app/react-native/src/bin/storybook-start.js
vendored
1
app/react-native/src/bin/storybook-start.js
vendored
@ -5,6 +5,7 @@ import program from 'commander';
|
||||
import Server from '../server';
|
||||
|
||||
program
|
||||
.allowUnknownOption()
|
||||
.option('-h, --host <host>', 'host to listen on', 'localhost')
|
||||
.option('-p, --port <port>', 'port to listen on', 7007)
|
||||
.option('-s, --secured', 'whether server is running on https')
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, ScrollView, KeyboardAvoidingView, Platform } from 'react-native';
|
||||
import { View, ScrollView } from 'react-native';
|
||||
|
||||
import style from '../style';
|
||||
|
||||
@ -8,8 +8,6 @@ export default class Wrapper extends PureComponent {
|
||||
render() {
|
||||
const { panels, addonSelected } = this.props;
|
||||
|
||||
const keyboardVerticalOffset = Platform.OS === 'ios' ? 60 : 0;
|
||||
|
||||
const addonKeys = Object.keys(panels);
|
||||
|
||||
return addonKeys.map(id => {
|
||||
@ -17,13 +15,7 @@ export default class Wrapper extends PureComponent {
|
||||
|
||||
return (
|
||||
<View key={id} style={selected ? style.flex : style.invisible}>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'android' ? null : 'padding'}
|
||||
keyboardVerticalOffset={keyboardVerticalOffset}
|
||||
style={style.flex}
|
||||
>
|
||||
<ScrollView style={style.flex}>{panels[id].render({ active: selected })}</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
<ScrollView style={style.flex}>{panels[id].render({ active: selected })}</ScrollView>
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
@ -1,6 +1,13 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { SafeAreaView, Animated, TouchableOpacity } from 'react-native';
|
||||
import {
|
||||
Keyboard,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
SafeAreaView,
|
||||
Animated,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
import Events from '@storybook/core-events';
|
||||
|
||||
import StoryListView from '../StoryListView';
|
||||
@ -22,6 +29,7 @@ import {
|
||||
import style from './style';
|
||||
|
||||
const ANIMATION_DURATION = 300;
|
||||
const IS_IOS = Platform.OS === 'ios';
|
||||
|
||||
export default class OnDeviceUI extends PureComponent {
|
||||
constructor(props) {
|
||||
@ -32,8 +40,8 @@ export default class OnDeviceUI extends PureComponent {
|
||||
this.state = {
|
||||
tabOpen,
|
||||
slideBetweenAnimation: false,
|
||||
selection: props.initialStory || {},
|
||||
storyFn: props.initialStory ? props.initialStory.storyFn : null,
|
||||
selection: {},
|
||||
storyFn: null,
|
||||
previewWidth: 0,
|
||||
previewHeight: 0,
|
||||
};
|
||||
@ -42,8 +50,18 @@ export default class OnDeviceUI extends PureComponent {
|
||||
this.forceRender = this.forceUpdate.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { events } = this.props;
|
||||
async componentWillMount() {
|
||||
const { events, getInitialStory } = this.props;
|
||||
|
||||
if (getInitialStory) {
|
||||
const story = await getInitialStory();
|
||||
|
||||
this.setState({
|
||||
selection: story || {},
|
||||
storyFn: story ? story.storyFn : null,
|
||||
});
|
||||
}
|
||||
|
||||
events.on(Events.SELECT_STORY, this.handleStoryChange);
|
||||
events.on(Events.FORCE_RE_RENDER, this.forceRender);
|
||||
}
|
||||
@ -95,10 +113,22 @@ export default class OnDeviceUI extends PureComponent {
|
||||
// True if swiping between navigator and addons
|
||||
slideBetweenAnimation: tabOpen + newTabOpen === PREVIEW,
|
||||
});
|
||||
|
||||
// close the keyboard opened from a TextInput from story list or knobs
|
||||
if (newTabOpen === PREVIEW) {
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { stories, events, url, isUIHidden } = this.props;
|
||||
const {
|
||||
stories,
|
||||
events,
|
||||
url,
|
||||
isUIHidden,
|
||||
shouldDisableKeyboardAvoidingView,
|
||||
keyboardAvoidingViewVerticalOffset,
|
||||
} = this.props;
|
||||
const {
|
||||
tabOpen,
|
||||
slideBetweenAnimation,
|
||||
@ -121,40 +151,47 @@ export default class OnDeviceUI extends PureComponent {
|
||||
|
||||
return (
|
||||
<SafeAreaView style={style.flex}>
|
||||
<AbsolutePositionedKeyboardAwareView
|
||||
onLayout={this.onLayout}
|
||||
previewHeight={previewHeight}
|
||||
previewWidth={previewWidth}
|
||||
<KeyboardAvoidingView
|
||||
enabled={!shouldDisableKeyboardAvoidingView || tabOpen !== PREVIEW}
|
||||
behavior={IS_IOS ? 'padding' : null}
|
||||
keyboardVerticalOffset={keyboardAvoidingViewVerticalOffset}
|
||||
style={style.flex}
|
||||
>
|
||||
<Animated.View style={previewWrapperStyles}>
|
||||
<Animated.View style={previewStyles}>
|
||||
<TouchableOpacity
|
||||
accessible={false}
|
||||
style={style.flex}
|
||||
disabled={tabOpen === PREVIEW}
|
||||
onPress={this.handleOpenPreview}
|
||||
>
|
||||
<StoryView url={url} events={events} selection={selection} storyFn={storyFn} />
|
||||
</TouchableOpacity>
|
||||
<AbsolutePositionedKeyboardAwareView
|
||||
onLayout={this.onLayout}
|
||||
previewHeight={previewHeight}
|
||||
previewWidth={previewWidth}
|
||||
>
|
||||
<Animated.View style={previewWrapperStyles}>
|
||||
<Animated.View style={previewStyles}>
|
||||
<TouchableOpacity
|
||||
accessible={false}
|
||||
style={style.flex}
|
||||
disabled={tabOpen === PREVIEW}
|
||||
onPress={this.handleOpenPreview}
|
||||
>
|
||||
<StoryView url={url} events={events} selection={selection} storyFn={storyFn} />
|
||||
</TouchableOpacity>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
<Panel style={getNavigatorPanelPosition(this.animatedValue, previewWidth)}>
|
||||
<StoryListView
|
||||
stories={stories}
|
||||
events={events}
|
||||
selectedKind={selection.kind}
|
||||
selectedStory={selection.story}
|
||||
/>
|
||||
</Panel>
|
||||
<Panel style={getAddonPanelPosition(this.animatedValue, previewWidth)}>
|
||||
<Addons />
|
||||
</Panel>
|
||||
</AbsolutePositionedKeyboardAwareView>
|
||||
<Navigation
|
||||
tabOpen={tabOpen}
|
||||
onChangeTab={this.handleToggleTab}
|
||||
initialUiVisible={!isUIHidden}
|
||||
/>
|
||||
<Panel style={getNavigatorPanelPosition(this.animatedValue, previewWidth)}>
|
||||
<StoryListView
|
||||
stories={stories}
|
||||
events={events}
|
||||
selectedKind={selection.kind}
|
||||
selectedStory={selection.story}
|
||||
/>
|
||||
</Panel>
|
||||
<Panel style={getAddonPanelPosition(this.animatedValue, previewWidth)}>
|
||||
<Addons />
|
||||
</Panel>
|
||||
</AbsolutePositionedKeyboardAwareView>
|
||||
<Navigation
|
||||
tabOpen={tabOpen}
|
||||
onChangeTab={this.handleToggleTab}
|
||||
initialUiVisible={!isUIHidden}
|
||||
/>
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
@ -175,16 +212,16 @@ OnDeviceUI.propTypes = {
|
||||
url: PropTypes.string,
|
||||
tabOpen: PropTypes.number,
|
||||
isUIHidden: PropTypes.bool,
|
||||
initialStory: PropTypes.shape({
|
||||
story: PropTypes.string.isRequired,
|
||||
kind: PropTypes.string.isRequired,
|
||||
storyFn: PropTypes.func.isRequired,
|
||||
}),
|
||||
getInitialStory: PropTypes.func,
|
||||
shouldDisableKeyboardAvoidingView: PropTypes.bool,
|
||||
keyboardAvoidingViewVerticalOffset: PropTypes.number,
|
||||
};
|
||||
|
||||
OnDeviceUI.defaultProps = {
|
||||
url: '',
|
||||
tabOpen: 0,
|
||||
isUIHidden: false,
|
||||
initialStory: null,
|
||||
getInitialStory: null,
|
||||
shouldDisableKeyboardAvoidingView: false,
|
||||
keyboardAvoidingViewVerticalOffset: 0,
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { SectionList, View, Text, TouchableOpacity } from 'react-native';
|
||||
import { SectionList, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||
import Events from '@storybook/core-events';
|
||||
import style from './style';
|
||||
|
||||
@ -40,6 +40,7 @@ export default class StoryListView extends Component {
|
||||
|
||||
this.state = {
|
||||
data: [],
|
||||
originalData: [],
|
||||
};
|
||||
|
||||
this.storyAddedHandler = this.handleStoryAdded.bind(this);
|
||||
@ -71,12 +72,39 @@ export default class StoryListView extends Component {
|
||||
}),
|
||||
{}
|
||||
);
|
||||
this.setState({
|
||||
data,
|
||||
});
|
||||
|
||||
this.setState({ data, originalData: data });
|
||||
}
|
||||
};
|
||||
|
||||
handleChangeSearchText = text => {
|
||||
const query = text.trim();
|
||||
const { originalData: data } = this.state;
|
||||
|
||||
if (!query) {
|
||||
this.setState({ data });
|
||||
return;
|
||||
}
|
||||
|
||||
const checkValue = value => value.toLowerCase().includes(query.toLowerCase());
|
||||
const filteredData = data.reduce((acc, story) => {
|
||||
const hasTitle = checkValue(story.title);
|
||||
const hasKind = story.data.some(kind => checkValue(kind.name));
|
||||
|
||||
if (hasTitle || hasKind) {
|
||||
acc.push({
|
||||
...story,
|
||||
// in case the query matches component's title, all of its stories will be shown
|
||||
data: !hasTitle ? story.data.filter(kind => checkValue(kind.name)) : story.data,
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this.setState({ data: filteredData });
|
||||
};
|
||||
|
||||
changeStory(kind, story) {
|
||||
const { events } = this.props;
|
||||
|
||||
@ -88,24 +116,34 @@ export default class StoryListView extends Component {
|
||||
const { data } = this.state;
|
||||
|
||||
return (
|
||||
<SectionList
|
||||
testID="Storybook.ListView"
|
||||
style={[style.list]}
|
||||
renderItem={({ item }) => (
|
||||
<ListItem
|
||||
title={item.name}
|
||||
kind={item.kind}
|
||||
selected={item.kind === selectedKind && item.name === selectedStory}
|
||||
onPress={() => this.changeStory(item.kind, item.name)}
|
||||
/>
|
||||
)}
|
||||
renderSectionHeader={({ section: { title } }) => (
|
||||
<SectionHeader title={title} selected={title === selectedKind} />
|
||||
)}
|
||||
keyExtractor={(item, index) => item + index}
|
||||
sections={data}
|
||||
stickySectionHeadersEnabled={false}
|
||||
/>
|
||||
<View style={style.flex}>
|
||||
<TextInput
|
||||
clearButtonMode="while-editing"
|
||||
disableFullscreenUI
|
||||
onChangeText={this.handleChangeSearchText}
|
||||
placeholder="Filter"
|
||||
returnKeyType="search"
|
||||
style={style.searchBar}
|
||||
/>
|
||||
<SectionList
|
||||
testID="Storybook.ListView"
|
||||
style={style.flex}
|
||||
renderItem={({ item }) => (
|
||||
<ListItem
|
||||
title={item.name}
|
||||
kind={item.kind}
|
||||
selected={item.kind === selectedKind && item.name === selectedStory}
|
||||
onPress={() => this.changeStory(item.kind, item.name)}
|
||||
/>
|
||||
)}
|
||||
renderSectionHeader={({ section: { title } }) => (
|
||||
<SectionHeader title={title} selected={title === selectedKind} />
|
||||
)}
|
||||
keyExtractor={(item, index) => item + index}
|
||||
sections={data}
|
||||
stickySectionHeadersEnabled={false}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,17 @@
|
||||
export default {
|
||||
list: {
|
||||
searchBar: {
|
||||
backgroundColor: '#eee',
|
||||
borderRadius: 5,
|
||||
fontSize: 16,
|
||||
marginHorizontal: 5,
|
||||
marginVertical: 5,
|
||||
padding: 5,
|
||||
},
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
paddingVertical: 5,
|
||||
},
|
||||
headerText: {
|
||||
fontSize: 20,
|
||||
|
73
app/react-native/src/preview/index.js
vendored
73
app/react-native/src/preview/index.js
vendored
@ -1,7 +1,7 @@
|
||||
/* eslint-disable react/no-this-in-sfc, no-underscore-dangle */
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
|
||||
import React from 'react';
|
||||
import { NativeModules } from 'react-native';
|
||||
import { AsyncStorage, NativeModules } from 'react-native';
|
||||
import parse from 'url-parse';
|
||||
import addons from '@storybook/addons';
|
||||
|
||||
@ -12,6 +12,8 @@ import { StoryStore, ClientApi } from '@storybook/core/client';
|
||||
import OnDeviceUI from './components/OnDeviceUI';
|
||||
import StoryView from './components/StoryView';
|
||||
|
||||
const STORAGE_KEY = 'lastOpenedStory';
|
||||
|
||||
export default class Preview {
|
||||
constructor() {
|
||||
this._addons = {};
|
||||
@ -44,7 +46,7 @@ export default class Preview {
|
||||
let channel = null;
|
||||
|
||||
const onDeviceUI = params.onDeviceUI !== false;
|
||||
|
||||
const { initialSelection, shouldPersistSelection } = params;
|
||||
// should the initial story be sent to storybookUI
|
||||
// set to true if using disableWebsockets or if connection to WebsocketServer fails.
|
||||
let setInitialStory = false;
|
||||
@ -75,7 +77,9 @@ export default class Preview {
|
||||
url,
|
||||
async: onDeviceUI,
|
||||
onError: () => {
|
||||
this._setInitialStory();
|
||||
// We are both emitting event and telling the component to get initial story. It may happen that component is created before the error or vise versa.
|
||||
// This way we handle both cases
|
||||
this._setInitialStory(initialSelection, shouldPersistSelection);
|
||||
|
||||
setInitialStory = true;
|
||||
},
|
||||
@ -88,7 +92,7 @@ export default class Preview {
|
||||
}
|
||||
|
||||
channel.on(Events.GET_STORIES, () => this._sendSetStories());
|
||||
channel.on(Events.SET_CURRENT_STORY, d => this._selectStory(d));
|
||||
channel.on(Events.SET_CURRENT_STORY, d => this._selectStoryEvent(d));
|
||||
this._sendSetStories();
|
||||
|
||||
// If the app is started with server running, set the story as the one selected in the browser
|
||||
@ -112,7 +116,13 @@ export default class Preview {
|
||||
url={webUrl}
|
||||
isUIOpen={params.isUIOpen}
|
||||
tabOpen={params.tabOpen}
|
||||
initialStory={setInitialStory ? preview._getInitialStory() : null}
|
||||
getInitialStory={
|
||||
setInitialStory
|
||||
? preview._getInitialStory(initialSelection, shouldPersistSelection)
|
||||
: null
|
||||
}
|
||||
shouldDisableKeyboardAvoidingView={params.shouldDisableKeyboardAvoidingView}
|
||||
keyboardAvoidingViewVerticalOffset={params.keyboardAvoidingViewVerticalOffset}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -133,15 +143,33 @@ export default class Preview {
|
||||
channel.emit(Events.GET_CURRENT_STORY);
|
||||
}
|
||||
|
||||
_setInitialStory = () => {
|
||||
const story = this._getInitialStory();
|
||||
_setInitialStory = async (initialSelection, shouldPersistSelection = true) => {
|
||||
const story = await this._getInitialStory(initialSelection, shouldPersistSelection)();
|
||||
|
||||
if (story) {
|
||||
this._selectStory(story);
|
||||
}
|
||||
};
|
||||
|
||||
_getInitialStory = () => {
|
||||
_getInitialStory = (initialSelection, shouldPersistSelection = true) => async () => {
|
||||
let story = null;
|
||||
if (initialSelection && this._checkStory(initialSelection)) {
|
||||
story = initialSelection;
|
||||
} else if (shouldPersistSelection) {
|
||||
const value = await AsyncStorage.getItem(STORAGE_KEY);
|
||||
const previousStory = JSON.parse(value);
|
||||
|
||||
if (this._checkStory(previousStory)) {
|
||||
story = previousStory;
|
||||
}
|
||||
}
|
||||
|
||||
if (story) {
|
||||
return this._getStory(story);
|
||||
}
|
||||
|
||||
const dump = this._stories.dumpStoryBook();
|
||||
|
||||
const nonEmptyKind = dump.find(kind => kind.stories.length > 0);
|
||||
if (nonEmptyKind) {
|
||||
return this._getStory({ kind: nonEmptyKind.kind, story: nonEmptyKind.stories[0] });
|
||||
@ -156,8 +184,31 @@ export default class Preview {
|
||||
return { ...selection, storyFn };
|
||||
}
|
||||
|
||||
_selectStory(selection) {
|
||||
_selectStoryEvent(selection) {
|
||||
AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(selection));
|
||||
|
||||
const story = this._getStory(selection);
|
||||
this._selectStory(story);
|
||||
}
|
||||
|
||||
_selectStory(story) {
|
||||
const channel = addons.getChannel();
|
||||
channel.emit(Events.SELECT_STORY, this._getStory(selection));
|
||||
channel.emit(Events.SELECT_STORY, story);
|
||||
}
|
||||
|
||||
_checkStory(selection) {
|
||||
if (!selection || typeof selection !== 'object' || !selection.kind || !selection.story) {
|
||||
console.warn('invalid storybook selection'); // eslint-disable-line no-console
|
||||
return null;
|
||||
}
|
||||
|
||||
const story = this._getStory(selection);
|
||||
|
||||
if (story.storyFn === null) {
|
||||
console.warn('invalid storybook selection'); // eslint-disable-line no-console
|
||||
return null;
|
||||
}
|
||||
|
||||
return story;
|
||||
}
|
||||
}
|
||||
|
1
app/react-native/src/server/config/babel.js
vendored
1
app/react-native/src/server/config/babel.js
vendored
@ -6,6 +6,7 @@ module.exports = {
|
||||
require.resolve('babel-preset-env'),
|
||||
{
|
||||
modules: process.env.NODE_ENV === 'test' ? 'commonjs' : false,
|
||||
shippedProposals: true,
|
||||
},
|
||||
],
|
||||
require.resolve('babel-preset-react'),
|
||||
|
@ -3,7 +3,7 @@ import webpack from 'webpack';
|
||||
import Dotenv from 'dotenv-webpack';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
|
||||
import { getManagerHeadHtml } from '@storybook/core/dist/server/utils';
|
||||
import { getManagerHeadHtml } from '@storybook/core/dist/server/utils/template';
|
||||
import { version } from '../../../package.json';
|
||||
import { includePaths, excludePaths, loadEnv } from './utils';
|
||||
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/react",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/react",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,25 +25,33 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-constant-elements": "^7.2.0",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@emotion/styled": "^0.10.6",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/node-logger": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"@storybook/node-logger": "4.1.0-alpha.12",
|
||||
"@svgr/webpack": "^4.0.3",
|
||||
"babel-plugin-named-asset-import": "^0.2.3",
|
||||
"babel-plugin-react-docgen": "^2.0.0",
|
||||
"babel-preset-react-app": "^6.1.0",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"lodash": "^4.17.11",
|
||||
"mini-css-extract-plugin": "^0.4.4",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dev-utils": "^6.1.0",
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"semver": "^5.6.0",
|
||||
"webpack": "^4.23.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"react": ">=15.0.0",
|
||||
"react-dom": ">=15.0.0"
|
||||
"babel-loader": "^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { window } from 'global';
|
||||
|
||||
if (window.parent !== window) {
|
||||
if (window && window.parent !== window) {
|
||||
try {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
@ -8,4 +8,7 @@ if (window.parent !== window) {
|
||||
// The above line can throw if we do not have access to the parent frame -- i.e. cross origin
|
||||
}
|
||||
}
|
||||
window.STORYBOOK_ENV = 'react';
|
||||
|
||||
if (window) {
|
||||
window.STORYBOOK_ENV = 'react';
|
||||
}
|
||||
|
24
app/react/src/client/preview/index.test.js
Normal file
24
app/react/src/client/preview/index.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
/* eslint-disable global-require */
|
||||
describe('preview', () => {
|
||||
afterEach(() => {
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
const isFunction = value => typeof value === 'function';
|
||||
|
||||
it('should return the client api in a browser environment', () => {
|
||||
const api = require('.');
|
||||
expect(Object.keys(api).length).toBeGreaterThan(0);
|
||||
expect(Object.values(api).every(isFunction)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return the client api in a node.js environment', () => {
|
||||
jest.mock('global', () => ({
|
||||
document: undefined,
|
||||
window: undefined,
|
||||
}));
|
||||
const api = require('.');
|
||||
expect(Object.keys(api).length).toBeGreaterThan(0);
|
||||
expect(Object.values(api).every(isFunction)).toEqual(true);
|
||||
});
|
||||
});
|
@ -4,7 +4,7 @@ import ReactDOM from 'react-dom';
|
||||
import { stripIndents } from 'common-tags';
|
||||
import isReactRenderable from './element_check';
|
||||
|
||||
const rootEl = document.getElementById('root');
|
||||
const rootEl = document ? document.getElementById('root') : null;
|
||||
|
||||
function render(node, el) {
|
||||
ReactDOM.render(
|
||||
|
151
app/react/src/server/__mocks__/mockRules.js
Normal file
151
app/react/src/server/__mocks__/mockRules.js
Normal file
@ -0,0 +1,151 @@
|
||||
export default [
|
||||
{ parser: { requireEnsure: false } },
|
||||
{
|
||||
test: /\.(js|mjs|jsx)$/,
|
||||
enforce: 'pre',
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: '/mock_folder/node_modules/react-dev-utils/eslintFormatter.js',
|
||||
eslintPath: '/mock_folder/node_modules/eslint/lib/api.js',
|
||||
baseConfig: {
|
||||
extends: ['/mock_folder/node_modules/eslint-config-react-app/index.js'],
|
||||
settings: { react: { version: '999.999.999' } },
|
||||
},
|
||||
ignore: false,
|
||||
useEslintrc: false,
|
||||
},
|
||||
loader: '/mock_folder/node_modules/eslint-loader/index.js',
|
||||
},
|
||||
],
|
||||
include: '/mock_folder/src',
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
||||
loader: '/mock_folder/node_modules/url-loader/dist/cjs.js',
|
||||
options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' },
|
||||
},
|
||||
{
|
||||
test: /\.(js|mjs|jsx|ts|tsx)$/,
|
||||
include: '/mock_folder/src',
|
||||
loader: '/mock_folder/node_modules/babel-loader/lib/index.js',
|
||||
options: {
|
||||
customize: '/mock_folder/node_modules/babel-preset-react-app/webpack-overrides.js',
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
presets: ['/mock_folder/node_modules/babel-preset-react-app/index.js'],
|
||||
cacheIdentifier:
|
||||
'development:babel-plugin-named-asset-import@0.2.3:babel-preset-react-app@6.1.0:react-dev-utils@6.1.1:react-scripts@',
|
||||
plugins: [
|
||||
[
|
||||
'/mock_folder/node_modules/babel-plugin-named-asset-import/index.js',
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
cacheCompression: false,
|
||||
compact: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(js|mjs)$/,
|
||||
exclude: {},
|
||||
loader: '/mock_folder/node_modules/babel-loader/lib/index.js',
|
||||
options: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
compact: false,
|
||||
presets: [
|
||||
['/mock_folder/node_modules/babel-preset-react-app/dependencies.js', { helpers: true }],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
cacheCompression: false,
|
||||
cacheIdentifier:
|
||||
'development:babel-plugin-named-asset-import@0.2.3:babel-preset-react-app@6.1.0:react-dev-utils@6.1.1:react-scripts@',
|
||||
sourceMaps: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: {},
|
||||
use: [
|
||||
'/mock_folder/node_modules/bmr-react-scripts/node_modules/style-loader/index.js',
|
||||
{
|
||||
loader: '/mock_folder/node_modules/bmr-react-scripts/node_modules/css-loader/index.js',
|
||||
options: { importLoaders: 1, sourceMap: false },
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/postcss-loader/src/index.js',
|
||||
options: { ident: 'postcss', sourceMap: false },
|
||||
},
|
||||
],
|
||||
sideEffects: true,
|
||||
},
|
||||
{
|
||||
test: /\.module\.css$/,
|
||||
use: [
|
||||
'/mock_folder/node_modules/bmr-react-scripts/node_modules/style-loader/index.js',
|
||||
{
|
||||
loader: '/mock_folder/node_modules/bmr-react-scripts/node_modules/css-loader/index.js',
|
||||
options: { importLoaders: 1, sourceMap: false, modules: true },
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/postcss-loader/src/index.js',
|
||||
options: { ident: 'postcss', sourceMap: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(scss|sass)$/,
|
||||
exclude: {},
|
||||
use: [
|
||||
'/mock_folder/node_modules/bmr-react-scripts/node_modules/style-loader/index.js',
|
||||
{
|
||||
loader: '/mock_folder/node_modules/bmr-react-scripts/node_modules/css-loader/index.js',
|
||||
options: { importLoaders: 2, sourceMap: false },
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/postcss-loader/src/index.js',
|
||||
options: { ident: 'postcss', sourceMap: false },
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/sass-loader/lib/loader.js',
|
||||
options: { sourceMap: false },
|
||||
},
|
||||
],
|
||||
sideEffects: true,
|
||||
},
|
||||
{
|
||||
test: /\.module\.(scss|sass)$/,
|
||||
use: [
|
||||
'/mock_folder/node_modules/bmr-react-scripts/node_modules/style-loader/index.js',
|
||||
{
|
||||
loader: '/mock_folder/node_modules/bmr-react-scripts/node_modules/css-loader/index.js',
|
||||
options: { importLoaders: 2, sourceMap: false, modules: true },
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/postcss-loader/src/index.js',
|
||||
options: { ident: 'postcss', sourceMap: false },
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/sass-loader/lib/loader.js',
|
||||
options: { sourceMap: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
loader: '/mock_folder/node_modules/file-loader/dist/cjs.js',
|
||||
exclude: [{}, {}, {}],
|
||||
options: { name: 'static/media/[name].[hash:8].[ext]' },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
141
app/react/src/server/cra-config.js
Normal file
141
app/react/src/server/cra-config.js
Normal file
@ -0,0 +1,141 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import { normalizeCondition } from 'webpack/lib/RuleSet';
|
||||
|
||||
const cssExtensions = ['.css', '.scss', '.sass'];
|
||||
const cssModuleExtensions = ['.module.css', '.module.scss', '.module.sass'];
|
||||
const typeScriptExtensions = ['.ts', '.tsx'];
|
||||
|
||||
let reactScriptsPath;
|
||||
|
||||
export function getReactScriptsPath({ noCache } = {}) {
|
||||
if (reactScriptsPath && !noCache) return reactScriptsPath;
|
||||
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const reactScriptsScriptPath = fs.realpathSync(
|
||||
path.join(appDirectory, '/node_modules/.bin/react-scripts')
|
||||
);
|
||||
|
||||
reactScriptsPath = path.join(reactScriptsScriptPath, '../..');
|
||||
const scriptsPkgJson = path.join(reactScriptsPath, 'package.json');
|
||||
|
||||
if (!fs.existsSync(scriptsPkgJson)) {
|
||||
reactScriptsPath = 'react-scripts';
|
||||
}
|
||||
|
||||
return reactScriptsPath;
|
||||
}
|
||||
|
||||
export function isReactScriptsInstalled(requiredVersion = '2.0.0') {
|
||||
try {
|
||||
// eslint-disable-next-line import/no-dynamic-require,global-require
|
||||
const reactScriptsJson = require(path.join(getReactScriptsPath(), 'package.json'));
|
||||
return !semver.lt(reactScriptsJson.version, requiredVersion);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const getRules = extensions => rules =>
|
||||
rules.reduce((craRules, rule) => {
|
||||
// If at least one extension satisfies the rule test, the rule is one
|
||||
// we want to extract
|
||||
if (rule.test && extensions.some(normalizeCondition(rule.test))) {
|
||||
// If the base test is for extensions, return early
|
||||
return craRules.concat(rule);
|
||||
}
|
||||
|
||||
// Get any rules contained in rule.oneOf
|
||||
if (!rule.test && rule.oneOf) {
|
||||
craRules.push(...getRules(extensions)(rule.oneOf));
|
||||
}
|
||||
|
||||
// Get any rules contained in rule.rules
|
||||
if (!rule.test && rule.rules) {
|
||||
craRules.push(...getRules(extensions)(rule.rules));
|
||||
}
|
||||
|
||||
return craRules;
|
||||
}, []);
|
||||
|
||||
const getStyleRules = getRules(cssExtensions.concat(cssModuleExtensions));
|
||||
|
||||
export const getTypeScriptRules = (webpackConfigRules, configDir) => {
|
||||
const rules = getRules(typeScriptExtensions)(webpackConfigRules);
|
||||
// We know CRA only has one rule targetting TS for now, which is the first rule.
|
||||
const babelRule = rules[0];
|
||||
// Resolves an issue where this config is parsed twice (#4903).
|
||||
if (typeof babelRule.include !== 'string') return rules;
|
||||
// Adds support for using TypeScript in the `.storybook` (or config) folder.
|
||||
return [
|
||||
{
|
||||
...babelRule,
|
||||
include: [babelRule.include, path.resolve(configDir)],
|
||||
},
|
||||
...rules.slice(1),
|
||||
];
|
||||
};
|
||||
|
||||
export function getCraWebpackConfig(mode) {
|
||||
const pathToReactScripts = getReactScriptsPath();
|
||||
|
||||
const craWebpackConfig =
|
||||
mode === 'production' ? 'config/webpack.config.prod' : 'config/webpack.config.dev';
|
||||
|
||||
let pathToWebpackConfig = require.resolve(path.join(pathToReactScripts, craWebpackConfig));
|
||||
|
||||
if (!fs.existsSync(pathToWebpackConfig)) {
|
||||
pathToWebpackConfig = path.join(pathToReactScripts, 'config/webpack.config');
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-dynamic-require,global-require
|
||||
const webpackConfig = require(pathToWebpackConfig);
|
||||
|
||||
if (typeof webpackConfig === 'function') {
|
||||
return webpackConfig(mode);
|
||||
}
|
||||
|
||||
return webpackConfig;
|
||||
}
|
||||
|
||||
export function applyCRAWebpackConfig(baseConfig, configDir) {
|
||||
// Check if the user can use TypeScript (react-scripts version 2.1+).
|
||||
const hasTsSupport = isReactScriptsInstalled('2.1.0');
|
||||
|
||||
const tsExtensions = hasTsSupport ? typeScriptExtensions : [];
|
||||
const extensions = [...cssExtensions, ...tsExtensions];
|
||||
|
||||
// Remove any rules from baseConfig that test true for any one of the extensions
|
||||
const filteredBaseRules = baseConfig.module.rules.filter(
|
||||
rule => !rule.test || !extensions.some(normalizeCondition(rule.test))
|
||||
);
|
||||
|
||||
// Load create-react-app config
|
||||
const craWebpackConfig = getCraWebpackConfig(baseConfig.mode);
|
||||
|
||||
const craStyleRules = getStyleRules(craWebpackConfig.module.rules);
|
||||
const craTypeScriptRules = hasTsSupport
|
||||
? getTypeScriptRules(craWebpackConfig.module.rules, configDir)
|
||||
: [];
|
||||
|
||||
// Add css minification for production
|
||||
const plugins = [...baseConfig.plugins];
|
||||
if (baseConfig.mode === 'production') {
|
||||
plugins.push(new MiniCssExtractPlugin());
|
||||
}
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
module: {
|
||||
...baseConfig.module,
|
||||
rules: [...filteredBaseRules, ...craStyleRules, ...craTypeScriptRules],
|
||||
},
|
||||
plugins,
|
||||
resolve: {
|
||||
...baseConfig.resolve,
|
||||
extensions: [...baseConfig.resolve.extensions, ...tsExtensions],
|
||||
},
|
||||
};
|
||||
}
|
60
app/react/src/server/cra-config.test.js
Normal file
60
app/react/src/server/cra-config.test.js
Normal file
@ -0,0 +1,60 @@
|
||||
import fs from 'fs';
|
||||
import { getReactScriptsPath, getTypeScriptRules } from './cra-config';
|
||||
import mockRules from './__mocks__/mockRules';
|
||||
|
||||
jest.mock('fs', () => ({
|
||||
realpathSync: jest.fn(),
|
||||
existsSync: () => true,
|
||||
}));
|
||||
jest.mock('mini-css-extract-plugin', () => {});
|
||||
|
||||
const SCRIPT_PATH = '.bin/react-scripts';
|
||||
|
||||
describe('cra-config', () => {
|
||||
beforeEach(() => {
|
||||
fs.realpathSync.mockImplementationOnce(() => '/test-project');
|
||||
});
|
||||
|
||||
describe('when used with the default react-scripts package', () => {
|
||||
beforeEach(() => {
|
||||
fs.realpathSync.mockImplementationOnce(path =>
|
||||
path.replace(SCRIPT_PATH, `react-scripts/${SCRIPT_PATH}`)
|
||||
);
|
||||
});
|
||||
|
||||
it('should locate the react-scripts package', () => {
|
||||
expect(getReactScriptsPath({ noCache: true })).toEqual(
|
||||
'/test-project/node_modules/react-scripts'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when used with a custom react-scripts package', () => {
|
||||
beforeEach(() => {
|
||||
fs.realpathSync.mockImplementationOnce(path =>
|
||||
path.replace(SCRIPT_PATH, `custom-react-scripts/${SCRIPT_PATH}`)
|
||||
);
|
||||
});
|
||||
|
||||
it('should locate the react-scripts package', () => {
|
||||
expect(getReactScriptsPath({ noCache: true })).toEqual(
|
||||
'/test-project/node_modules/custom-react-scripts'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when used with TypeScript', () => {
|
||||
const rules = getTypeScriptRules(mockRules, './.storybook');
|
||||
|
||||
it('should return the correct config', () => {
|
||||
// Normalise the return, as we know our new rules object will be an array, whereas a string is expected.
|
||||
const rulesObject = { ...rules[0], include: rules[0].include[0] };
|
||||
expect(rulesObject).toMatchObject(mockRules[2].oneOf[1]);
|
||||
});
|
||||
|
||||
// Allows using TypeScript in the `.storybook` (or config) folder.
|
||||
it('should add the Storybook config directory to `include`', () => {
|
||||
expect(rules[0].include.findIndex(string => string.includes('.storybook'))).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,91 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
|
||||
import { normalizeCondition } from 'webpack/lib/RuleSet';
|
||||
|
||||
let reactScriptsPath;
|
||||
function getReactScriptsPath() {
|
||||
if (reactScriptsPath) return reactScriptsPath;
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const reactScriptsScriptPath = fs.realpathSync(
|
||||
path.join(appDirectory, '/node_modules/.bin/react-scripts')
|
||||
);
|
||||
reactScriptsPath = path.join(reactScriptsScriptPath, '../..');
|
||||
return reactScriptsPath;
|
||||
}
|
||||
|
||||
export function isReactScriptsInstalled() {
|
||||
try {
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
const reactScriptsJson = require(path.join(getReactScriptsPath(), 'package.json'));
|
||||
if (semver.lt(reactScriptsJson.version, '2.0.0')) return false;
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getStyleRules(rules) {
|
||||
// Extensions of style rules we're interested in
|
||||
const extensions = ['.css', '.scss', '.sass', '.module.css', '.module.scss', '.module.sass'];
|
||||
|
||||
return rules.reduce((styleRules, rule) => {
|
||||
// If at least one style extension satisfies the rule test, the rule is one
|
||||
// we want to extract
|
||||
if (rule.test && extensions.some(normalizeCondition(rule.test))) {
|
||||
// If the base test is for styles, return early
|
||||
return styleRules.concat(rule);
|
||||
}
|
||||
|
||||
// Get any style rules contained in rule.oneOf
|
||||
if (!rule.test && rule.oneOf) {
|
||||
styleRules.push(...getStyleRules(rule.oneOf));
|
||||
}
|
||||
|
||||
// Get any style rules contained in rule.rules
|
||||
if (!rule.test && rule.rules) {
|
||||
styleRules.push(...getStyleRules(rule.rules));
|
||||
}
|
||||
|
||||
return styleRules;
|
||||
}, []);
|
||||
}
|
||||
|
||||
export function getCraWebpackConfig(mode) {
|
||||
if (mode === 'production') {
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
return require(path.join(getReactScriptsPath(), 'config/webpack.config.prod'));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
return require(path.join(getReactScriptsPath(), 'config/webpack.config.dev'));
|
||||
}
|
||||
|
||||
export function applyCRAWebpackConfig(baseConfig) {
|
||||
// Remove any rules from baseConfig that test true for any one of the extensions
|
||||
const baseRulesExcludingStyles = baseConfig.module.rules.filter(
|
||||
rule => !rule.test || !['.css', '.scss', '.sass'].some(normalizeCondition(rule.test))
|
||||
);
|
||||
|
||||
// Load create-react-app config
|
||||
const craWebpackConfig = getCraWebpackConfig(baseConfig.mode);
|
||||
|
||||
const craStyleRules = getStyleRules(craWebpackConfig.module.rules);
|
||||
|
||||
// Add css minification for production
|
||||
const plugins = [...baseConfig.plugins];
|
||||
if (baseConfig.mode === 'production') {
|
||||
plugins.push(new MiniCssExtractPlugin());
|
||||
}
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
module: {
|
||||
...baseConfig.module,
|
||||
rules: [...baseRulesExcludingStyles, ...craStyleRules],
|
||||
},
|
||||
plugins,
|
||||
};
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import { applyCRAWebpackConfig, isReactScriptsInstalled } from './cra_config';
|
||||
|
||||
export function webpackFinal(config) {
|
||||
if (!isReactScriptsInstalled()) {
|
||||
logger.info('=> Using base config because react-scripts is not installed.');
|
||||
return config;
|
||||
}
|
||||
|
||||
logger.info('=> Loading create-react-app config.');
|
||||
|
||||
return applyCRAWebpackConfig(config);
|
||||
}
|
36
app/react/src/server/framework-preset-cra.js
Normal file
36
app/react/src/server/framework-preset-cra.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import { applyCRAWebpackConfig, isReactScriptsInstalled } from './cra-config';
|
||||
|
||||
export function webpackFinal(config, { configDir }) {
|
||||
if (!isReactScriptsInstalled()) {
|
||||
logger.info('=> Using base config because react-scripts is not installed.');
|
||||
return config;
|
||||
}
|
||||
|
||||
logger.info('=> Loading create-react-app config.');
|
||||
|
||||
return applyCRAWebpackConfig(config, configDir);
|
||||
}
|
||||
|
||||
export function babelDefault(config) {
|
||||
if (!isReactScriptsInstalled()) {
|
||||
return config;
|
||||
}
|
||||
|
||||
return {
|
||||
...config,
|
||||
presets: [require.resolve('babel-preset-react-app')],
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-named-asset-import'),
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
@ -5,7 +5,7 @@ export default {
|
||||
defaultConfigName: 'create-react-app',
|
||||
frameworkPresets: [
|
||||
require.resolve('./framework-preset-react.js'),
|
||||
require.resolve('./framework-preset-cra.js'),
|
||||
require.resolve('./framework-preset-react-docgen.js'),
|
||||
require.resolve('./framework-preset-cra-styles.js'),
|
||||
],
|
||||
};
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/riot",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for riot.js: View riot snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/riot",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -27,21 +24,20 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.1.0",
|
||||
"@babel/plugin-transform-runtime": "^7.1.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
|
||||
"@babel/preset-env": "^7.2.0",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/runtime": "^7.0.0"
|
||||
"@babel/preset-react": "^7.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
@ -49,5 +45,8 @@
|
||||
"riot-compiler": "^3.5.1 || ^4.0.0",
|
||||
"riot-hot-reload": "^1.0.0",
|
||||
"riot-tag-loader": "^2.0.0 || ^3.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -15,5 +15,12 @@ export function webpack(config) {
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...config.resolve.alias,
|
||||
'riot-compiler': 'riot-compiler/dist/es6.compiler',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/svelte",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/svelte",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,19 +25,24 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte": "^2.13.5",
|
||||
"svelte": "^2.15.3",
|
||||
"svelte-loader": "^2.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"babel-loader": "^7.0.0 || ^8.0.0",
|
||||
"svelte": "^2.7.2",
|
||||
"svelte-loader": "^2.9.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@storybook/vue",
|
||||
"version": "4.0.12",
|
||||
"version": "4.1.0-alpha.12",
|
||||
"description": "Storybook for Vue: Develop Vue Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/app/vue",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
@ -28,12 +25,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@storybook/core": "4.0.12",
|
||||
"@storybook/core": "4.1.0-alpha.12",
|
||||
"common-tags": "^1.8.0",
|
||||
"core-js": "^2.5.7",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.6.0",
|
||||
"react-dom": "^16.6.0"
|
||||
"react-dom": "^16.6.0",
|
||||
"regenerator-runtime": "^0.12.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-preset-vue": "^2.0.2",
|
||||
@ -46,5 +44,8 @@
|
||||
"vue": ">=2.5.16",
|
||||
"vue-loader": ">=15.x.x",
|
||||
"vue-template-compiler": ">=2.5.16"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ const checkRequiredLabels = labels => {
|
||||
const foundLabels = intersection(requiredLabels, labels);
|
||||
if (isEmpty(foundLabels)) {
|
||||
fail(`PR is not labeled with one of: ${JSON.stringify(requiredLabels)}`);
|
||||
} else if (foundLabels.length > 1) {
|
||||
fail(`Please choose only one of these labels: ${JSON.stringify(foundLabels)}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6,11 +6,13 @@ const sm = require('sitemap');
|
||||
const stripIndent = require('common-tags/lib/stripIndent');
|
||||
|
||||
function pagesToSitemap(pages) {
|
||||
return pages.filter(p => !!p.path).map(p => ({
|
||||
url: p.path,
|
||||
changefreq: 'daily',
|
||||
priority: 0.7,
|
||||
}));
|
||||
return pages
|
||||
.filter(p => !!p.path)
|
||||
.map(p => ({
|
||||
url: p.path,
|
||||
changefreq: 'daily',
|
||||
priority: 0.7,
|
||||
}));
|
||||
}
|
||||
|
||||
function generateSitemap(pages) {
|
||||
|
@ -19,16 +19,16 @@
|
||||
"prepare": "npm run snyk-protect"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addon-actions": "^4.0.0",
|
||||
"@storybook/addon-links": "^3.4.11",
|
||||
"@storybook/addons": "^3.4.11",
|
||||
"@storybook/addon-actions": "^4.0.9",
|
||||
"@storybook/addon-links": "^4.0.9",
|
||||
"@storybook/addons": "^4.0.9",
|
||||
"@storybook/react": "^3.4.11",
|
||||
"babel-loader": "^6.4.1",
|
||||
"bootstrap": "^4.1.3",
|
||||
"common-tags": "^1.8.0",
|
||||
"gatsby": "^1.9.279",
|
||||
"gatsby-link": "^1.6.45",
|
||||
"gatsby-plugin-sharp": "^2.0.10",
|
||||
"gatsby-plugin-sharp": "^2.0.12",
|
||||
"gatsby-remark-autolink-headers": "^1.4.19",
|
||||
"gatsby-remark-copy-linked-files": "^1.5.37",
|
||||
"gatsby-remark-images": "^1.5.67",
|
||||
@ -36,9 +36,9 @@
|
||||
"gatsby-source-filesystem": "^1.5.39",
|
||||
"gatsby-transformer-remark": "^1.7.44",
|
||||
"global": "^4.3.2",
|
||||
"highlight.js": "^9.13.0",
|
||||
"highlight.js": "^9.13.1",
|
||||
"lodash": "^4.17.11",
|
||||
"marked": "^0.5.1",
|
||||
"marked": "^0.5.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^15.6.2",
|
||||
"react-document-title": "^2.0.3",
|
||||
@ -46,8 +46,8 @@
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-router": "^4.3.1",
|
||||
"react-stack-grid": "^0.7.1",
|
||||
"sitemap": "^2.0.1",
|
||||
"snyk": "^1.104.0"
|
||||
"sitemap": "^2.1.0",
|
||||
"snyk": "^1.110.2"
|
||||
},
|
||||
"snyk": true
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import '@storybook/addon-actions/register';
|
||||
import '@storybook/addon-links/register';
|
||||
import '@storybook/addon-notes/register';
|
||||
```
|
||||
Once created, youl'll have to restart storybook to make the underlying webpack aware of the addons file.
|
||||
|
||||
|
||||
This will register all the addons and you'll be able to see the actions and notes panels (in that order) when you are viewing the story. (Links do not register a tab--check individual addon docs to see which Storybook features they use!)
|
||||
|
||||
|
@ -15,11 +15,11 @@ In this guide, we will set up Storybook for your React project.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Add @storybook/react](#add-storybookreact)
|
||||
- [Add react, react-dom, babel-core, and babel-loader](#add-react-react-dom-babel-core-and-babel-loader)
|
||||
- [Create the config file](#create-the-config-file)
|
||||
- [Write your stories](#write-your-stories)
|
||||
- [Run your Storybook](#run-your-storybook)
|
||||
- [Add @storybook/react](#add-storybookreact)
|
||||
- [Add react, react-dom, @babel/core, and babel-loader](#add-react-react-dom-babel-core-and-babel-loader)
|
||||
- [Create the config file](#create-the-config-file)
|
||||
- [Write your stories](#write-your-stories)
|
||||
- [Run your Storybook](#run-your-storybook)
|
||||
|
||||
## Add @storybook/react
|
||||
|
||||
@ -29,13 +29,13 @@ First of all, you need to add `@storybook/react` to your project. To do that, ru
|
||||
npm i --save-dev @storybook/react
|
||||
```
|
||||
|
||||
## Add react, react-dom, babel-core, and babel-loader
|
||||
## Add react, react-dom, @babel/core, and babel-loader
|
||||
|
||||
Make sure that you have `react`, `react-dom`, `babel-core`, and `babel-loader` in your dependencies as well because we list these as peer dependencies:
|
||||
Make sure that you have `react`, `react-dom`, `@babel/core`, and `babel-loader` in your dependencies as well because we list these as a peer dependencies:
|
||||
|
||||
```sh
|
||||
npm i --save react react-dom
|
||||
npm i --save-dev babel-core
|
||||
npm i --save-dev @babel/core
|
||||
npm i --save-dev babel-loader
|
||||
```
|
||||
|
||||
@ -51,7 +51,7 @@ Then add the following NPM script to your `package.json` in order to start the s
|
||||
|
||||
## Create the config file
|
||||
|
||||
Storybook can be configured in several different ways.
|
||||
Storybook can be configured in several different ways.
|
||||
That’s why we need a config directory. We've added a `-c` option to the above NPM script mentioning `.storybook` as the config directory.
|
||||
|
||||
For a basic Storybook configuration, the only thing you need to do is tell Storybook where to find stories.
|
||||
@ -83,14 +83,12 @@ import { storiesOf } from '@storybook/react';
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
storiesOf('Button', module)
|
||||
.add('with text', () => <Button>Hello Button</Button>)
|
||||
.add('with text', () => (
|
||||
<Button>Hello Button</Button>
|
||||
))
|
||||
.add('with some emoji', () => (
|
||||
<Button>
|
||||
<span role="img" aria-label="so cool">
|
||||
😀 😎 👍 💯
|
||||
</span>
|
||||
</Button>
|
||||
));
|
||||
<Button><span role="img" aria-label="so cool">😀 😎 👍 💯</span></Button>
|
||||
));
|
||||
```
|
||||
|
||||
Each story is a single state of your component. In the above case, there are two stories for the demo button component:
|
||||
|
@ -86,4 +86,5 @@ storybook({
|
||||
port: 9009,
|
||||
configDir: './.storybook',
|
||||
});
|
||||
```
|
||||
```
|
||||
|
||||
|
@ -78,7 +78,17 @@ overlayBackground: applied to overlay `background`, // 'linear-gradient(to botto
|
||||
All options above are single key options, in other words, they are variables, and their usage is fixed.
|
||||
|
||||
We will extend the theming ability in the future and possibly add more deep theming ability.
|
||||
Right now we have identified the most likely thing you might want to change the appearance of more then just 1 variable so we allow you the deep-theme the header using: `brand`.
|
||||
Right now we allow to deep theme: `stories nav panel`. Below are the varaiables that are used to deep theme `stories nav panel`.
|
||||
|
||||
storiesNav: deep theme for `stories nav`
|
||||
|
||||
```
|
||||
storiesNav: {
|
||||
backgroundColor: 'aqua',
|
||||
}
|
||||
```
|
||||
|
||||
brand: deep theme for brand including `brand name` and `shortcuts`
|
||||
|
||||
```
|
||||
brand: {
|
||||
@ -86,6 +96,69 @@ brand: {
|
||||
}
|
||||
```
|
||||
|
||||
brandLink: deep theme for only `brand name`
|
||||
|
||||
```
|
||||
brandLink: {
|
||||
border: 'none'
|
||||
}
|
||||
```
|
||||
|
||||
filter: deep thene for `stories filter section`
|
||||
|
||||
```
|
||||
filter: {
|
||||
backgroundColor: 'red',
|
||||
}
|
||||
```
|
||||
|
||||
treeHeader: deep thene for `tree header`
|
||||
|
||||
```
|
||||
treeHeader: {
|
||||
color: 'blue',
|
||||
}
|
||||
```
|
||||
|
||||
treeMenuHeader: deep thene for `tree menu header` of each menu
|
||||
|
||||
```
|
||||
treeMenuHeader: {
|
||||
color: 'aqua',
|
||||
}
|
||||
```
|
||||
|
||||
menuLink: deep thene for `menu link` of each story
|
||||
|
||||
```
|
||||
menuLink: {
|
||||
color: 'black',
|
||||
}
|
||||
```
|
||||
|
||||
activeMenuLink: deep thene for `active menu link` for the active story
|
||||
|
||||
```
|
||||
activeMenuLink: {
|
||||
fontWeight: 'light',
|
||||
}
|
||||
```
|
||||
|
||||
treeArrow: deep theme for `tree arrow`. This accepts an object which receives `height`, `width`, `base` and `wrapper`
|
||||
|
||||
```
|
||||
treeArrow: {
|
||||
height: 5,
|
||||
width: 5,
|
||||
base: {
|
||||
fontSize: '12px'
|
||||
},
|
||||
wrapper: {
|
||||
backgroundColor: 'white'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The styles provided here support everything [emotion](https://emotion.sh/) does. So that included things like nested selectors!
|
||||
|
||||
## Adding more theme variables for addons
|
||||
|
@ -1,11 +1,13 @@
|
||||
---
|
||||
id: 'typescript-config'
|
||||
title: 'Typescript Config'
|
||||
title: 'TypeScript Config'
|
||||
---
|
||||
|
||||
This is a central reference for using Storybook with Typescript.
|
||||
This is a central reference for using Storybook with TypeScript.
|
||||
|
||||
## Dependencies you may need
|
||||
## Setting up TypeScript with awesome-typescript-loader
|
||||
|
||||
### Dependencies you may need
|
||||
|
||||
```bash
|
||||
yarn add -D typescript
|
||||
@ -17,7 +19,7 @@ yarn add -D jest "@types/jest" ts-jest #testing
|
||||
|
||||
We have had the best experience using `awesome-typescript-loader`, but other tutorials may use `ts-loader`, just configure accordingly. You can even use `babel-loader` with a `ts-loader` configuration.
|
||||
|
||||
## Setting up Typescript to work with Storybook
|
||||
### Setting up TypeScript to work with Storybook
|
||||
|
||||
We first have to use the [custom Webpack config in full control mode, extending default configs](/configurations/custom-webpack-config/#full-control-mode--default) by creating a `webpack.config.js` file in our Storybook configuration directory (by default, it’s `.storybook`):
|
||||
|
||||
@ -37,7 +39,7 @@ module.exports = (baseConfig, env, config) => {
|
||||
|
||||
The above example shows a working Webpack config with the TSDocgen plugin also integrated; remove the optional sections if you don't plan on using them.
|
||||
|
||||
## `tsconfig.json`
|
||||
### `tsconfig.json`
|
||||
|
||||
```json
|
||||
{
|
||||
@ -71,9 +73,41 @@ The above example shows a working Webpack config with the TSDocgen plugin also i
|
||||
|
||||
This is for the default configuration where `/stories` is a peer of `src`. If you have them all in just `src` you may wish to replace `"rootDirs": ["src", "stories"]` above with `"rootDir": "src",`.
|
||||
|
||||
## Setting up TypeScript with babel-loader
|
||||
|
||||
When using latest create-react-app (CRA 2.0), Babel 7 has native TypeScript support. Setup becomes easier.
|
||||
|
||||
### Dependencies you may need
|
||||
|
||||
```bash
|
||||
yarn add -D @types/storybook__react # typings
|
||||
```
|
||||
|
||||
### Setting up TypeScript to work with Storybook
|
||||
|
||||
We first have to use the [custom Webpack config in full control mode, extending default configs](/configurations/custom-webpack-config/#full-control-mode--default) by creating a `webpack.config.js` file in our Storybook configuration directory (by default, it’s `.storybook`):
|
||||
|
||||
```js
|
||||
module.exports = (baseConfig, env, config) => {
|
||||
config.module.rules.push({
|
||||
test: /\.(ts|tsx)$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
presets: [['react-app', { flow: false, typescript: true }]],
|
||||
},
|
||||
});
|
||||
config.resolve.extensions.push('.ts', '.tsx');
|
||||
return config;
|
||||
};
|
||||
```
|
||||
|
||||
### `tsconfig.json`
|
||||
|
||||
The default `tsconfig.json` that comes with CRA works great. If your stories are outside the `src` folder, for example the `stories` folder in root, then `rootDirs": ["src", "stories"]` needs to be added to be added to `compilerOptions` so it knows what folders to compile. Make sure `jsx` is set to preserve. Should be unchanged.
|
||||
|
||||
## Import tsx stories
|
||||
|
||||
Change `config.ts` inside the Storybook config directory (by default, it’s `.storybook`) to import stories made with Typescript:
|
||||
Change `config.ts` inside the Storybook config directory (by default, it’s `.storybook`) to import stories made with TypeScript:
|
||||
|
||||
```js
|
||||
// automatically import all files ending in *.stories.tsx
|
||||
@ -86,9 +120,9 @@ function loadStories() {
|
||||
configure(loadStories, module);
|
||||
```
|
||||
|
||||
## Using Typescript with the TSDocgen addon
|
||||
## Using TypeScript with the TSDocgen addon
|
||||
|
||||
The very handy [Storybook Info addon](https://github.com/storybooks/storybook/tree/master/addons/info) autogenerates prop tables documentation for each component, however it doesn't work with Typescript types. The current solution is to use [react-docgen-typescript-loader](https://github.com/strothj/react-docgen-typescript-loader) to preprocess the Typescript files to give the Info addon what it needs. The webpack config above does this, and so for the rest of your stories you use it as per normal:
|
||||
The very handy [Storybook Info addon](https://github.com/storybooks/storybook/tree/master/addons/info) autogenerates prop tables documentation for each component, however it doesn't work with Typescript types. The current solution is to use [react-docgen-typescript-loader](https://github.com/strothj/react-docgen-typescript-loader) to preprocess the TypeScript files to give the Info addon what it needs. The webpack config above does this, and so for the rest of your stories you use it as per normal:
|
||||
|
||||
```js
|
||||
import * as React from 'react';
|
||||
@ -196,16 +230,16 @@ This is an example `jest.config.js` file for jest:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
transform: {
|
||||
".(ts|tsx)": "ts-jest",
|
||||
},
|
||||
testPathIgnorePatterns: ["/node_modules/", "/lib/"],
|
||||
testRegex: "(/test/.*|\\.(test|spec))\\.(ts|tsx|js)$",
|
||||
moduleFileExtensions: ["ts", "tsx", "js", "json"],
|
||||
transform: {
|
||||
'.(ts|tsx)': 'ts-jest',
|
||||
},
|
||||
testPathIgnorePatterns: ['/node_modules/', '/lib/'],
|
||||
testRegex: '(/test/.*|\\.(test|spec))\\.(ts|tsx|js)$',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||
};
|
||||
```
|
||||
|
||||
## Building your Typescript Storybook
|
||||
## Building your TypeScript Storybook
|
||||
|
||||
You will need to set up some scripts - these may help:
|
||||
|
||||
|
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