Merge remote-tracking branch 'origin/master' into angular-storyshots

# Conflicts:
#	.editorconfig
#	addons/storyshots/package.json
#	examples/angular-cli/package.json
#	examples/vue-kitchen-sink/package.json
#	yarn.lock
This commit is contained in:
igor 2018-01-14 13:12:46 +02:00
commit 5fcf200a08
132 changed files with 3165 additions and 592 deletions

View File

@ -3,6 +3,6 @@ root = true
[*]
end_of_line = lf
[*.{js,json,ts,vue}]
[*.{js,json,ts,vue,html}]
indent_style = space
indent_size = 2

View File

@ -1,3 +1,102 @@
# 3.4.0-alpha.4
2018-January-13
Republish `3.4.0-alpha.3` due to potential publishing errors
# 3.4.0-alpha.3
2018-January-13
#### Features
- Polymer 2 support [#2225](https://github.com/storybooks/storybook/pull/2225)
- Add image snapshots to addon-storyshots [#2413](https://github.com/storybooks/storybook/pull/2413)
- Angular template support for Storybook [#2690](https://github.com/storybooks/storybook/pull/2690)
#### Bug Fixes
- Remove polymer-cli dependency [#2741](https://github.com/storybooks/storybook/pull/2741)
- Add scss for components in angular apps by default. [#2703](https://github.com/storybooks/storybook/pull/2703)
#### Maintenance
- Change ng stories dir [#2672](https://github.com/storybooks/storybook/pull/2672)
#### Dependency Upgrades
<details>
<summary>
54 Upgrades
</summary>
- Upgraded `jest-image-snapshot` in `/` from "2.2.1" to "2.3.0" [#2740](https://github.com/storybooks/storybook/pull/2740)
- Upgraded `polymer-webpack-loader` in `app/polymer` from "2.0.0" to "2.0.1" [#2740](https://github.com/storybooks/storybook/pull/2740)
- Upgraded `jest-image-snapshot` in `addons/storyshots` from "2.2.1" to "2.3.0" [#2740](https://github.com/storybooks/storybook/pull/2740)
- Upgraded `shelljs` in `/` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `shelljs` in `addons/links` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `autoprefixer` in `app/react` from "7.2.4" to "7.2.5" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `shelljs` in `app/react` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `autoprefixer` in `app/angular` from "7.2.4" to "7.2.5" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `shelljs` in `app/angular` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `autoprefixer` in `app/react-native` from "7.2.4" to "7.2.5" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `shelljs` in `app/react-native` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `autoprefixer` in `app/vue` from "7.2.4" to "7.2.5" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `shelljs` in `app/vue` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Upgraded `shelljs` in `lib/cli` from "0.7.8" to "0.8.0" [#2734](https://github.com/storybooks/storybook/pull/2734)
- Update gatsby in /docs from 1.9.153 to 1.9.154 [#2733](https://github.com/storybooks/storybook/pull/2733)
- Update @angular/cli in examples/angular-cli from 1.6.3 to 1.6.4 [#2726](https://github.com/storybooks/storybook/pull/2726)
- Upgraded `commander` in `/` from "2.12.2" to "2.13.0" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest` in `/` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest-cli` in `/` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest-config` in `/` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest-diff` in `/` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest-environment-jsdom` in `/` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest-jasmine2` in `/` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `nodemon` in `/` from "1.14.10" to "1.14.11" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `prettier` in `/` from "1.9.2" to "1.10.2" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `tslint` in `/` from "5.8.0" to "5.9.1" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `commander` in `app/react` from "2.12.2" to "2.13.0" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `common-tags` in `app/react` from "1.7.0" to "1.7.2" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `nodemon` in `app/react` from "1.14.10" to "1.14.11" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `commander` in `app/angular` from "2.12.2" to "2.13.0" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `common-tags` in `app/angular` from "1.7.0" to "1.7.2" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `zone.js` in `app/angular` from "0.8.19" to "0.8.20" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `nodemon` in `app/angular` from "1.14.10" to "1.14.11" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `commander` in `app/react-native` from "2.12.2" to "2.13.0" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `commander` in `app/vue` from "2.12.2" to "2.13.0" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `common-tags` in `app/vue` from "1.7.0" to "1.7.2" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `nodemon` in `app/vue` from "1.14.10" to "1.14.11" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `babel-jest` in `examples/cra-kitchen-sink` from "22.0.4" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `jest` in `examples/cra-kitchen-sink` from "22.0.5" to "22.0.6" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `commander` in `lib/cli` from "2.12.2" to "2.13.0" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `zone.js` in `examples/angular-cli` from "0.8.19" to "0.8.20" [#2724](https://github.com/storybooks/storybook/pull/2724)
- Upgraded `@storybook/addon-actions` in `/docs` from "3.3.7" to "3.3.8" [#2722](https://github.com/storybooks/storybook/pull/2722)
- Upgraded `@storybook/addon-links` in `/docs` from "3.3.7" to "3.3.8" [#2722](https://github.com/storybooks/storybook/pull/2722)
- Upgraded `@storybook/addons` in `/docs` from "3.3.7" to "3.3.8" [#2722](https://github.com/storybooks/storybook/pull/2722)
- Upgraded `@storybook/react` in `/docs` from "3.3.7" to "3.3.8" [#2722](https://github.com/storybooks/storybook/pull/2722)
- Upgraded `gatsby-transformer-remark` in `/docs` from "1.7.27" to "1.7.28" [#2722](https://github.com/storybooks/storybook/pull/2722)
- Upgraded `gatsby` in `/docs` from "1.9.151" to "1.9.153" [#2722](https://github.com/storybooks/storybook/pull/2722)
- Upgraded `@storybook/addon-actions` in `/docs` from "3.3.6" to "3.3.7" [#2710](https://github.com/storybooks/storybook/pull/2710)
- Upgraded `@storybook/addon-links` in `/docs` from "3.3.6" to "3.3.7" [#2710](https://github.com/storybooks/storybook/pull/2710)
- Upgraded `@storybook/addons` in `/docs` from "3.3.6" to "3.3.7" [#2710](https://github.com/storybooks/storybook/pull/2710)
- Upgraded `@storybook/react` in `/docs` from "3.3.6" to "3.3.7" [#2710](https://github.com/storybooks/storybook/pull/2710)
- Upgraded `gatsby-link` in `/docs` from "1.6.33" to "1.6.34" [#2710](https://github.com/storybooks/storybook/pull/2710)
- Upgraded `gatsby-transformer-remark` in `/docs` from "1.7.26" to "1.7.27" [#2710](https://github.com/storybooks/storybook/pull/2710)
- Upgraded `gatsby` in `/docs` from "1.9.150" to "1.9.151" [#2710](https://github.com/storybooks/storybook/pull/2710)
</details>
# 3.3.9
2018-January-13
#### Bug Fixes
- Start haul/react-native using named binaries instead of cli.js [#2715](https://github.com/storybooks/storybook/pull/2715)
- Reflect the new peer dependencies in docs and CLI templates [#2714](https://github.com/storybooks/storybook/pull/2714)
- Don't mangle function names for production builds [#2705](https://github.com/storybooks/storybook/pull/2705)
# 3.4.0-alpha.2
2018-January-11

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-a11y",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "a11y addon for storybook",
"keywords": [
"a11y",
@ -25,8 +25,9 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.4",
"axe-core": "^2.6.1",
"glamorous": "^4.11.2",
"prop-types": "^15.6.0"
},
"peerDependencies": {

View File

@ -6,10 +6,10 @@ import Report from './Report';
const styles = {
passes: {
color: '#2ecc71',
color: '#0D6731',
},
violations: {
color: '#e74c3c',
color: '#AC2300',
},
};
@ -47,11 +47,11 @@ class Panel extends Component {
<Tabs
tabs={[
{
label: <span style={styles.violations}>Violations</span>,
label: <span style={styles.violations}>{violations.length} Violations</span>,
panel: <Report passes={false} items={violations} empty="No a11y violations found." />,
},
{
label: <span style={styles.passes}>Passes</span>,
label: <span style={styles.passes}>{passes.length} Passes</span>,
panel: <Report passes items={passes} empty="No a11y check passed" />,
},
]}

View File

@ -0,0 +1,17 @@
import glamorous from 'glamorous';
const RerunButton = glamorous.button({
position: 'absolute',
bottom: 0,
right: 0,
border: 'none',
borderTop: 'solid 1px rgba(0, 0, 0, 0.2)',
borderLeft: 'solid 1px rgba(0, 0, 0, 0.2)',
background: 'rgba(255, 255, 255, 0.5)',
padding: '5px 10px',
borderRadius: '4px 0 0 0',
color: 'rgba(0, 0, 0, 0.5)',
textTransform: 'uppercase',
});
export default RerunButton;

View File

@ -1,6 +1,7 @@
import React from 'react';
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import addons from '@storybook/addons';
import RerunButton from './RerunButton';
import Item from './Item';
const styles = {
@ -17,17 +18,23 @@ const styles = {
},
};
function Report({ items, empty, passes }) {
if (items.length) {
return (
function onRerunClick() {
const channel = addons.getChannel();
channel.emit('addon:a11y:rerun');
}
const Report = ({ items, empty, passes }) => (
<Fragment>
{items.length ? (
<div style={styles.container}>
{items.map(item => <Item passes={passes} item={item} key={item.id} />)}
</div>
);
}
return <span style={styles.empty}>{empty}</span>;
}
) : (
<span style={styles.empty}>{empty}</span>
)}
<RerunButton onClick={onRerunClick}>Re-run tests</RerunButton>
</Fragment>
);
Report.propTypes = {
items: PropTypes.arrayOf(

View File

@ -5,6 +5,7 @@ import { baseFonts } from '@storybook/components';
const styles = {
container: {
width: '100%',
position: 'relative',
...baseFonts,
},
tabs: {

View File

@ -15,8 +15,24 @@ class WrapStory extends Component {
channel: {},
};
/* eslint-disable react/no-find-dom-node */
constructor(props) {
super(props);
this.runA11yCheck = this.runA11yCheck.bind(this);
}
componentDidMount() {
const { channel } = this.props;
channel.on('addon:a11y:rerun', this.runA11yCheck);
this.runA11yCheck();
}
componentWillUnmount() {
const { channel } = this.props;
channel.removeListener('addon:a11y:rerun', this.runA11yCheck);
}
/* eslint-disable react/no-find-dom-node */
runA11yCheck() {
const { channel } = this.props;
const wrapper = findDOMNode(this);

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-actions",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Action Logger addon for storybook",
"keywords": [
"storybook"

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-backgrounds",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "A storybook addon to show different backgrounds for your preview",
"keywords": [
"addon",

View File

@ -5,7 +5,7 @@ import addons from '@storybook/addons';
const style = {
wrapper: {
overflow: 'scroll',
overflow: 'auto',
position: 'fixed',
top: 0,
bottom: 0,

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-centered",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook decorator to center components",
"license": "MIT",
"author": "Muhammed Thanish <mnmtanish@gmail.com>",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-events",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Add events to your Storybook stories.",
"keywords": [
"addon",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-graphql",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook addon to display the GraphiQL IDE",
"keywords": [
"storybook"

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-info",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "A Storybook addon to show additional information for your stories.",
"license": "MIT",
"main": "dist/index.js",
@ -15,8 +15,8 @@
"storybook": "start-storybook -p 9010"
},
"dependencies": {
"@storybook/client-logger": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/client-logger": "^3.4.0-alpha.4",
"@storybook/components": "^3.4.0-alpha.4",
"babel-runtime": "^6.26.0",
"global": "^4.3.2",
"marksy": "^6.0.3",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-jest",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "React storybook addon that show component jest report",
"keywords": [
"addon",
@ -25,7 +25,7 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.4",
"glamor": "^2.20.40",
"glamorous": "^4.11.2",
"global": "^4.3.2",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-knobs",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook Addon Prop Editor Component",
"license": "MIT",
"main": "dist/index.js",

1
addons/knobs/polymer.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('./dist/polymer');

View File

@ -0,0 +1,87 @@
<dom-module id="wrap-story">
<script>
class WrapStory extends HTMLElement {
static get is() {
return 'wrap-story';
}
constructor(component, channel, context, storyFn, knobStore) {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = '<div id="wrapper"></div>';
this.channel = channel;
this.context = context;
this.storyFn = storyFn;
this.knobStore = knobStore;
this.knobChanged = this.knobChanged.bind(this);
this.knobClicked = this.knobClicked.bind(this);
this.resetKnobs = this.resetKnobs.bind(this);
this.setPaneKnobs = this.setPaneKnobs.bind(this);
this.connectChannel(this.channel);
this.knobStore.subscribe(this.setPaneKnobs);
this.render(component);
}
disconnectedCallback() {
this.disconnectChannel(this.channel);
this.knobStore.unsubscribe(this.setPaneKnobs);
}
connectChannel(channel) {
channel.on('addon:knobs:knobChange', this.knobChanged);
channel.on('addon:knobs:knobClick', this.knobClicked);
channel.on('addon:knobs:reset', this.resetKnobs);
}
disconnectChannel(channel) {
channel.removeListener('addon:knobs:knobChange', this.knobChanged);
channel.removeListener('addon:knobs:knobClick', this.knobClicked);
channel.removeListener('addon:knobs:reset', this.resetKnobs);
}
knobChanged(change) {
const { name, value } = change;
const { knobStore, storyFn, context } = this;
// Update the related knob and it's value.
const knobOptions = knobStore.get(name);
knobOptions.value = value;
knobStore.markAllUnused();
this.render(storyFn(context));
}
knobClicked(clicked) {
const knobOptions = this.knobStore.get(clicked.name);
knobOptions.callback();
}
resetKnobs() {
const { knobStore, storyFn, context } = this;
knobStore.reset();
this.render(storyFn(context));
this.setPaneKnobs(this.channel, this.knobStore, false);
}
setPaneKnobs(timestamp = +new Date()) {
const { channel, knobStore } = this;
channel.emit('addon:knobs:setKnobs', { knobs: knobStore.getAll(), timestamp });
}
render(component) {
const wrapper = this.shadowRoot.querySelector('div#wrapper');
if (typeof component === 'string') {
wrapper.innerHTML = component;
} else {
wrapper.innerHTML = '';
wrapper.appendChild(component);
}
}
}
customElements.define(WrapStory.is, WrapStory);
</script>
</dom-module>

View File

@ -0,0 +1,36 @@
import addons from '@storybook/addons';
import window from 'global';
import './WrapStory.html';
import { knob, text, boolean, number, color, object, array, date, select, manager } from '../base';
export { knob, text, boolean, number, color, object, array, date, select };
export function button(name, callback) {
return manager.knob(name, { type: 'button', value: Date.now(), callback, hideLabel: true });
}
function prepareComponent({ getStory, context, channel, knobStore }) {
const WrapStory = window.customElements.get('wrap-story');
return new WrapStory(getStory(context), channel, context, getStory, knobStore);
}
export const polymerHandler = (channel, knobStore) => getStory => context =>
prepareComponent({ getStory, context, channel, knobStore });
function wrapperKnobs(options) {
const channel = addons.getChannel();
manager.setChannel(channel);
if (options) channel.emit('addon:knobs:setOptions', options);
return polymerHandler(channel, manager.knobStore);
}
export function withKnobs(storyFn, context) {
return wrapperKnobs()(storyFn)(context);
}
export function withKnobsOptions(options = {}) {
return (storyFn, context) => wrapperKnobs(options)(storyFn)(context);
}

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-links",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Story Links addon for storybook",
"keywords": [
"storybook"
@ -22,7 +22,7 @@
"storybook": "start-storybook -p 9001"
},
"dependencies": {
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.4",
"global": "^4.3.2",
"prop-types": "^15.5.10"
},
@ -30,7 +30,7 @@
"enzyme": "^3.3.0",
"react": "^16.1.0",
"react-dom": "^16.1.0",
"shelljs": "^0.7.8"
"shelljs": "^0.8.0"
},
"peerDependencies": {
"@storybook/addons": "^3.3.0",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-notes",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Write notes for your Storybook stories.",
"keywords": [
"addon",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-options",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Options addon for storybook",
"keywords": [
"storybook"

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-storyshots",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
"license": "MIT",
"main": "dist/index.js",
@ -16,19 +16,19 @@
"example": "jest storyshot.test"
},
"dependencies": {
"@storybook/channels": "^3.4.0-alpha.1",
"@storybook/channels": "^3.4.0-alpha.4",
"babel-runtime": "^6.26.0",
"glob": "^7.1.2",
"global": "^4.3.2",
"jest-image-snapshot": "^2.3.0",
"jest-specific-snapshot": "^0.3.0",
"jest-image-snapshot": "^2.2.0",
"prop-types": "^15.6.0",
"puppeteer": "^0.13.0",
"read-pkg-up": "^3.0.0"
},
"devDependencies": {
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/react": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/react": "^3.4.0-alpha.4",
"babel-cli": "^6.26.0",
"babel-jest": "^20.0.3",
"babel-plugin-transform-runtime": "^6.23.0",
@ -42,7 +42,7 @@
"react-dom": "^16.1.0"
},
"peerDependencies": {
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.4",
"babel-core": "^6.26.0 || ^7.0.0-0"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addon-viewport",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook addon to change the viewport size to mobile",
"main": "register.js",
"keywords": [
@ -11,7 +11,7 @@
},
"license": "MIT",
"dependencies": {
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.4",
"global": "^4.3.2",
"prop-types": "^15.5.10"
},

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/angular",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.",
"homepage": "https://github.com/storybooks/storybook/tree/master/apps/angular",
"bugs": {
@ -23,15 +23,15 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/channel-postmessage": "^3.4.0-alpha.1",
"@storybook/core": "^3.4.0-alpha.1",
"@storybook/ui": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/channel-postmessage": "^3.4.0-alpha.4",
"@storybook/core": "^3.4.0-alpha.4",
"@storybook/ui": "^3.4.0-alpha.4",
"airbnb-js-shims": "^1.1.1",
"angular2-template-loader": "^0.6.2",
"autoprefixer": "^7.2.4",
"autoprefixer": "^7.2.5",
"babel-core": "^6.26.0",
"babel-loader": "^7.0.0",
"babel-plugin-react-docgen": "^1.6.0",
@ -73,7 +73,7 @@
"rxjs": "^5.4.2",
"sass-loader": "^6.0.6",
"serve-favicon": "^2.4.3",
"shelljs": "^0.7.8",
"shelljs": "^0.8.0",
"style-loader": "^0.18.2",
"ts-loader": "^2.2.2",
"uglifyjs-webpack-plugin": "^1.1.6",

3
app/polymer/.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": ["env", "stage-0", "react"]
}

3
app/polymer/.npmignore Normal file
View File

@ -0,0 +1,3 @@
docs
src
.babelrc

41
app/polymer/README.md Normal file
View File

@ -0,0 +1,41 @@
# Storybook for Polymer
[![Build Status on CircleCI](https://circleci.com/gh/storybooks/storybook.svg?style=shield)](https://circleci.com/gh/storybooks/storybook)
[![CodeFactor](https://www.codefactor.io/repository/github/storybooks/storybook/badge)](https://www.codefactor.io/repository/github/storybooks/storybook)
[![Known Vulnerabilities](https://snyk.io/test/github/storybooks/storybook/8f36abfd6697e58cd76df3526b52e4b9dc894847/badge.svg)](https://snyk.io/test/github/storybooks/storybook/8f36abfd6697e58cd76df3526b52e4b9dc894847)
[![BCH compliance](https://bettercodehub.com/edge/badge/storybooks/storybook)](https://bettercodehub.com/results/storybooks/storybook) [![codecov](https://codecov.io/gh/storybooks/storybook/branch/master/graph/badge.svg)](https://codecov.io/gh/storybooks/storybook)
[![Storybook Slack](https://now-examples-slackin-nqnzoygycp.now.sh/badge.svg)](https://now-examples-slackin-nqnzoygycp.now.sh/)
[![Backers on Open Collective](https://opencollective.com/storybook/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/storybook/sponsors/badge.svg)](#sponsors)
* * *
Storybook for polymer is a UI development environment for your Polymer components.
With it, you can visualize different states of your UI components and develop them interactively.
> Storybook for Polymer is at the **EXPERIMENTAL** stage!
![Storybook Screenshot](https://github.com/storybooks/storybook/blob/master/app/polymer/docs/demo.gif)
Storybook runs outside of your app.
So you can develop UI components in isolation without worrying about app specific dependencies and requirements.
## Getting Started
```sh
npm i -g @storybook/cli
cd my-polymer-app
getstorybook
```
For more information visit: [storybook.js.org](https://storybook.js.org)
* * *
Storybook also comes with a lot of [addons](https://storybook.js.org/addons/introduction) and a great API to customize as you wish.
You can also build a [static version](https://storybook.js.org/basics/exporting-storybook) of your storybook and deploy it anywhere you want.
## Polymer Notes
- This is super super experimental, if you want to use this, expect some bugs, and missing features.
- We're looking for help to support this. If you're a member of the Polymer community and like this project, please help us!
If you need any onboarding from us, we're happy to help you in any way!

3
app/polymer/bin/build.js Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env node
require('../dist/server/build');

3
app/polymer/bin/index.js Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env node
require('../dist/server');

BIN
app/polymer/docs/demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

87
app/polymer/package.json Normal file
View File

@ -0,0 +1,87 @@
{
"name": "@storybook/polymer",
"version": "3.4.0-alpha.4",
"description": "Storybook for Polymer: Develop Polymer components in isolation with Hot Reloading.",
"homepage": "https://github.com/storybooks/storybook/tree/master/apps/polymer",
"bugs": {
"url": "https://github.com/storybooks/storybook/issues"
},
"license": "MIT",
"main": "dist/client/index.js",
"bin": {
"build-storybook": "./bin/build.js",
"start-storybook": "./bin/index.js",
"storybook-server": "./bin/index.js"
},
"repository": {
"type": "git",
"url": "https://github.com/storybooks/storybook.git"
},
"scripts": {
"dev": "DEV_BUILD=1 nodemon --watch ./src --exec 'yarn prepare'",
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/channel-postmessage": "^3.4.0-alpha.4",
"@storybook/client-logger": "^3.4.0-alpha.4",
"@storybook/core": "^3.4.0-alpha.4",
"@storybook/node-logger": "^3.4.0-alpha.4",
"@storybook/ui": "^3.4.0-alpha.4",
"@webcomponents/webcomponentsjs": "^1.0.17",
"airbnb-js-shims": "^1.3.0",
"autoprefixer": "^7.1.6",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-react-docgen": "^1.8.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0",
"babel-preset-minify": "^0.2.0",
"babel-preset-react": "^6.24.1",
"babel-preset-react-app": "^3.1.0",
"babel-preset-stage-0": "^6.24.1",
"babel-runtime": "^6.26.0",
"case-sensitive-paths-webpack-plugin": "^2.1.1",
"chalk": "^2.3.0",
"commander": "^2.11.0",
"common-tags": "^1.4.0",
"configstore": "^3.1.1",
"copy-webpack-plugin": "^4.2.0",
"core-js": "^2.5.1",
"css-loader": "^0.28.7",
"express": "^4.16.2",
"file-loader": "^0.11.2",
"find-cache-dir": "^1.0.0",
"global": "^4.3.2",
"html-webpack-plugin": "^2.30.1",
"json-loader": "^0.5.7",
"json-stringify-safe": "^5.0.1",
"json5": "^0.5.1",
"lodash.pick": "^4.4.0",
"polymer-webpack-loader": "2.0.1",
"postcss-flexbugs-fixes": "^3.2.0",
"postcss-loader": "^2.0.8",
"prop-types": "^15.6.0",
"qs": "^6.5.1",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-modal": "^2.4.1",
"redux": "^3.7.2",
"request": "^2.83.0",
"serve-favicon": "^2.4.5",
"shelljs": "^0.7.8",
"style-loader": "^0.18.2",
"url-loader": "^0.6.2",
"util-deprecate": "^1.0.2",
"uuid": "^3.1.0",
"webpack": "^3.6.0",
"webpack-dev-middleware": "^1.12.0",
"webpack-hot-middleware": "^2.20.0"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"nodemon": "^1.12.1"
}
}

View File

@ -0,0 +1,17 @@
// import deprecate from 'util-deprecate';
// NOTE export these to keep backwards compatibility
// import { action as deprecatedAction } from '@storybook/addon-actions';
// import { linkTo as deprecatedLinkTo } from '@storybook/addon-links';
export { storiesOf, setAddon, addDecorator, configure, getStorybook } from './preview';
// export const action = deprecate(
// deprecatedAction,
// '@storybook/react action is deprecated. See: https://github.com/storybooks/storybook/tree/master/addons/actions'
// );
// export const linkTo = deprecate(
// deprecatedLinkTo,
// '@storybook/react linkTo is deprecated. See: https://github.com/storybooks/storybook/tree/master/addons/links'
// );

View File

@ -0,0 +1,7 @@
/* global document */
import renderStorybookUI from '@storybook/ui';
import Provider from './provider';
const rootEl = document.getElementById('root');
renderStorybookUI(rootEl, new Provider());

View File

@ -0,0 +1,39 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
const iframeStyle = {
width: '100%',
height: '100%',
border: 0,
margin: 0,
padding: 0,
};
class Preview extends Component {
shouldComponentUpdate() {
// When the manager is re-rendered, due to changes in the layout (going full screen / changing
// addon panel to right) Preview section will update. If its re-rendered the whole html page
// inside the html is re-rendered making the story to re-mount.
// We dont have to re-render this component for any reason since changes are communicated to
// story using the channel and necessary changes are done by it.
return false;
}
render() {
return (
<iframe
id="storybook-preview-iframe"
title="preview"
style={iframeStyle}
src={this.props.url}
allowFullScreen
/>
);
}
}
Preview.propTypes = {
url: PropTypes.string.isRequired,
};
export default Preview;

View File

@ -0,0 +1,51 @@
import { location } from 'global';
import qs from 'qs';
import React from 'react';
import { Provider } from '@storybook/ui';
import addons from '@storybook/addons';
import createChannel from '@storybook/channel-postmessage';
import Preview from './preview';
export default class ReactProvider extends Provider {
constructor() {
super();
this.channel = createChannel({ page: 'manager' });
addons.setChannel(this.channel);
}
getPanels() {
return addons.getPanels();
}
renderPreview(selectedKind, selectedStory) {
const queryParams = {
selectedKind,
selectedStory,
};
// Add the react-perf query string to the iframe if that present.
if (/react_perf/.test(location.search)) {
queryParams.react_perf = '1';
}
const queryString = qs.stringify(queryParams);
const url = `iframe.html?${queryString}`;
return <Preview url={url} />;
}
handleAPI(api) {
api.onStory((kind, story) => {
this.channel.emit('setCurrentStory', { kind, story });
});
this.channel.on('setStories', data => {
api.setStories(data.stories);
});
this.channel.on('selectStory', data => {
api.selectStory(data.kind, data.story);
});
this.channel.on('applyShortcut', data => {
api.handleShortcut(data.event);
});
addons.loadAddons(api);
}
}

View File

@ -0,0 +1,37 @@
export const errorpreview = (message, stack) => `
<style>
.errordisplay_main {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 20;
background-color: rgb(187, 49, 49);
color: #FFF;
webkit-font-smoothing: antialiased;
}
.errordisplay_heading {
font-size: 20;
font-weight: 600;
letter-spacing: 0.2;
margin: 10px 0;
font-family: -apple-system, ".SFNSText-Regular", "San Francisco", Roboto, "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;
}
.errordisplay_code {
font-size: 14;
width: 100vw;
overflow: auto;
}
</style>
<div class="errordisplay_main">
<div class="errordisplay_heading">${message}</div>
<pre class="errordisplay_code">
<code>
${stack}
</code>
</pre>
</div>
`;

View File

@ -0,0 +1,61 @@
import { createStore } from 'redux';
import addons from '@storybook/addons';
import { navigator, window } from 'global';
import createChannel from '@storybook/channel-postmessage';
import { handleKeyboardShortcuts } from '@storybook/ui/dist/libs/key_events';
import {
StoryStore,
ClientApi,
ConfigApi,
Actions,
reducer,
syncUrlWithStore,
} from '@storybook/core/client';
import render from './render';
// check whether we're running on node/browser
const isBrowser =
navigator &&
navigator.userAgent &&
navigator.userAgent !== 'storyshots' &&
!(navigator.userAgent.indexOf('Node.js') > -1) &&
!(navigator.userAgent.indexOf('jsdom') > -1);
const storyStore = new StoryStore();
/* eslint-disable no-underscore-dangle */
const reduxStore = createStore(reducer);
/* eslint-enable */
const context = { storyStore, reduxStore };
if (isBrowser) {
// setup preview channel
const channel = createChannel({ page: 'preview' });
channel.on('setCurrentStory', data => {
reduxStore.dispatch(Actions.selectStory(data.kind, data.story));
});
addons.setChannel(channel);
Object.assign(context, { channel });
syncUrlWithStore(reduxStore);
// Handle keyboard shortcuts
window.onkeydown = handleKeyboardShortcuts(channel);
}
const clientApi = new ClientApi(context);
export const { storiesOf, setAddon, addDecorator, clearDecorators, getStorybook } = clientApi;
const configApi = new ConfigApi({ clearDecorators, ...context });
export const { configure } = configApi;
// initialize the UI
const renderUI = () => {
if (isBrowser) {
render(context);
}
};
reduxStore.subscribe(renderUI);
export const forceReRender = () => render(context, true);

View File

@ -0,0 +1,42 @@
export const nopreview = `
<style>
.nopreview_wrapper {
position: fixed;
display: flex;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 20;
align-content: center;
justify-content: center;
font-family: -apple-system, ".SFNSText-Regular", "San Francisco", Roboto, "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;
webkit-font-smoothing: antialiased;
}
.nopreview_main {
margin: auto;
padding: 30px;
border-radius: 10px;
background: rgba(0,0,0,0.03);
}
.nopreview_heading {
font-size: 20;
font-weight: 600;
letter-spacing: 0.2;
margin: 10px 0;
text-align: center;
}
</style>
<div class="nopreview_wrapper">
<div class="nopreview_main">
<h1 class="nopreview_heading">No Preview</h1>
<p>Sorry, but you either have no stories or none are selected somehow.</p>
<ul>
<li>Please check the storybook config.</li>
<li>Try reloading the page.</li>
</ul>
</div>
</div>
`;

View File

@ -0,0 +1,66 @@
import { document } from 'global';
import { stripIndents } from 'common-tags';
import { logger } from '@storybook/client-logger';
import { nopreview } from './nopreview';
import { errorpreview } from './errorpreview';
let previousKind = '';
let previousStory = '';
const rootElement = document.getElementById('root');
export function renderError(error) {
rootElement.innerHTML = errorpreview(error.message, error.stack);
}
export function renderException(error) {
renderError(error);
logger.error(error.stack);
}
export function renderMain(data, storyStore) {
if (storyStore.size() === 0) return;
const { selectedKind, selectedStory } = data;
const story = storyStore.getStory(selectedKind, selectedStory);
if (selectedKind !== previousKind || previousStory !== selectedStory) {
previousKind = selectedKind;
previousStory = selectedStory;
} else {
return;
}
const context = {
kind: selectedKind,
story: selectedStory,
};
const component = story ? story(context) : nopreview;
if (!component) {
renderError({
message: `Expecting a Polymer component from the story: "${selectedStory}" of "${selectedKind}".`,
stack: stripIndents`
Did you forget to return the Polymer component from the story?
Use "() => '&lt;your-component-name&gt;&lt;/your-component-name\&gt;'" when defining the story.
`,
});
return;
}
if (typeof component === 'string') {
rootElement.innerHTML = component;
} else {
rootElement.innerHTML = '';
rootElement.appendChild(component);
}
}
export default function renderPreview({ reduxStore, storyStore }) {
const state = reduxStore.getState();
if (state.error) {
return renderException(state.error);
}
try {
return renderMain(state, storyStore);
} catch (ex) {
return renderException(ex);
}
}

View File

@ -0,0 +1,2 @@
// import '@storybook/addon-actions/register';
// import '@storybook/addon-links/register';

View File

@ -0,0 +1,82 @@
import fs from 'fs';
import path from 'path';
import JSON5 from 'json5';
import { logger } from '@storybook/node-logger';
import defaultConfig from './config/babel';
function removeReactHmre(presets) {
const index = presets.indexOf('react-hmre');
if (index > -1) {
presets.splice(index, 1);
}
}
// Tries to load a .babelrc and returns the parsed object if successful
function loadFromPath(babelConfigPath) {
let config;
if (fs.existsSync(babelConfigPath)) {
const content = fs.readFileSync(babelConfigPath, 'utf-8');
try {
config = JSON5.parse(content);
config.babelrc = false;
logger.info('=> Loading custom .babelrc');
} catch (e) {
logger.error(`=> Error parsing .babelrc file: ${e.message}`);
throw e;
}
}
if (!config) return null;
// Remove react-hmre preset.
// It causes issues with react-storybook.
// We don't really need it.
// Earlier, we fix this by running storybook in the production mode.
// But, that hide some useful debug messages.
if (config.presets) {
removeReactHmre(config.presets);
}
if (config.env && config.env.development && config.env.development.presets) {
removeReactHmre(config.env.development.presets);
}
return config;
}
export default function(configDir) {
let babelConfig = loadFromPath(path.resolve(configDir, '.babelrc'));
let inConfigDir = true;
if (!babelConfig) {
babelConfig = loadFromPath('.babelrc');
inConfigDir = false;
}
if (babelConfig) {
// If the custom config uses babel's `extends` clause, then replace it with
// an absolute path. `extends` will not work unless we do this.
if (babelConfig.extends) {
babelConfig.extends = inConfigDir
? path.resolve(configDir, babelConfig.extends)
: path.resolve(babelConfig.extends);
}
}
const finalConfig = babelConfig || defaultConfig;
// Ensure plugins are defined or fallback to an array to avoid empty values.
const babelConfigPlugins = finalConfig.plugins || [];
const extraPlugins = [
[
require.resolve('babel-plugin-react-docgen'),
{
DOC_GEN_COLLECTION_NAME: 'STORYBOOK_REACT_CLASSES',
},
],
];
// If `babelConfigPlugins` is not an `Array`, calling `concat` will inject it
// as a single value, if it is an `Array` it will be spreaded.
finalConfig.plugins = [].concat(babelConfigPlugins, extraPlugins);
return finalConfig;
}

View File

@ -0,0 +1,110 @@
import loadBabelConfig from './babel_config';
// eslint-disable-next-line global-require
jest.mock('fs', () => require('../../../../__mocks__/fs'));
jest.mock('path', () => ({
resolve: () => '.babelrc',
}));
const setup = ({ files }) => {
// eslint-disable-next-line no-underscore-dangle, global-require
require('fs').__setMockFiles(files);
};
describe('babel_config', () => {
// As the 'fs' is going to be mocked, let's call require.resolve
// so the require.cache has the correct route to the file.
// In fact let's use it in the tests :)
const babelPluginReactDocgenPath = require.resolve('babel-plugin-react-docgen');
it('should return the config with the extra plugins when `plugins` is an array.', () => {
setup({
files: {
'.babelrc': `{
"presets": [
"env",
"foo-preset"
],
"plugins": [
"foo-plugin"
]
}`,
},
});
const config = loadBabelConfig('.foo');
expect(config).toEqual({
babelrc: false,
plugins: [
'foo-plugin',
[
babelPluginReactDocgenPath,
{
DOC_GEN_COLLECTION_NAME: 'STORYBOOK_REACT_CLASSES',
},
],
],
presets: ['env', 'foo-preset'],
});
});
it('should return the config with the extra plugins when `plugins` is not an array.', () => {
setup({
files: {
'.babelrc': `{
"presets": [
"env",
"foo-preset"
],
"plugins": "bar-plugin"
}`,
},
});
const config = loadBabelConfig('.bar');
expect(config).toEqual({
babelrc: false,
plugins: [
'bar-plugin',
[
babelPluginReactDocgenPath,
{
DOC_GEN_COLLECTION_NAME: 'STORYBOOK_REACT_CLASSES',
},
],
],
presets: ['env', 'foo-preset'],
});
});
it('should return the config only with the extra plugins when `plugins` is not present.', () => {
// Mock a `.babelrc` config file with no plugins key.
setup({
files: {
'.babelrc': `{
"presets": [
"env",
"foo-preset"
]
}`,
},
});
const config = loadBabelConfig('.biz');
expect(config).toEqual({
babelrc: false,
plugins: [
[
babelPluginReactDocgenPath,
{
DOC_GEN_COLLECTION_NAME: 'STORYBOOK_REACT_CLASSES',
},
],
],
presets: ['env', 'foo-preset'],
});
});
});

83
app/polymer/src/server/build.js Executable file
View File

@ -0,0 +1,83 @@
import webpack from 'webpack';
import program from 'commander';
import path from 'path';
import fs from 'fs';
import chalk from 'chalk';
import shelljs from 'shelljs';
import { logger } from '@storybook/node-logger';
import packageJson from '../../package.json';
import getBaseConfig from './config/webpack.config.prod';
import loadConfig from './config';
import { parseList, getEnvConfig } from './utils';
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
program
.version(packageJson.version)
.option('-s, --static-dir <dir-names>', 'Directory where to load static files from', parseList)
.option('-o, --output-dir [dir-name]', 'Directory where to store built files')
.option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from')
.option('-d, --db-path [db-file]', 'DEPRECATED!')
.option('--enable-db', 'DEPRECATED!')
.parse(process.argv);
logger.info(chalk.bold(`${packageJson.name} v${packageJson.version}\n`));
if (program.enableDb || program.dbPath) {
logger.error(
[
'Error: the experimental local database addon is no longer bundled with',
'react-storybook. Please remove these flags (-d,--db-path,--enable-db)',
'from the command or npm script and try again.',
].join(' ')
);
process.exit(1);
}
// The key is the field created in `program` variable for
// each command line argument. Value is the env variable.
getEnvConfig(program, {
staticDir: 'SBCONFIG_STATIC_DIR',
outputDir: 'SBCONFIG_OUTPUT_DIR',
configDir: 'SBCONFIG_CONFIG_DIR',
});
const configDir = program.configDir || './.storybook';
const outputDir = program.outputDir || './storybook-static';
// create output directory if not exists
shelljs.mkdir('-p', path.resolve(outputDir));
// clear the static dir
shelljs.rm('-rf', path.resolve(outputDir, 'static'));
shelljs.cp(path.resolve(__dirname, 'public/favicon.ico'), outputDir);
// Build the webpack configuration using the `baseConfig`
// custom `.babelrc` file and `webpack.config.js` files
// NOTE changes to env should be done before calling `getBaseConfig`
const config = loadConfig('PRODUCTION', getBaseConfig(), configDir);
config.output.path = path.resolve(outputDir);
// copy all static files
if (program.staticDir) {
program.staticDir.forEach(dir => {
if (!fs.existsSync(dir)) {
logger.error(`Error: no such directory to load static files: ${dir}`);
process.exit(-1);
}
logger.log(`=> Copying static files from: ${dir}`);
shelljs.cp('-r', `${dir}/*`, outputDir);
});
}
// compile all resources with webpack and write them to the disk.
logger.log('Building storybook ...');
webpack(config).run((err, stats) => {
if (err || stats.hasErrors()) {
logger.error('Failed to build the storybook');
// eslint-disable-next-line no-unused-expressions
err && logger.error(err.message);
// eslint-disable-next-line no-unused-expressions
stats.hasErrors() && stats.toJson().errors.forEach(e => logger.error(e));
process.exit(1);
}
});

View File

@ -0,0 +1,86 @@
/* eslint-disable global-require, import/no-dynamic-require */
import fs from 'fs';
import path from 'path';
import findCacheDir from 'find-cache-dir';
import { logger } from '@storybook/node-logger';
import loadBabelConfig from './babel_config';
// `baseConfig` is a webpack configuration bundled with storybook.
// Storybook will look in the `configDir` directory
// (inside working directory) if a config path is not provided.
export default function(configType, baseConfig, configDir) {
const config = baseConfig;
const babelConfig = loadBabelConfig(configDir);
config.module.rules[0].query = {
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables a cache directory for faster-rebuilds
// `find-cache-dir` will create the cache directory under the node_modules directory.
cacheDirectory: findCacheDir({ name: 'react-storybook' }),
...babelConfig,
};
// Check whether a config.js file exists inside the storybook
// config directory and throw an error if it's not.
const storybookConfigPath = path.resolve(configDir, 'config.js');
if (!fs.existsSync(storybookConfigPath)) {
const err = new Error(`=> Create a storybook config file in "${configDir}/config.js".`);
throw err;
}
config.entry.preview.push(require.resolve(storybookConfigPath));
// Check whether addons.js file exists inside the storybook.
// Load the default addons.js file if it's missing.
// Insert it after polyfills.js, but before client/manager.
const storybookDefaultAddonsPath = path.resolve(__dirname, 'addons.js');
const storybookCustomAddonsPath = path.resolve(configDir, 'addons.js');
if (fs.existsSync(storybookCustomAddonsPath)) {
logger.info('=> Loading custom addons config.');
config.entry.manager.splice(1, 0, storybookCustomAddonsPath);
} else {
config.entry.manager.splice(1, 0, storybookDefaultAddonsPath);
}
// Check whether user has a custom webpack config file and
// return the (extended) base configuration if it's not available.
const customConfigPath = path.resolve(configDir, 'webpack.config.js');
if (!fs.existsSync(customConfigPath)) {
logger.info('=> Using default webpack setup based on "polymer-cli".');
const configPath = path.resolve(__dirname, './config/defaults/webpack.config.js');
const customConfig = require(configPath);
return customConfig(config);
}
const customConfig = require(customConfigPath);
if (typeof customConfig === 'function') {
logger.info('=> Loading custom webpack config (full-control mode).');
return customConfig(config, configType);
}
logger.info('=> Loading custom webpack config (extending mode).');
return {
...customConfig,
// We'll always load our configurations after the custom config.
// So, we'll always load the stuff we need.
...config,
// Override with custom devtool if provided
devtool: customConfig.devtool || config.devtool,
// We need to use our and custom plugins.
plugins: [...config.plugins, ...(customConfig.plugins || [])],
module: {
...config.module,
// We need to use our and custom rules.
...customConfig.module,
rules: [...config.module.rules, ...(customConfig.module.rules || [])],
},
resolve: {
...config.resolve,
...customConfig.resolve,
alias: {
...config.alias,
...(customConfig.resolve && customConfig.resolve.alias),
},
},
};
}

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
// @remove-on-eject-end
// This Webpack plugin ensures `npm install <library>` forces a project rebuild.
// Were not sure why this isn't Webpack's default behavior.
// See https://github.com/facebookincubator/create-react-app/issues/186.
function WatchMissingNodeModulesPlugin(nodeModulesPath) {
this.nodeModulesPath = nodeModulesPath;
}
WatchMissingNodeModulesPlugin.prototype.apply = function apply(compiler) {
compiler.plugin('emit', (compilation, callback) => {
const missingDeps = compilation.missingDependencies;
const { nodeModulesPath } = this;
// If any missing files are expected to appear in node_modules...
if (missingDeps.some(file => file.indexOf(nodeModulesPath) !== -1)) {
// ...tell webpack to watch node_modules recursively until they appear.
compilation.contextDependencies.push(nodeModulesPath);
}
callback();
});
};
module.exports = WatchMissingNodeModulesPlugin;

View File

@ -0,0 +1,28 @@
module.exports = {
// Don't try to find .babelrc because we want to force this configuration.
babelrc: false,
presets: [
[
require.resolve('babel-preset-env'),
{
targets: {
browsers: ['last 2 versions', 'safari >= 7'],
},
modules: process.env.NODE_ENV === 'test' ? 'commonjs' : false,
},
],
require.resolve('babel-preset-stage-0'),
require.resolve('babel-preset-react'),
],
plugins: [
require.resolve('babel-plugin-transform-regenerator'),
[
require.resolve('babel-plugin-transform-runtime'),
{
helpers: true,
polyfill: true,
regenerator: true,
},
],
],
};

View File

@ -0,0 +1,29 @@
module.exports = {
// Don't try to find .babelrc because we want to force this configuration.
babelrc: false,
presets: [
[
require.resolve('babel-preset-env'),
{
targets: {
browsers: ['last 2 versions', 'safari >= 7'],
},
modules: false,
},
],
require.resolve('babel-preset-stage-0'),
require.resolve('babel-preset-react'),
require.resolve('babel-preset-minify'),
],
plugins: [
require.resolve('babel-plugin-transform-regenerator'),
[
require.resolve('babel-plugin-transform-runtime'),
{
helpers: true,
polyfill: true,
regenerator: true,
},
],
],
};

View File

@ -0,0 +1,73 @@
// import webpack from 'webpack';
import autoprefixer from 'autoprefixer';
import { includePaths } from '../utils';
// Add a default custom config which is similar to what React Create App does.
module.exports = storybookBaseConfig => {
const newConfig = { ...storybookBaseConfig };
newConfig.module.rules = [
...storybookBaseConfig.module.rules,
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
plugins: () => [
require('postcss-flexbugs-fixes'), // eslint-disable-line
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
test: /\.json$/,
include: includePaths,
loader: require.resolve('json-loader'),
},
{
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/,
include: includePaths,
loader: require.resolve('file-loader'),
query: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
{
test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
include: includePaths,
loader: require.resolve('url-loader'),
query: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
];
newConfig.resolve.alias = {
...storybookBaseConfig.resolve.alias,
// This is to support NPM2
'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator'),
};
// Return the altered config
return newConfig;
};

View File

@ -0,0 +1,4 @@
/* globals window */
window.STORYBOOK_REACT_CLASSES = {};
window.STORYBOOK_ENV = 'polymer';

View File

@ -0,0 +1,4 @@
import 'core-js/es6/symbol';
import 'core-js/fn/array/iterator';
import 'airbnb-js-shims';
import 'babel-polyfill';

View File

@ -0,0 +1,37 @@
import path from 'path';
export const includePaths = [path.resolve('./')];
export const excludePaths = [path.resolve('node_modules')];
export const nodeModulesPaths = path.resolve('./node_modules');
export const nodePaths = (process.env.NODE_PATH || '')
.split(process.platform === 'win32' ? ';' : ':')
.filter(Boolean)
.map(p => path.resolve('./', p));
// Load environment variables starts with STORYBOOK_ to the client side.
export function loadEnv(options = {}) {
const defaultNodeEnv = options.production ? 'production' : 'development';
const env = {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || defaultNodeEnv),
// This is to support CRA's public folder feature.
// In production we set this to dot(.) to allow the browser to access these assests
// even when deployed inside a subpath. (like in GitHub pages)
// In development this is just empty as we always serves from the root.
PUBLIC_URL: JSON.stringify(options.production ? '.' : ''),
};
Object.keys(process.env)
.filter(name => /^STORYBOOK_/.test(name))
.forEach(name => {
env[name] = JSON.stringify(process.env[name]);
});
return {
'process.env': env,
};
}
export const getConfigDir = () => process.env.SBCONFIG_CONFIG_DIR || './.storybook';

View File

@ -0,0 +1,105 @@
import path from 'path';
import webpack from 'webpack';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import WatchMissingNodeModulesPlugin from './WatchMissingNodeModulesPlugin';
import {
getConfigDir,
includePaths,
excludePaths,
nodeModulesPaths,
loadEnv,
nodePaths,
} from './utils';
import { getPreviewHeadHtml, getManagerHeadHtml } from '../utils';
import babelLoaderConfig from './babel';
import { version } from '../../../package.json';
export default function() {
const config = {
devtool: 'cheap-module-source-map',
entry: {
manager: [require.resolve('./polyfills'), require.resolve('../../client/manager')],
preview: [
require.resolve('./polyfills'),
require.resolve('./globals'),
`${require.resolve('webpack-hot-middleware/client')}?reload=true`,
],
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'static/[name].bundle.js',
publicPath: '/',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
chunks: ['manager'],
data: {
managerHead: getManagerHeadHtml(getConfigDir()),
version,
},
template: require.resolve('../index.html.ejs'),
}),
new HtmlWebpackPlugin({
filename: 'iframe.html',
excludeChunks: ['manager'],
data: {
previewHead: getPreviewHeadHtml(getConfigDir()),
},
template: require.resolve('../iframe.html.ejs'),
}),
new CopyWebpackPlugin([
{ from: require.resolve('@webcomponents/webcomponentsjs/webcomponents-lite.js') },
{ from: require.resolve('@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js') },
]),
new webpack.DefinePlugin(loadEnv()),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(nodeModulesPaths),
new webpack.ProgressPlugin(),
],
module: {
rules: [
{
test: /\.jsx?$/,
loader: require.resolve('babel-loader'),
query: babelLoaderConfig,
include: includePaths,
exclude: excludePaths,
},
{
test: /\.html$/,
use: [
{
loader: require.resolve('babel-loader'),
query: babelLoaderConfig,
},
{
loader: require.resolve('polymer-webpack-loader'),
options: { processStyleLinks: true },
},
],
},
],
},
resolve: {
// Since we ship with json-loader always, it's better to move extensions to here
// from the default config.
extensions: ['.js', '.json', '.jsx'],
// Add support to NODE_PATH. With this we could avoid relative path imports.
// Based on this CRA feature: https://github.com/facebookincubator/create-react-app/issues/253
modules: ['node_modules'].concat(nodePaths),
alias: {
react$: require.resolve('react'),
'react-dom$': require.resolve('react-dom'),
},
},
performance: {
hints: false,
},
};
return config;
}

View File

@ -0,0 +1,103 @@
import path from 'path';
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import babelLoaderConfig from './babel.prod';
import { getConfigDir, includePaths, excludePaths, loadEnv, nodePaths } from './utils';
import { getPreviewHeadHtml, getManagerHeadHtml } from '../utils';
import { version } from '../../../package.json';
export default function() {
const entries = {
preview: [require.resolve('./polyfills'), require.resolve('./globals')],
manager: [require.resolve('./polyfills'), path.resolve(__dirname, '../../client/manager')],
};
const config = {
bail: true,
devtool: '#cheap-module-source-map',
entry: entries,
output: {
filename: 'static/[name].[chunkhash].bundle.js',
// Here we set the publicPath to ''.
// This allows us to deploy storybook into subpaths like GitHub pages.
// This works with css and image loaders too.
// This is working for storybook since, we don't use pushState urls and
// relative URLs works always.
publicPath: '',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
chunks: ['manager'],
data: {
managerHead: getManagerHeadHtml(getConfigDir()),
version,
},
template: require.resolve('../index.html.ejs'),
}),
new HtmlWebpackPlugin({
filename: 'iframe.html',
excludeChunks: ['manager'],
data: {
previewHead: getPreviewHeadHtml(getConfigDir()),
},
template: require.resolve('../iframe.html.ejs'),
}),
new CopyWebpackPlugin([
{ from: require.resolve('@webcomponents/webcomponentsjs/webcomponents-lite.js') },
{ from: require.resolve('@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js') },
]),
new webpack.DefinePlugin(loadEnv({ production: true })),
new webpack.optimize.UglifyJsPlugin({
compress: {
screw_ie8: true,
warnings: false,
},
mangle: false,
output: {
comments: false,
screw_ie8: true,
},
}),
],
module: {
rules: [
{
test: /\.jsx?$/,
loader: require.resolve('babel-loader'),
query: babelLoaderConfig,
include: includePaths,
exclude: excludePaths,
},
{
test: /\.html$/,
use: [
{
loader: require.resolve('babel-loader'),
query: babelLoaderConfig,
},
{
loader: require.resolve('polymer-webpack-loader'),
options: { processStyleLinks: true },
},
],
},
],
},
resolve: {
// Since we ship with json-loader always, it's better to move extensions to here
// from the default config.
extensions: ['.js', '.json', '.jsx'],
// Add support to NODE_PATH. With this we could avoid relative path imports.
// Based on this CRA feature: https://github.com/facebookincubator/create-react-app/issues/253
modules: ['node_modules'].concat(nodePaths),
alias: {
react$: require.resolve('react'),
'react-dom$': require.resolve('react-dom'),
},
},
};
return config;
}

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base target="_parent">
<title>Storybook</title>
<script src="custom-elements-es5-adapter.js"></script>
<script src="webcomponents-lite.js"></script>
<%= htmlWebpackPlugin.options.data.previewHead %>
</head>
<body>
<div id="root"></div>
<div id="error-display"></div>
</body>
</html>

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="storybook-version" content="<%= htmlWebpackPlugin.options.data.version %>">
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
<title>Storybook</title>
<style>
/*
When resizing panels, the drag event breaks if the cursor
moves over the iframe. Add the 'dragging' class to the body
at drag start and remove it when the drag ends.
*/
.dragging iframe {
pointer-events: none;
}
/* Styling the fuzzy search box placeholders */
.searchBox::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: #ddd;
font-size: 16px;
}
.searchBox::-moz-placeholder { /* Firefox 19+ */
color: #ddd;
font-size: 16px;
}
.searchBox:focus{
border-color: #EEE !important;
}
.btn:hover{
background-color: #eee
}
</style>
<%= htmlWebpackPlugin.options.data.managerHead %>
</head>
<body style="margin: 0;">
<div id="root"></div>
</body>
</html>

166
app/polymer/src/server/index.js Executable file
View File

@ -0,0 +1,166 @@
import express from 'express';
import https from 'https';
import favicon from 'serve-favicon';
import program from 'commander';
import path from 'path';
import fs from 'fs';
import chalk from 'chalk';
import shelljs from 'shelljs';
import { logger } from '@storybook/node-logger';
import storybook, { webpackValid } from './middleware';
import packageJson from '../../package.json';
import { parseList, getEnvConfig } from './utils';
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
program
.version(packageJson.version)
.option('-p, --port [number]', 'Port to run Storybook (Required)', str => parseInt(str, 10))
.option('-h, --host [string]', 'Host to run Storybook')
.option('-s, --static-dir <dir-names>', 'Directory where to load static files from')
.option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from')
.option(
'--https',
'Serve Storybook over HTTPS. Note: You must provide your own certificate information.'
)
.option(
'--ssl-ca <ca>',
'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)',
parseList
)
.option('--ssl-cert <cert>', 'Provide an SSL certificate. (Required with --https)')
.option('--ssl-key <key>', 'Provide an SSL key. (Required with --https)')
.option('--smoke-test', 'Exit after successful start')
.option('-d, --db-path [db-file]', 'DEPRECATED!')
.option('--enable-db', 'DEPRECATED!')
.parse(process.argv);
logger.info(chalk.bold(`${packageJson.name} v${packageJson.version}`) + chalk.reset('\n'));
if (program.enableDb || program.dbPath) {
logger.error(
[
'Error: the experimental local database addon is no longer bundled with',
'react-storybook. Please remove these flags (-d,--db-path,--enable-db)',
'from the command or npm script and try again.',
].join(' ')
);
process.exit(1);
}
// The key is the field created in `program` variable for
// each command line argument. Value is the env variable.
getEnvConfig(program, {
port: 'SBCONFIG_PORT',
host: 'SBCONFIG_HOSTNAME',
staticDir: 'SBCONFIG_STATIC_DIR',
configDir: 'SBCONFIG_CONFIG_DIR',
});
if (!program.port) {
logger.error('Error: port to run Storybook is required!\n');
program.help();
process.exit(-1);
}
// Used with `app.listen` below
const listenAddr = [program.port];
if (program.host) {
listenAddr.push(program.host);
}
const app = express();
let server = app;
if (program.https) {
if (!program.sslCert) {
logger.error('Error: --ssl-cert is required with --https');
process.exit(-1);
}
if (!program.sslKey) {
logger.error('Error: --ssl-key is required with --https');
process.exit(-1);
}
const sslOptions = {
ca: (program.sslCa || []).map(ca => fs.readFileSync(ca, 'utf-8')),
cert: fs.readFileSync(program.sslCert, 'utf-8'),
key: fs.readFileSync(program.sslKey, 'utf-8'),
};
server = https.createServer(sslOptions, app);
}
let hasCustomFavicon = false;
if (program.staticDir) {
program.staticDir = parseList(program.staticDir);
program.staticDir.forEach(dir => {
const staticPath = path.resolve(dir);
if (!fs.existsSync(staticPath)) {
logger.error(`Error: no such directory to load static files: ${staticPath}`);
process.exit(-1);
}
logger.log(`=> Loading static files from: ${staticPath} .`);
app.use(express.static(staticPath, { index: false }));
const faviconPath = path.resolve(staticPath, 'favicon.ico');
if (fs.existsSync(faviconPath)) {
hasCustomFavicon = true;
app.use(favicon(faviconPath));
}
});
}
if (!hasCustomFavicon) {
app.use(favicon(path.resolve(__dirname, 'public/favicon.ico')));
}
// Build the webpack configuration using the `baseConfig`
// custom `.babelrc` file and `webpack.config.js` files
const configDir = program.configDir || './.storybook';
// The repository info is sent to the storybook while running on
// development mode so it'll be easier for tools to integrate.
const exec = cmd => shelljs.exec(cmd, { silent: true }).stdout.trim();
process.env.STORYBOOK_GIT_ORIGIN =
process.env.STORYBOOK_GIT_ORIGIN || exec('git remote get-url origin');
process.env.STORYBOOK_GIT_BRANCH =
process.env.STORYBOOK_GIT_BRANCH || exec('git symbolic-ref HEAD --short');
// NOTE changes to env should be done before calling `getBaseConfig`
// `getBaseConfig` function which is called inside the middleware
app.use(storybook(configDir));
let serverResolve = () => {};
let serverReject = () => {};
const serverListening = new Promise((resolve, reject) => {
serverResolve = resolve;
serverReject = reject;
});
server.listen(...listenAddr, error => {
if (error) {
serverReject(error);
} else {
serverResolve();
}
});
Promise.all([webpackValid, serverListening])
.then(() => {
const proto = program.https ? 'https' : 'http';
const address = `${proto}://${program.host || 'localhost'}:${program.port}/`;
logger.info(`Storybook started on => ${chalk.cyan(address)}\n`);
if (program.smokeTest) {
process.exit(0);
}
})
.catch(error => {
if (error instanceof Error) {
logger.error(error);
}
if (program.smokeTest) {
process.exit(1);
}
});

View File

@ -0,0 +1,64 @@
import { Router } from 'express';
import webpack from 'webpack';
import path from 'path';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import getBaseConfig from './config/webpack.config';
import loadConfig from './config';
import { getMiddleware } from './utils';
let webpackResolve = () => {};
let webpackReject = () => {};
export const webpackValid = new Promise((resolve, reject) => {
webpackResolve = resolve;
webpackReject = reject;
});
export default function(configDir) {
// Build the webpack configuration using the `getBaseConfig`
// custom `.babelrc` file and `webpack.config.js` files
const config = loadConfig('DEVELOPMENT', getBaseConfig(), configDir);
const middlewareFn = getMiddleware(configDir);
// remove the leading '/'
let { publicPath } = config.output;
if (publicPath[0] === '/') {
publicPath = publicPath.slice(1);
}
const compiler = webpack(config);
const devMiddlewareOptions = {
noInfo: true,
publicPath: config.output.publicPath,
watchOptions: config.watchOptions || {},
...config.devServer,
};
const router = new Router();
const webpackDevMiddlewareInstance = webpackDevMiddleware(compiler, devMiddlewareOptions);
router.use(webpackDevMiddlewareInstance);
router.use(webpackHotMiddleware(compiler));
// custom middleware
middlewareFn(router);
webpackDevMiddlewareInstance.waitUntilValid(stats => {
router.get('/', (req, res) => {
res.set('Content-Type', 'text/html');
res.sendFile(path.join(`${__dirname}/public/index.html`));
});
router.get('/iframe.html', (req, res) => {
res.set('Content-Type', 'text/html');
res.sendFile(path.join(`${__dirname}/public/iframe.html`));
});
if (stats.toJson().errors.length) {
webpackReject(stats);
} else {
webpackResolve(stats);
}
});
return router;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,56 @@
import path from 'path';
import fs from 'fs';
import deprecate from 'util-deprecate';
const fallbackHeadUsage = deprecate(() => {},
'Usage of head.html has been deprecated. Please rename head.html to preview-head.html');
export function parseList(str) {
return str.split(',');
}
export function getPreviewHeadHtml(configDirPath) {
const headHtmlPath = path.resolve(configDirPath, 'preview-head.html');
const fallbackHtmlPath = path.resolve(configDirPath, 'head.html');
let headHtml = '';
if (fs.existsSync(headHtmlPath)) {
headHtml = fs.readFileSync(headHtmlPath, 'utf8');
} else if (fs.existsSync(fallbackHtmlPath)) {
headHtml = fs.readFileSync(fallbackHtmlPath, 'utf8');
fallbackHeadUsage();
}
return headHtml;
}
export function getManagerHeadHtml(configDirPath) {
const scriptPath = path.resolve(configDirPath, 'manager-head.html');
let scriptHtml = '';
if (fs.existsSync(scriptPath)) {
scriptHtml = fs.readFileSync(scriptPath, 'utf8');
}
return scriptHtml;
}
export function getEnvConfig(program, configEnv) {
Object.keys(configEnv).forEach(fieldName => {
const envVarName = configEnv[fieldName];
const envVarValue = process.env[envVarName];
if (envVarValue) {
program[fieldName] = envVarValue; // eslint-disable-line
}
});
}
export function getMiddleware(configDir) {
const middlewarePath = path.resolve(configDir, 'middleware.js');
if (fs.existsSync(middlewarePath)) {
let middlewareModule = require(middlewarePath); // eslint-disable-line
if (middlewareModule.__esModule) { // eslint-disable-line
middlewareModule = middlewareModule.default;
}
return middlewareModule;
}
return () => {};
}

View File

@ -0,0 +1,69 @@
import { getPreviewHeadHtml, getManagerHeadHtml } from './utils';
// eslint-disable-next-line global-require
jest.mock('fs', () => require('../../../../__mocks__/fs'));
jest.mock('path', () => ({
resolve: (a, p) => p,
}));
const setup = ({ files }) => {
// eslint-disable-next-line no-underscore-dangle, global-require
require('fs').__setMockFiles(files);
};
const HEAD_HTML_CONTENTS = 'UNITTEST_HEAD_HTML_CONTENTS';
describe('getPreviewHeadHtml', () => {
it('returns an empty string without head.html present', () => {
setup({
files: {},
});
const result = getPreviewHeadHtml('first');
expect(result).toEqual('');
});
it('return contents of head.html when present', () => {
setup({
files: {
'head.html': HEAD_HTML_CONTENTS,
},
});
const result = getPreviewHeadHtml('second');
expect(result).toEqual(HEAD_HTML_CONTENTS);
});
it('returns contents of preview-head.html when present', () => {
setup({
files: {
'preview-head.html': HEAD_HTML_CONTENTS,
},
});
const result = getPreviewHeadHtml('second');
expect(result).toEqual(HEAD_HTML_CONTENTS);
});
});
describe('getManagerHeadHtml', () => {
it('returns an empty string without manager-head.html present', () => {
setup({
files: {},
});
const result = getManagerHeadHtml('first');
expect(result).toEqual('');
});
it('returns contents of manager-head.html when present', () => {
setup({
files: {
'manager-head.html': HEAD_HTML_CONTENTS,
},
});
const result = getManagerHeadHtml('second');
expect(result).toEqual(HEAD_HTML_CONTENTS);
});
});

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/react-native",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "A better way to develop React Native Components for your app",
"keywords": [
"react",
@ -25,13 +25,13 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/channel-websocket": "^3.4.0-alpha.1",
"@storybook/core": "^3.4.0-alpha.1",
"@storybook/ui": "^3.4.0-alpha.1",
"autoprefixer": "^7.2.4",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/channel-websocket": "^3.4.0-alpha.4",
"@storybook/core": "^3.4.0-alpha.4",
"@storybook/ui": "^3.4.0-alpha.4",
"autoprefixer": "^7.2.5",
"babel-loader": "^7.1.2",
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-syntax-trailing-function-commas": "^6.22.0",
@ -60,7 +60,7 @@
"prop-types": "^15.6.0",
"react-native-compat": "^1.0.0",
"react-native-iphone-x-helper": "^1.0.1",
"shelljs": "^0.7.8",
"shelljs": "^0.8.0",
"style-loader": "^0.19.1",
"uglifyjs-webpack-plugin": "^1.1.6",
"url-loader": "^0.6.2",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/react",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
"homepage": "https://github.com/storybooks/storybook/tree/master/app/react",
"bugs": {
@ -23,16 +23,16 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/channel-postmessage": "^3.4.0-alpha.1",
"@storybook/client-logger": "^3.4.0-alpha.1",
"@storybook/core": "^3.4.0-alpha.1",
"@storybook/node-logger": "^3.4.0-alpha.1",
"@storybook/ui": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/channel-postmessage": "^3.4.0-alpha.4",
"@storybook/client-logger": "^3.4.0-alpha.4",
"@storybook/core": "^3.4.0-alpha.4",
"@storybook/node-logger": "^3.4.0-alpha.4",
"@storybook/ui": "^3.4.0-alpha.4",
"airbnb-js-shims": "^1.4.0",
"autoprefixer": "^7.2.4",
"autoprefixer": "^7.2.5",
"babel-loader": "^7.1.2",
"babel-plugin-react-docgen": "^1.8.0",
"babel-plugin-transform-regenerator": "^6.26.0",
@ -72,7 +72,7 @@
"redux": "^3.7.2",
"request": "^2.83.0",
"serve-favicon": "^2.4.5",
"shelljs": "^0.7.8",
"shelljs": "^0.8.0",
"style-loader": "^0.19.1",
"uglifyjs-webpack-plugin": "^1.1.6",
"url-loader": "^0.6.2",

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/vue",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook for Vue: Develop Vue Component in isolation with Hot Reloading.",
"homepage": "https://github.com/storybooks/storybook/tree/master/apps/vue",
"bugs": {
@ -23,14 +23,14 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/channel-postmessage": "^3.4.0-alpha.1",
"@storybook/core": "^3.4.0-alpha.1",
"@storybook/ui": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/channel-postmessage": "^3.4.0-alpha.4",
"@storybook/core": "^3.4.0-alpha.4",
"@storybook/ui": "^3.4.0-alpha.4",
"airbnb-js-shims": "^1.4.0",
"autoprefixer": "^7.2.4",
"autoprefixer": "^7.2.5",
"babel-loader": "^7.1.2",
"babel-plugin-react-docgen": "^1.8.0",
"babel-plugin-transform-regenerator": "^6.26.0",
@ -68,7 +68,7 @@
"redux": "^3.7.2",
"request": "^2.83.0",
"serve-favicon": "^2.4.5",
"shelljs": "^0.7.8",
"shelljs": "^0.8.0",
"style-loader": "^0.19.1",
"uglifyjs-webpack-plugin": "^1.1.6",
"url-loader": "^0.6.2",

View File

@ -18,10 +18,10 @@
"storybook": "start-storybook -p 9009 -s src/pages"
},
"dependencies": {
"@storybook/addon-actions": "^3.3.8",
"@storybook/addon-links": "^3.3.8",
"@storybook/addons": "^3.3.8",
"@storybook/react": "^3.3.8",
"@storybook/addon-actions": "^3.3.9",
"@storybook/addon-links": "^3.3.9",
"@storybook/addons": "^3.3.9",
"@storybook/react": "^3.3.9",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^6.4.1",
@ -31,7 +31,7 @@
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"bootstrap": "^3.3.7",
"gatsby": "^1.9.153",
"gatsby": "^1.9.155",
"gatsby-link": "^1.6.34",
"gatsby-plugin-sharp": "^1.6.24",
"gatsby-remark-autolink-headers": "^1.4.11",

View File

@ -27,4 +27,6 @@ Just like that, you can access all of the stories in your Storybook.
It will be hard to use all the frameworks we've [mentioned](/testing/react-ui-testing#3-css-style-testing), but we'll be able to use frameworks which are based on URL as the input source. (Such as [BackstopJS](https://github.com/garris/BackstopJS) and [Gemini](https://github.com/gemini-testing/gemini))
- [Loki](https://loki.js.org/): Is a great tool for visual regression testing.
> In the future we are also planning to smooth this process with the help of [StoryShots](https://github.com/storybooks/storybook/tree/master/addons/storyshots).

View File

@ -2,9 +2,9 @@
# yarn lockfile v1
"@storybook/addon-actions@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-3.3.8.tgz#7efa3d639b35f5b7540ed5befd2fbd80bc49e821"
"@storybook/addon-actions@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-3.3.9.tgz#2b191548928467fe1dd26dcba606feafbf182d36"
dependencies:
deep-equal "^1.0.1"
global "^4.3.2"
@ -13,37 +13,37 @@
react-inspector "^2.2.2"
uuid "^3.1.0"
"@storybook/addon-links@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-3.3.8.tgz#d760952951c1f51eef280ceb091505d7af84bfb6"
"@storybook/addon-links@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-3.3.9.tgz#13781ac1c21ddfe347ece6ceab8518c8d1f98a0f"
dependencies:
"@storybook/components" "^3.3.8"
"@storybook/components" "^3.3.9"
global "^4.3.2"
prop-types "^15.5.10"
"@storybook/addons@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-3.3.8.tgz#2e36fdc0c03fb6eb9d2245fea1311ee7aaafbf0e"
"@storybook/addons@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-3.3.9.tgz#356ce7f1de892d88ca4bc5f686d06e07dd8c2108"
"@storybook/channel-postmessage@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-3.3.8.tgz#249a25e6f8c1c59e229ecec71a545c8127d59ab8"
"@storybook/channel-postmessage@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-3.3.9.tgz#a59220f9ecbdbe05deac6ac4339715aa587d41dd"
dependencies:
"@storybook/channels" "^3.3.8"
"@storybook/channels" "^3.3.9"
global "^4.3.2"
json-stringify-safe "^5.0.1"
"@storybook/channels@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-3.3.8.tgz#3989a77c57ae6bf29bc2dcd9a82f364225f595ba"
"@storybook/channels@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-3.3.9.tgz#3116a6c5e441fd057558870b254c34fe3a9fbfb0"
"@storybook/client-logger@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-3.3.8.tgz#58fc42e31ba10fc54380b324fbb8a16c76370398"
"@storybook/client-logger@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-3.3.9.tgz#a73e382c383c1bfa6d2ff7fa5cae77cd09efa524"
"@storybook/components@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/components/-/components-3.3.8.tgz#850737561c1d97cfba003ed060db8f0cdf448c94"
"@storybook/components@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/components/-/components-3.3.9.tgz#1f7ced8b10a0e405c1d3fd6fe7ef7b8957ddf89f"
dependencies:
glamor "^2.20.40"
glamorous "^4.11.2"
@ -57,9 +57,9 @@
"@storybook/react-simple-di" "^1.2.1"
babel-runtime "6.x.x"
"@storybook/node-logger@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-3.3.8.tgz#b528bebb5d74156cf51e2c6424ba6da653adefe2"
"@storybook/node-logger@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-3.3.9.tgz#c070ef5ced91b1b1aa7bb3e402855db277ed426b"
dependencies:
chalk "^2.3.0"
npmlog "^4.1.2"
@ -87,17 +87,17 @@
dependencies:
babel-runtime "^6.5.0"
"@storybook/react@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/react/-/react-3.3.8.tgz#c7d3d4bb20d5ed281f73b118ccb2a22cd91eb0e8"
"@storybook/react@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/react/-/react-3.3.9.tgz#2bd203a5b3c5e5fad4a756ca41d78e62cd49b160"
dependencies:
"@storybook/addon-actions" "^3.3.8"
"@storybook/addon-links" "^3.3.8"
"@storybook/addons" "^3.3.8"
"@storybook/channel-postmessage" "^3.3.8"
"@storybook/client-logger" "^3.3.8"
"@storybook/node-logger" "^3.3.8"
"@storybook/ui" "^3.3.8"
"@storybook/addon-actions" "^3.3.9"
"@storybook/addon-links" "^3.3.9"
"@storybook/addons" "^3.3.9"
"@storybook/channel-postmessage" "^3.3.9"
"@storybook/client-logger" "^3.3.9"
"@storybook/node-logger" "^3.3.9"
"@storybook/ui" "^3.3.9"
airbnb-js-shims "^1.4.0"
autoprefixer "^7.2.3"
babel-loader "^7.1.2"
@ -149,11 +149,11 @@
webpack-dev-middleware "^1.12.2"
webpack-hot-middleware "^2.21.0"
"@storybook/ui@^3.3.8":
version "3.3.8"
resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-3.3.8.tgz#fc9e9f3da3d988da8b6e07f78e1f6db0a5c6e1dd"
"@storybook/ui@^3.3.9":
version "3.3.9"
resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-3.3.9.tgz#abb1df557131b174bf3c0879863a309ee85de8e3"
dependencies:
"@storybook/components" "^3.3.8"
"@storybook/components" "^3.3.9"
"@storybook/mantra-core" "^1.7.2"
"@storybook/react-komposer" "^2.0.3"
babel-runtime "^6.26.0"
@ -4379,9 +4379,9 @@ gatsby-plugin-sharp@^1.6.24:
sharp "^0.17.3"
svgo "^0.7.2"
gatsby-react-router-scroll@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/gatsby-react-router-scroll/-/gatsby-react-router-scroll-1.0.7.tgz#50be2d6d3857625eb087c14f2a6789672fd73219"
gatsby-react-router-scroll@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/gatsby-react-router-scroll/-/gatsby-react-router-scroll-1.0.8.tgz#6cc9d80c139e58ed5189dd35146ac37b46846cd5"
dependencies:
babel-runtime "^6.26.0"
scroll-behavior "^0.9.1"
@ -4468,9 +4468,9 @@ gatsby-transformer-remark@^1.7.28:
unist-util-select "^1.5.0"
unist-util-visit "^1.1.1"
gatsby@^1.9.153:
version "1.9.153"
resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-1.9.153.tgz#5a435d2e75ee5a714ed5ea934b44a574d1bf0487"
gatsby@^1.9.155:
version "1.9.155"
resolved "https://registry.yarnpkg.com/gatsby/-/gatsby-1.9.155.tgz#49fe4063fa2d19279f90b4a1019dcf20ce94d08a"
dependencies:
async "^2.1.2"
babel-code-frame "^6.22.0"
@ -4513,7 +4513,7 @@ gatsby@^1.9.153:
gatsby-cli "^1.1.28"
gatsby-link "^1.6.34"
gatsby-module-loader "^1.0.9"
gatsby-react-router-scroll "^1.0.7"
gatsby-react-router-scroll "^1.0.8"
glob "^7.1.1"
graphql "^0.11.7"
graphql-relay "^0.5.1"

View File

@ -1,6 +1,6 @@
{
"name": "angular-cli",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"license": "MIT",
"scripts": {
"ng": "ng",
@ -30,12 +30,12 @@
"@angular/cli": "1.6.4",
"@angular/compiler-cli": "^5.1.3",
"@angular/language-service": "^5.1.3",
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addon-notes": "^3.4.0-alpha.1",
"@storybook/addon-storyshots": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/angular": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addon-notes": "^3.4.0-alpha.4",
"@storybook/addon-storyshots": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/angular": "^3.4.0-alpha.4",
"@types/jasmine": "~2.8.3",
"@types/node": "~6.0.96",
"global": "^4.3.2",
@ -52,4 +52,3 @@
"typescript": "^2.4.0"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "cra-kitchen-sink",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"scripts": {
"build": "react-scripts build",
"build-storybook": "build-storybook -s public",
@ -18,23 +18,23 @@
"react-dom": "^16.2.0"
},
"devDependencies": {
"@storybook/addon-a11y": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-backgrounds": "^3.4.0-alpha.1",
"@storybook/addon-centered": "^3.4.0-alpha.1",
"@storybook/addon-events": "^3.4.0-alpha.1",
"@storybook/addon-info": "^3.4.0-alpha.1",
"@storybook/addon-jest": "^3.4.0-alpha.1",
"@storybook/addon-knobs": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addon-notes": "^3.4.0-alpha.1",
"@storybook/addon-options": "^3.4.0-alpha.1",
"@storybook/addon-storyshots": "^3.4.0-alpha.1",
"@storybook/addon-viewport": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/client-logger": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/react": "^3.4.0-alpha.1",
"@storybook/addon-a11y": "^3.4.0-alpha.4",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-backgrounds": "^3.4.0-alpha.4",
"@storybook/addon-centered": "^3.4.0-alpha.4",
"@storybook/addon-events": "^3.4.0-alpha.4",
"@storybook/addon-info": "^3.4.0-alpha.4",
"@storybook/addon-jest": "^3.4.0-alpha.4",
"@storybook/addon-knobs": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addon-notes": "^3.4.0-alpha.4",
"@storybook/addon-options": "^3.4.0-alpha.4",
"@storybook/addon-storyshots": "^3.4.0-alpha.4",
"@storybook/addon-viewport": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/client-logger": "^3.4.0-alpha.4",
"@storybook/components": "^3.4.0-alpha.4",
"@storybook/react": "^3.4.0-alpha.4",
"babel-jest": "^22.0.6",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.0",

View File

@ -0,0 +1,22 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class DelayedRender extends Component {
static propTypes = {
children: PropTypes.node.isRequired,
};
state = {
show: false,
};
componentDidMount() {
setTimeout(() => {
this.setState({
show: true,
});
}, 1000);
}
render() {
return this.state.show ? this.props.children : <div />;
}
}

View File

@ -1,6 +1,6 @@
{
"name": "official-storybook",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"scripts": {
"build-storybook": "build-storybook -c ./",
"storybook": "start-storybook -p 9010 -c ./",
@ -9,22 +9,22 @@
"image-snapshots": "yarn run build-storybook && jest --projects=./image-snapshots"
},
"devDependencies": {
"@storybook/addon-a11y": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-backgrounds": "^3.4.0-alpha.1",
"@storybook/addon-centered": "^3.4.0-alpha.1",
"@storybook/addon-events": "^3.4.0-alpha.1",
"@storybook/addon-info": "^3.4.0-alpha.1",
"@storybook/addon-jest": "^3.4.0-alpha.1",
"@storybook/addon-knobs": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addon-notes": "^3.4.0-alpha.1",
"@storybook/addon-options": "^3.4.0-alpha.1",
"@storybook/addon-storyshots": "^3.4.0-alpha.1",
"@storybook/addon-viewport": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/components": "^3.4.0-alpha.1",
"@storybook/react": "^3.4.0-alpha.1",
"@storybook/addon-a11y": "^3.4.0-alpha.4",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-backgrounds": "^3.4.0-alpha.4",
"@storybook/addon-centered": "^3.4.0-alpha.4",
"@storybook/addon-events": "^3.4.0-alpha.4",
"@storybook/addon-info": "^3.4.0-alpha.4",
"@storybook/addon-jest": "^3.4.0-alpha.4",
"@storybook/addon-knobs": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addon-notes": "^3.4.0-alpha.4",
"@storybook/addon-options": "^3.4.0-alpha.4",
"@storybook/addon-storyshots": "^3.4.0-alpha.4",
"@storybook/addon-viewport": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/components": "^3.4.0-alpha.4",
"@storybook/react": "^3.4.0-alpha.4",
"babel-jest": "^21.2.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.0",

View File

@ -23,3 +23,5 @@ exports[`Storyshots Addons|a11y Label 1`] = `
Testing the a11y addon
</button>
`;
exports[`Storyshots Addons|a11y delayed render 1`] = `<div />`;

View File

@ -2,7 +2,7 @@
exports[`Storyshots Addons|Backgrounds story 1 1`] = `
<div
style="overflow:scroll;position:fixed;top:0;bottom:0;right:0;left:0;transition:background 0.25s ease-in-out;background-position:center;background-size:cover;background:transparent"
style="overflow:auto;position:fixed;top:0;bottom:0;right:0;left:0;transition:background 0.25s ease-in-out;background-position:center;background-size:cover;background:transparent"
>
<button>
You should be able to switch backgrounds for this story
@ -12,7 +12,7 @@ exports[`Storyshots Addons|Backgrounds story 1 1`] = `
exports[`Storyshots Addons|Backgrounds story 2 1`] = `
<div
style="overflow:scroll;position:fixed;top:0;bottom:0;right:0;left:0;transition:background 0.25s ease-in-out;background-position:center;background-size:cover;background:transparent"
style="overflow:auto;position:fixed;top:0;bottom:0;right:0;left:0;transition:background 0.25s ease-in-out;background-position:center;background-size:cover;background:transparent"
>
<button>
This one too!

View File

@ -1,17 +1,28 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { setOptions } from '@storybook/addon-options';
import { checkA11y } from '@storybook/addon-a11y';
import BaseButton from '../components/BaseButton';
import DelayedRender from '../components/DelayedRender';
const text = 'Testing the a11y addon';
storiesOf('Addons|a11y', module)
.addDecorator(checkA11y)
.addDecorator(fn => {
setOptions({ selectedAddonPanel: '@storybook/addon-a11y/panel' });
return fn();
})
.add('Default', () => <BaseButton label="" />)
.add('Label', () => <BaseButton label={text} />)
.add('Disabled', () => <BaseButton disabled label={text} />)
.add('Invalid contrast', () => (
// FIXME has no effect on score
<BaseButton style={{ color: 'black', backgroundColor: 'black' }} label={text} />
))
.add('delayed render', () => (
<DelayedRender>
<BaseButton label="This button has a delayed render of 1s" />
</DelayedRender>
));

View File

@ -0,0 +1,7 @@
module.exports = {
globals: {
Polymer: true,
customElements: true,
CustomEvent: true,
},
};

View File

@ -0,0 +1,4 @@
import '@storybook/addon-actions/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-viewport/register';

View File

@ -0,0 +1,10 @@
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions */
import { configure } from '@storybook/polymer';
function loadStories() {
require('../src/stories/index.stories');
require('../src/stories/advanced.stories');
}
configure(loadStories, module);

View File

@ -0,0 +1,8 @@
# Polymer kitchen sink example
This project was generated with [Polymer CLI](https://github.com/Polymer/polymer-cli) version 1.5.2.
## Development server
Run `yarn start` for a dev server. Navigate to `http://127.0.0.1:8081/components/polymer-cli/`.
The app will automatically reload if you change any of the source files.

View File

@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<base href="/">
<title>Storybook for Polymer!</title>
<script src="webcomponents-loader.js"></script>
<script src="custom-elements-es5-adapter.js"></script>
</head>
<body>
<polymer-playground-app title="Polymer playground app"}></polymer-playground-app>
</body>
</html>

View File

@ -0,0 +1,31 @@
{
"name": "polymer-cli",
"version": "3.4.0-alpha.4",
"scripts": {
"start": "webpack-dev-server",
"storybook": "start-storybook -p 9001 -c .storybook"
},
"private": true,
"dependencies": {
"@polymer/polymer": "^2.2.0",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-knobs": "^3.4.0-alpha.4",
"@storybook/addon-notes": "^3.4.0-alpha.4",
"@storybook/addon-viewport": "^3.4.0-alpha.4",
"@storybook/polymer": "^3.4.0-alpha.4",
"@webcomponents/webcomponentsjs": "^1.0.17",
"global": "^4.3.2",
"polymer-webpack-loader": "^2.0.0",
"webpack": "^3.8.1"
},
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-2": "^6.24.1",
"copy-webpack-plugin": "^4.2.0",
"html-webpack-plugin": "^2.30.1",
"webpack-dev-server": "^2.9.4"
}
}

View File

@ -0,0 +1 @@
<svg width="256" height="178" viewBox="0 0 256 178" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><g fill="none"><path d="M153.6 177.98L51.194.605H102.4L204.807 177.98H153.6z" fill="#FF4081"/><path d="M153.6 177.98l25.6-44.344 25.607 44.344H153.6z" fill-opacity=".2" fill="#FFF"/><path d="M128 133.636l25.6 44.344 25.6-44.344H128z" fill-opacity=".1" fill="#FFF"/><path d="M102.4 89.292l25.6 44.344 25.6-44.344h-51.2z" fill-opacity=".1" fill="#000"/><path d="M102.4 89.292L128 44.948l25.6 44.344h-51.2z" fill-opacity=".2" fill="#000"/><path d="M76.8 44.948l25.6 44.344 25.601-44.344h-51.2z" fill-opacity=".3" fill="#000"/><path d="M76.8 44.948L102.4.605l25.601 44.343h-51.2z" fill-opacity=".4" fill="#000"/><path d="M51.194.605L76.8 44.948 102.4.605H51.195z" fill-opacity=".5" fill="#000"/><path d="M51.194 177.98L-.013 89.292l25.606-44.344L102.4 177.98H51.193z" fill="#536DFE"/><path d="M51.194 177.98L76.8 133.636l25.6 44.344H51.195z" fill-opacity=".2" fill="#FFF"/><path d="M25.593 133.636l25.6 44.344L76.8 133.636H25.593z" fill-opacity=".1" fill="#FFF"/><path d="M25.593 133.636l25.6-44.344L76.8 133.636H25.593z"/><path d="M-.013 89.292l25.606 44.344 25.6-44.344H-.012z" fill-opacity=".1" fill="#000"/><path d="M-.013 89.292l25.606-44.344 25.6 44.344H-.012z" fill-opacity=".2" fill="#000"/><path d="M51.194 89.292l-25.6-44.344L51.193.605 76.8 44.948 51.194 89.292z" fill="#303F9F"/><path d="M76.8 44.948L51.194.605l-25.6 44.343H76.8z" fill-opacity=".2" fill="#000"/><path d="M204.806 177.98L179.2 133.636l25.606-44.344 25.6 44.344-25.6 44.344z" fill="#3F51B5"/><path d="M230.407 133.636l-25.6 44.344-25.607-44.344h51.207z" fill-opacity=".2" fill="#000"/><path d="M230.407 133.636L153.6.605h51.207l51.207 88.687-25.606 44.344h-.001z" fill="#7986CB"/><path d="M204.806 89.292l25.6 44.344 25.607-44.344h-51.207z" fill-opacity=".2" fill="#FFF"/><path d="M204.806 89.292l25.6-44.344 25.607 44.344h-51.207z" fill-opacity=".1" fill="#FFF"/><path d="M179.2 44.948L204.806.605l25.6 44.343H179.2z" fill-opacity=".1" fill="#000"/><path d="M153.6.605l25.6 44.343L204.808.605H153.6z" fill-opacity=".2" fill="#000"/></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,50 @@
<link rel="import" href="../../../node_modules/@polymer/polymer/polymer-element.html">
<dom-module id="playground-button">
<template>
<style>
.square {
border: 1px solid black;
}
</style>
<button on-click="handleTap"
class$="[[computedClass]]">
[[title]] [[counter]]
</button>
</template>
<script>
class PlaygroundButton extends Polymer.Element {
static get is() { return 'playground-button'; }
static get properties() {
return {
title: {
type: String,
value: 'Click me:',
},
counter: {
type: Number,
value: 0
},
isSquare: {
type: Boolean,
value: false
},
computedClass: {
type: String,
computed: '_computeClass(isSquare)'
}
};
}
handleTap() {
this.counter += 1;
}
_computeClass(isSquare) {
return isSquare && 'square';
}
}
customElements.define(PlaygroundButton.is, PlaygroundButton);
</script>
</dom-module>

View File

@ -0,0 +1,26 @@
<link rel="import" href="../../../node_modules/@polymer/polymer/polymer-element.html">
<link rel="import" href="playground-button.html">
<dom-module id="polymer-playground-app">
<template>
<h2>[[title]]</h2>
<p>Hello [[prop1]]!</p>
<playground-button></playground-button>
</template>
<script>
class PolymerPlaygroundApp extends Polymer.Element {
static get is() { return 'polymer-playground-app'; }
static get properties() {
return {
prop1: {
type: String,
value: 'polymer-playground-app'
},
title: String,
};
}
}
customElements.define(PolymerPlaygroundApp.is, PolymerPlaygroundApp);
</script>
</dom-module>

View File

@ -0,0 +1,17 @@
<link rel="import" href="../../../../node_modules/@polymer/polymer/polymer-element.html">
<dom-module id="separated-button">
<template>
<button on-click="handleTap">
[[title]] [[counter]]
</button>
</template>
<script>
import { separatedButton } from './separated-button';
class PlaygroundButton extends separatedButton(Polymer.Element) {
}
customElements.define(PlaygroundButton.is, PlaygroundButton);
</script>
</dom-module>

View File

@ -0,0 +1,26 @@
import { uselessMixin } from './useless-mixin';
export const separatedButton = superClass =>
class SeparatedButton extends uselessMixin(superClass) {
static get is() {
return 'separated-button';
}
static get properties() {
return {
title: {
type: String,
value: 'Click me:',
},
counter: {
type: Number,
value: 0,
},
};
}
async handleTap() {
this.counter += await Promise.resolve(1);
this.someMethod();
}
};

View File

@ -0,0 +1,12 @@
export const uselessMixin = superClass =>
class UselessMixin extends superClass {
constructor() {
super();
this.eventType = 'test';
}
someMethod() {
this.dispatchEvent(new CustomEvent(this.eventType, { detail: 'test' }));
}
};

View File

@ -0,0 +1,104 @@
import { storiesOf } from '@storybook/polymer';
import { action } from '@storybook/addon-actions';
import { withNotes } from '@storybook/addon-notes';
import {
withKnobs,
text,
button,
number,
select,
date,
color,
array,
boolean,
} from '@storybook/addon-knobs/polymer';
import { document } from 'global';
import '../polymer-playground-app.html';
import '../playground-button.html';
import '../separated-button/separated-button.html';
import './storybook-welcome-to-polymer.html';
storiesOf('Advanced/Decorator', module)
.addDecorator(story => {
const el = story();
el.setAttribute('title', `${el.getAttribute('title')} - decorated`);
return el;
})
.add('example decoration', () => {
const el = document.createElement('playground-button');
el.setAttribute('title', 'An example title');
return el;
});
storiesOf('Advanced/Addon Actions', module)
.add('Action only', () => {
const el = document.createElement('playground-button');
el.addEventListener('click', action('log1'));
return el;
})
.add('Action and method', () => {
const el = document.createElement('playground-button');
el.addEventListener('click', e => action('log2')(e.target));
return el;
});
storiesOf('Advanced/Addon Notes', module)
.add(
'Simple note',
withNotes({ text: 'My notes on some bold text' })(
() =>
'<p><strong>Etiam vulputate elit eu venenatis eleifend. Duis nec lectus augue. Morbi egestas diam sed vulputate mollis. Fusce egestas pretium vehicula. Integer sed neque diam. Donec consectetur velit vitae enim varius, ut placerat arcu imperdiet. Praesent sed faucibus arcu. Nullam sit amet nibh a enim eleifend rhoncus. Donec pretium elementum leo at fermentum. Nulla sollicitudin, mauris quis semper tempus, sem metus tristique diam, efficitur pulvinar mi urna id urna.</strong></p>'
)
)
.add(
'Note with HTML',
withNotes({
text: `
<h2>My notes on emojies</h2>
<em>It's not all that important to be honest, but..</em>
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
`,
})(() => '<p>🤔😳😯😮<br/>😄😩😓😱<br/>🤓😑😶😊</p>')
);
storiesOf('Advanced/Addon Knobs', module)
.addDecorator(withKnobs)
.add('simple', () => {
const title = text('Button title', 'Hello');
const el = document.createElement('playground-button');
el.setAttribute('title', title);
button('callback', () => el.setAttribute('title', 'testing'));
return el;
})
.add('complex', () => {
const name = text('Name', 'Jane');
const stock = number('Stock', 20, { range: true, min: 0, max: 30, step: 5 });
const fruits = { apples: 'Apple', bananas: 'Banana', cherries: 'Cherry' };
const fruit = select('Fruit', fruits, 'apple');
const price = number('Price', 2.25);
const colour = color('Border', 'deeppink');
const today = date('Today', new Date('Jan 20 2017'));
const items = array('Items', ['Laptop', 'Book', 'Whiskey']);
const nice = boolean('Nice', true);
const stockMessage = stock
? `I have a stock of ${stock} ${fruit}, costing &dollar;${price} each.`
: `I'm out of ${fruit}${nice ? ', Sorry!' : '.'}`;
button('Arbitrary action', action('You clicked it!'));
return `
<div style="border:2px dotted ${colour}; padding: 8px 22px; border-radius: 8px">
<h1>My name is ${name},</h1>
<h3>today is ${new Date(today).toLocaleDateString()}</h3>
<p>${stockMessage}</p>
<p>Also, I have:</p>
<ul>
${items.map(item => `<li>${item}</li>`).join('')}
</ul>
<p>${nice ? 'Nice to meet you!' : 'Leave me alone!'}</p>
</div>
`;
});

View File

@ -0,0 +1,34 @@
import { storiesOf } from '@storybook/polymer';
import { withKnobs, text } from '@storybook/addon-knobs/polymer';
import { document } from 'global';
import '../polymer-playground-app.html';
import '../playground-button.html';
import '../separated-button/separated-button.html';
import './storybook-welcome-to-polymer.html';
import { StringTemplateButton } from '../string-template-button';
storiesOf('Welcome', module).add(
'Welcome',
() => '<storybook-welcome-to-polymer></storybook-welcome-to-polymer>'
);
storiesOf('App', module)
.addDecorator(withKnobs)
.add('full app', () => {
const title = text('title', 'This title can be edited via a knob');
return `<polymer-playground-app title="${title}"></polymer-playground-app>`;
});
storiesOf('Button', module)
.add('rounded', () => '<playground-button></playground-button>')
.add('square', () => '<playground-button is-square></playground-button>');
storiesOf('Methods for rendering', module)
.add('html string', () => '<div>Rendered with string</div>')
.add('html with custom elements', () => '<separated-button title="Click me!"></separated-button>')
.add('document.createElement', () => {
const el = document.createElement('playground-button');
el.setAttribute('title', 'Rendered with document.createElement');
return el;
})
.add('Polymer instance', () => new StringTemplateButton());

View File

@ -0,0 +1,77 @@
<link rel="import" href="../../../../node_modules/@polymer/polymer/polymer-element.html">
<dom-module id="storybook-welcome-to-polymer">
<template>
<style>
.main {
margin: 15px;
max-width: 600px;
line-height: 1.4;
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
}
.logo {
width: 200px;
}
.code {
font-size: 15px;
font-weight: 600;
padding: 2px 5px;
border: 1px solid #eae9e9;
border-radius: 4px;
background-color: #f3f2f2;
color: #3a3a3a;
}
.note {
opacity: 0.5;
}
</style>
<div class="main">
<h1>Welcome to Storybook for Polymer</h1>
<p>This is a UI component dev environment for your polymer app.</p>
<p>
We've added some basic stories inside the <code class="code">src/stories</code> 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 class="link" href="#">stories</a> for a component called <code class="code">playground-button</code>
</p>
<p style="text-align:center"><img src="../logo.svg" class="logo" /></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 <code class="code">playground-button</code> stories
located at <code class="code">src/playground-button.html</code>.)
</p>
<p>
Usually we create stories with smaller UI components in the app.<br />
Have a look at the
<a class="link" href="https://storybook.js.org/basics/writing-stories" target="_blank">
Writing Stories
</a>
section in our documentation.
</p>
<p class="note">
<b>NOTE:</b>
<br />
Have a look at the
<code class="code">.storybook/webpack.config.js</code>
to add webpack loaders and plugins you are using in this project.
</p>
</div>
</template>
<script>
class StorybookWelcomeToPolymer extends Polymer.Element {
static get is() { return 'storybook-welcome-to-polymer'; }
}
customElements.define(StorybookWelcomeToPolymer.is, StorybookWelcomeToPolymer);
</script>
</dom-module>

View File

@ -0,0 +1,28 @@
export class StringTemplateButton extends Polymer.Element {
static get is() {
return 'string-template-button';
}
static get properties() {
return {
title: {
type: String,
value: 'Wow, I am inline',
},
counter: {
type: Number,
value: 0,
},
};
}
static get template() {
return '<button on-click="handleTap">[[title]]: [[counter]]</button>';
}
handleTap() {
this.counter += 1;
}
}
customElements.define(StringTemplateButton.is, StringTemplateButton);

View File

@ -0,0 +1,31 @@
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/polymer-playground-app.html',
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].[chunkhash:8].js',
},
module: {
loaders: [
{
test: /\.html$/,
exclude: require.resolve('./index.html'),
use: [{ loader: 'babel-loader' }, { loader: 'polymer-webpack-loader' }],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
}),
new CopyWebpackPlugin([
{ from: require.resolve('@webcomponents/webcomponentsjs/webcomponents-lite.js') },
{ from: require.resolve('@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js') },
]),
],
devServer: { historyApiFallback: true },
devtool: 'eval-source-map',
};

View File

@ -1,17 +1,17 @@
{
"name": "vue-example",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"private": true,
"devDependencies": {
"@storybook/addon-actions": "^3.4.0-alpha.1",
"@storybook/addon-centered": "^3.4.0-alpha.1",
"@storybook/addon-knobs": "^3.4.0-alpha.1",
"@storybook/addon-links": "^3.4.0-alpha.1",
"@storybook/addon-notes": "^3.4.0-alpha.1",
"@storybook/addon-storyshots": "^3.4.0-alpha.1",
"@storybook/addon-viewport": "^3.4.0-alpha.1",
"@storybook/addons": "^3.4.0-alpha.1",
"@storybook/vue": "^3.4.0-alpha.1",
"@storybook/addon-actions": "^3.4.0-alpha.4",
"@storybook/addon-centered": "^3.4.0-alpha.4",
"@storybook/addon-knobs": "^3.4.0-alpha.4",
"@storybook/addon-links": "^3.4.0-alpha.4",
"@storybook/addon-notes": "^3.4.0-alpha.4",
"@storybook/addon-storyshots": "^3.4.0-alpha.4",
"@storybook/addon-viewport": "^3.4.0-alpha.4",
"@storybook/addons": "^3.4.0-alpha.4",
"@storybook/vue": "^3.4.0-alpha.4",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",

View File

@ -8,5 +8,5 @@
}
},
"concurrency": 1,
"version": "3.4.0-alpha.1"
"version": "3.4.0-alpha.4"
}

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/addons",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "Storybook addons store",
"keywords": [
"storybook"

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/channel-postmessage",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "",
"license": "MIT",
"main": "dist/index.js",
@ -9,7 +9,7 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/channels": "^3.4.0-alpha.1",
"@storybook/channels": "^3.4.0-alpha.4",
"global": "^4.3.2",
"json-stringify-safe": "^5.0.1"
}

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/channel-websocket",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "",
"license": "MIT",
"main": "dist/index.js",
@ -9,7 +9,7 @@
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/channels": "^3.4.0-alpha.1",
"@storybook/channels": "^3.4.0-alpha.4",
"global": "^4.3.2"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@storybook/channels",
"version": "3.4.0-alpha.1",
"version": "3.4.0-alpha.4",
"description": "",
"license": "MIT",
"main": "dist/index.js",

Some files were not shown because too many files have changed in this diff Show More