mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-17 05:02:23 +08:00
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:
commit
5fcf200a08
@ -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
|
||||
|
99
CHANGELOG.md
99
CHANGELOG.md
@ -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
|
||||
|
@ -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": {
|
||||
|
@ -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" />,
|
||||
},
|
||||
]}
|
||||
|
17
addons/a11y/src/components/Report/RerunButton.js
Normal file
17
addons/a11y/src/components/Report/RerunButton.js
Normal 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;
|
@ -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(
|
||||
|
@ -5,6 +5,7 @@ import { baseFonts } from '@storybook/components';
|
||||
const styles = {
|
||||
container: {
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
...baseFonts,
|
||||
},
|
||||
tabs: {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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",
|
||||
|
@ -5,7 +5,7 @@ import addons from '@storybook/addons';
|
||||
|
||||
const style = {
|
||||
wrapper: {
|
||||
overflow: 'scroll',
|
||||
overflow: 'auto',
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
|
@ -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>",
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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
1
addons/knobs/polymer.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./dist/polymer');
|
87
addons/knobs/src/polymer/WrapStory.html
Normal file
87
addons/knobs/src/polymer/WrapStory.html
Normal 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>
|
36
addons/knobs/src/polymer/index.js
Normal file
36
addons/knobs/src/polymer/index.js
Normal 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);
|
||||
}
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
},
|
||||
|
@ -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
3
app/polymer/.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["env", "stage-0", "react"]
|
||||
}
|
3
app/polymer/.npmignore
Normal file
3
app/polymer/.npmignore
Normal file
@ -0,0 +1,3 @@
|
||||
docs
|
||||
src
|
||||
.babelrc
|
41
app/polymer/README.md
Normal file
41
app/polymer/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Storybook for Polymer
|
||||
|
||||
[](https://circleci.com/gh/storybooks/storybook)
|
||||
[](https://www.codefactor.io/repository/github/storybooks/storybook)
|
||||
[](https://snyk.io/test/github/storybooks/storybook/8f36abfd6697e58cd76df3526b52e4b9dc894847)
|
||||
[](https://bettercodehub.com/results/storybooks/storybook) [](https://codecov.io/gh/storybooks/storybook)
|
||||
[](https://now-examples-slackin-nqnzoygycp.now.sh/)
|
||||
[](#backers) [](#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 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
3
app/polymer/bin/build.js
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('../dist/server/build');
|
3
app/polymer/bin/index.js
Executable file
3
app/polymer/bin/index.js
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('../dist/server');
|
BIN
app/polymer/docs/demo.gif
Normal file
BIN
app/polymer/docs/demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 MiB |
BIN
app/polymer/docs/react_storybook_screenshot.png
Normal file
BIN
app/polymer/docs/react_storybook_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 245 KiB |
BIN
app/polymer/docs/storybooks_io_logo.png
Normal file
BIN
app/polymer/docs/storybooks_io_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
87
app/polymer/package.json
Normal file
87
app/polymer/package.json
Normal 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"
|
||||
}
|
||||
}
|
17
app/polymer/src/client/index.js
Normal file
17
app/polymer/src/client/index.js
Normal 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'
|
||||
// );
|
7
app/polymer/src/client/manager/index.js
Normal file
7
app/polymer/src/client/manager/index.js
Normal 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());
|
39
app/polymer/src/client/manager/preview.js
Normal file
39
app/polymer/src/client/manager/preview.js
Normal 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;
|
51
app/polymer/src/client/manager/provider.js
Normal file
51
app/polymer/src/client/manager/provider.js
Normal 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);
|
||||
}
|
||||
}
|
37
app/polymer/src/client/preview/errorpreview.js
Normal file
37
app/polymer/src/client/preview/errorpreview.js
Normal 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>
|
||||
`;
|
61
app/polymer/src/client/preview/index.js
Normal file
61
app/polymer/src/client/preview/index.js
Normal 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);
|
42
app/polymer/src/client/preview/nopreview.js
Normal file
42
app/polymer/src/client/preview/nopreview.js
Normal 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>
|
||||
`;
|
66
app/polymer/src/client/preview/render.js
Normal file
66
app/polymer/src/client/preview/render.js
Normal 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 "() => '<your-component-name></your-component-name\>'" 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);
|
||||
}
|
||||
}
|
2
app/polymer/src/server/addons.js
Normal file
2
app/polymer/src/server/addons.js
Normal file
@ -0,0 +1,2 @@
|
||||
// import '@storybook/addon-actions/register';
|
||||
// import '@storybook/addon-links/register';
|
82
app/polymer/src/server/babel_config.js
Normal file
82
app/polymer/src/server/babel_config.js
Normal 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;
|
||||
}
|
110
app/polymer/src/server/babel_config.test.js
Normal file
110
app/polymer/src/server/babel_config.test.js
Normal 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
83
app/polymer/src/server/build.js
Executable 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);
|
||||
}
|
||||
});
|
86
app/polymer/src/server/config.js
Normal file
86
app/polymer/src/server/config.js
Normal 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),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
@ -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.
|
||||
// We’re 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;
|
28
app/polymer/src/server/config/babel.js
Normal file
28
app/polymer/src/server/config/babel.js
Normal 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,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
29
app/polymer/src/server/config/babel.prod.js
Normal file
29
app/polymer/src/server/config/babel.prod.js
Normal 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,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
73
app/polymer/src/server/config/defaults/webpack.config.js
Normal file
73
app/polymer/src/server/config/defaults/webpack.config.js
Normal 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;
|
||||
};
|
4
app/polymer/src/server/config/globals.js
Normal file
4
app/polymer/src/server/config/globals.js
Normal file
@ -0,0 +1,4 @@
|
||||
/* globals window */
|
||||
|
||||
window.STORYBOOK_REACT_CLASSES = {};
|
||||
window.STORYBOOK_ENV = 'polymer';
|
4
app/polymer/src/server/config/polyfills.js
Normal file
4
app/polymer/src/server/config/polyfills.js
Normal file
@ -0,0 +1,4 @@
|
||||
import 'core-js/es6/symbol';
|
||||
import 'core-js/fn/array/iterator';
|
||||
import 'airbnb-js-shims';
|
||||
import 'babel-polyfill';
|
37
app/polymer/src/server/config/utils.js
Normal file
37
app/polymer/src/server/config/utils.js
Normal 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';
|
105
app/polymer/src/server/config/webpack.config.js
Normal file
105
app/polymer/src/server/config/webpack.config.js
Normal 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;
|
||||
}
|
103
app/polymer/src/server/config/webpack.config.prod.js
Normal file
103
app/polymer/src/server/config/webpack.config.prod.js
Normal 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;
|
||||
}
|
16
app/polymer/src/server/iframe.html.ejs
Normal file
16
app/polymer/src/server/iframe.html.ejs
Normal 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>
|
44
app/polymer/src/server/index.html.ejs
Normal file
44
app/polymer/src/server/index.html.ejs
Normal 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
166
app/polymer/src/server/index.js
Executable 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);
|
||||
}
|
||||
});
|
64
app/polymer/src/server/middleware.js
Normal file
64
app/polymer/src/server/middleware.js
Normal 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;
|
||||
}
|
BIN
app/polymer/src/server/public/favicon.ico
Executable file
BIN
app/polymer/src/server/public/favicon.ico
Executable file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
56
app/polymer/src/server/utils.js
Normal file
56
app/polymer/src/server/utils.js
Normal 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 () => {};
|
||||
}
|
69
app/polymer/src/server/utils.test.js
Normal file
69
app/polymer/src/server/utils.test.js
Normal 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);
|
||||
});
|
||||
});
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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).
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
22
examples/official-storybook/components/DelayedRender.js
Normal file
22
examples/official-storybook/components/DelayedRender.js
Normal 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 />;
|
||||
}
|
||||
}
|
@ -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",
|
||||
|
@ -23,3 +23,5 @@ exports[`Storyshots Addons|a11y Label 1`] = `
|
||||
Testing the a11y addon
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Addons|a11y delayed render 1`] = `<div />`;
|
||||
|
@ -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!
|
||||
|
@ -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>
|
||||
));
|
||||
|
7
examples/polymer-cli/.eslintrc.js
Normal file
7
examples/polymer-cli/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
globals: {
|
||||
Polymer: true,
|
||||
customElements: true,
|
||||
CustomEvent: true,
|
||||
},
|
||||
};
|
4
examples/polymer-cli/.storybook/addons.js
Normal file
4
examples/polymer-cli/.storybook/addons.js
Normal 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';
|
10
examples/polymer-cli/.storybook/config.js
Normal file
10
examples/polymer-cli/.storybook/config.js
Normal 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);
|
8
examples/polymer-cli/README.md
Normal file
8
examples/polymer-cli/README.md
Normal 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.
|
14
examples/polymer-cli/index.html
Normal file
14
examples/polymer-cli/index.html
Normal 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>
|
31
examples/polymer-cli/package.json
Normal file
31
examples/polymer-cli/package.json
Normal 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"
|
||||
}
|
||||
}
|
1
examples/polymer-cli/src/logo.svg
Normal file
1
examples/polymer-cli/src/logo.svg
Normal 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 |
50
examples/polymer-cli/src/playground-button.html
Normal file
50
examples/polymer-cli/src/playground-button.html
Normal 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>
|
26
examples/polymer-cli/src/polymer-playground-app.html
Normal file
26
examples/polymer-cli/src/polymer-playground-app.html
Normal 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>
|
@ -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>
|
@ -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();
|
||||
}
|
||||
};
|
12
examples/polymer-cli/src/separated-button/useless-mixin.js
Normal file
12
examples/polymer-cli/src/separated-button/useless-mixin.js
Normal 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' }));
|
||||
}
|
||||
};
|
104
examples/polymer-cli/src/stories/advanced.stories.js
Normal file
104
examples/polymer-cli/src/stories/advanced.stories.js
Normal 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 $${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>
|
||||
`;
|
||||
});
|
34
examples/polymer-cli/src/stories/index.stories.js
Normal file
34
examples/polymer-cli/src/stories/index.stories.js
Normal 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());
|
@ -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>
|
28
examples/polymer-cli/src/string-template-button.js
Normal file
28
examples/polymer-cli/src/string-template-button.js
Normal 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);
|
31
examples/polymer-cli/webpack.config.js
Normal file
31
examples/polymer-cli/webpack.config.js
Normal 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',
|
||||
};
|
@ -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",
|
||||
|
@ -8,5 +8,5 @@
|
||||
}
|
||||
},
|
||||
"concurrency": 1,
|
||||
"version": "3.4.0-alpha.1"
|
||||
"version": "3.4.0-alpha.4"
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user