mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-07 23:02:00 +08:00
Merge branch 'master' into react-native-dependency-version
This commit is contained in:
commit
9eb61c2120
@ -53,6 +53,7 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
'import/prefer-default-export': ignore,
|
'import/prefer-default-export': ignore,
|
||||||
'react/jsx-wrap-multilines': ignore,
|
'react/jsx-wrap-multilines': ignore,
|
||||||
|
'react/jsx-indent': ignore,
|
||||||
'react/jsx-indent-props': ignore,
|
'react/jsx-indent-props': ignore,
|
||||||
'react/jsx-closing-bracket-location': ignore,
|
'react/jsx-closing-bracket-location': ignore,
|
||||||
'react/jsx-uses-react': error,
|
'react/jsx-uses-react': error,
|
||||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -1,3 +1,29 @@
|
|||||||
|
# 3.1.9
|
||||||
|
|
||||||
|
2017-July-16
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- React fiber support [#1443](https://github.com/storybooks/storybook/pull/1443)
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
|
||||||
|
- Refine docs about loading stories dynamically for react-native [#1420](https://github.com/storybooks/storybook/pull/1420)
|
||||||
|
|
||||||
|
#### Bug Fixes
|
||||||
|
|
||||||
|
- Verify that name is a string in addons/actions [#1415](https://github.com/storybooks/storybook/pull/1415)
|
||||||
|
- Knobs: fix label alignment [#1471](https://github.com/storybooks/storybook/pull/1471)
|
||||||
|
- Fix display of large components [#1237](https://github.com/storybooks/storybook/pull/1237)
|
||||||
|
|
||||||
|
#### Dependency Upgrades
|
||||||
|
|
||||||
|
- Dependency updates [#1439](https://github.com/storybooks/storybook/pull/1439)
|
||||||
|
- chore(package): update husky to version 0.14.3 [#1437](https://github.com/storybooks/storybook/pull/1437)
|
||||||
|
- Update danger to the latest version 🚀 [#1393](https://github.com/storybooks/storybook/pull/1393)
|
||||||
|
- Update lerna to the latest version 🚀 [#1423](https://github.com/storybooks/storybook/pull/1423)
|
||||||
|
- Pin gatsby version and upgrade gh-pages [#1462](https://github.com/storybooks/storybook/pull/1462)
|
||||||
|
|
||||||
# 3.1.8
|
# 3.1.8
|
||||||
|
|
||||||
2017-July-06
|
2017-July-06
|
||||||
|
@ -124,5 +124,5 @@ If you **are** using these addons, migrating is simple:
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { storiesOf } from '@storybook/react';
|
import { storiesOf } from '@storybook/react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import { link } from '@storybook/addon-links';
|
import { linkTo } from '@storybook/addon-links';
|
||||||
```
|
```
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-actions",
|
"name": "@storybook/addon-actions",
|
||||||
"version": "3.1.8",
|
"version": "3.1.9",
|
||||||
"description": "Action Logger addon for storybook",
|
"description": "Action Logger addon for storybook",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -9,7 +9,11 @@ class ActionLogger extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderAction(action) {
|
renderAction(action) {
|
||||||
const counter = <div style={style.counter}>{action.count}</div>;
|
const counter = (
|
||||||
|
<div style={style.counter}>
|
||||||
|
{action.count}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div key={action.id} style={style.action}>
|
<div key={action.id} style={style.action}>
|
||||||
<div style={style.countwrap}>
|
<div style={style.countwrap}>
|
||||||
@ -29,8 +33,12 @@ class ActionLogger extends Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={style.wrapper}>
|
<div style={style.wrapper}>
|
||||||
<pre style={style.actions}>{this.getActionData()}</pre>
|
<pre style={style.actions}>
|
||||||
<button style={style.button} onClick={this.props.onClear}>CLEAR</button>
|
{this.getActionData()}
|
||||||
|
</pre>
|
||||||
|
<button style={style.button} onClick={this.props.onClear}>
|
||||||
|
CLEAR
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ export function action(name) {
|
|||||||
// the same.
|
// the same.
|
||||||
//
|
//
|
||||||
// Ref: https://bocoup.com/weblog/whats-in-a-function-name
|
// Ref: https://bocoup.com/weblog/whats-in-a-function-name
|
||||||
const fnName = name ? name.replace(/\W+/g, '_') : 'action';
|
const fnName = name && typeof name === 'string' ? name.replace(/\W+/g, '_') : 'action';
|
||||||
// eslint-disable-next-line no-eval
|
// eslint-disable-next-line no-eval
|
||||||
const named = eval(`(function ${fnName}() { return handler.apply(this, arguments) })`);
|
const named = eval(`(function ${fnName}() { return handler.apply(this, arguments) })`);
|
||||||
return named;
|
return named;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-centered",
|
"name": "@storybook/addon-centered",
|
||||||
"version": "3.1.2",
|
"version": "3.1.9",
|
||||||
"description": "Storybook decorator to center components",
|
"description": "Storybook decorator to center components",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Muhammed Thanish <mnmtanish@gmail.com>",
|
"author": "Muhammed Thanish <mnmtanish@gmail.com>",
|
||||||
|
@ -9,8 +9,19 @@ const style = {
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
overflow: 'auto',
|
||||||
|
};
|
||||||
|
|
||||||
|
const innerStyle = {
|
||||||
|
margin: 'auto',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function(storyFn) {
|
export default function(storyFn) {
|
||||||
return <div style={style}>{storyFn()}</div>;
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<div style={innerStyle}>
|
||||||
|
{storyFn()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-comments",
|
"name": "@storybook/addon-comments",
|
||||||
"version": "3.1.6",
|
"version": "3.1.9",
|
||||||
"description": "Comments addon for Storybook",
|
"description": "Comments addon for Storybook",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"storybook"
|
"storybook"
|
||||||
|
@ -59,10 +59,16 @@ export default class CommentItem extends Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className="comment-content" style={style.commentContent}>
|
<div className="comment-content" style={style.commentContent}>
|
||||||
<div style={style.commentHead}>
|
<div style={style.commentHead}>
|
||||||
<span style={style.commentUser}>{comment.user.name}</span>
|
<span style={style.commentUser}>
|
||||||
<span style={style.commentTime}>{time}</span>
|
{comment.user.name}
|
||||||
|
</span>
|
||||||
|
<span style={style.commentTime}>
|
||||||
|
{time}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span style={style.commentText}>{body}</span>
|
<span style={style.commentText}>
|
||||||
|
{body}
|
||||||
|
</span>
|
||||||
{showDelete ? this.renderDelete() : null}
|
{showDelete ? this.renderDelete() : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,9 @@ export default function CommentsPanel(props) {
|
|||||||
return (
|
return (
|
||||||
<div style={style.wrapper}>
|
<div style={style.wrapper}>
|
||||||
<div style={style.message}>
|
<div style={style.message}>
|
||||||
<a style={style.button} href={appsUrl}>Create an app for this repo on Storybook Hub</a>
|
<a style={style.button} href={appsUrl}>
|
||||||
|
Create an app for this repo on Storybook Hub
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-events",
|
"name": "@storybook/addon-events",
|
||||||
"version": "3.1.6",
|
"version": "3.1.9",
|
||||||
"description": "Add events to your Storybook stories.",
|
"description": "Add events to your Storybook stories.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"addon",
|
"addon",
|
||||||
|
@ -136,7 +136,9 @@ export default class Item extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={styles.item}>
|
<div style={styles.item}>
|
||||||
<label htmlFor={`addon-event-${name}`} style={styles.label}>{title}</label>
|
<label htmlFor={`addon-event-${name}`} style={styles.label}>
|
||||||
|
{title}
|
||||||
|
</label>
|
||||||
<button
|
<button
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
onClick={this.onEmitClick}
|
onClick={this.onEmitClick}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-info",
|
"name": "@storybook/addon-info",
|
||||||
"version": "3.1.6",
|
"version": "3.1.9",
|
||||||
"description": "A Storybook addon to show additional information for your stories.",
|
"description": "A Storybook addon to show additional information for your stories.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
@ -66,7 +66,9 @@ export default function Node(props) {
|
|||||||
if (!name) {
|
if (!name) {
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div style={containerStyle}>
|
||||||
<span style={tagStyle}>{text}</span>
|
<span style={tagStyle}>
|
||||||
|
{text}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -75,7 +77,9 @@ export default function Node(props) {
|
|||||||
if (!children) {
|
if (!children) {
|
||||||
return (
|
return (
|
||||||
<div style={containerStyle}>
|
<div style={containerStyle}>
|
||||||
<span style={tagStyle}><{name}</span>
|
<span style={tagStyle}>
|
||||||
|
<{name}
|
||||||
|
</span>
|
||||||
<Props
|
<Props
|
||||||
node={node}
|
node={node}
|
||||||
singleLine
|
singleLine
|
||||||
@ -96,7 +100,9 @@ export default function Node(props) {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div style={containerStyleCopy}>
|
<div style={containerStyleCopy}>
|
||||||
<span style={tagStyle}><{name}</span>
|
<span style={tagStyle}>
|
||||||
|
<{name}
|
||||||
|
</span>
|
||||||
<Props
|
<Props
|
||||||
node={node}
|
node={node}
|
||||||
maxPropsIntoLine={maxPropsIntoLine}
|
maxPropsIntoLine={maxPropsIntoLine}
|
||||||
@ -117,7 +123,9 @@ export default function Node(props) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div style={containerStyleCopy}>
|
<div style={containerStyleCopy}>
|
||||||
<span style={tagStyle}></{name}></span>
|
<span style={tagStyle}>
|
||||||
|
</{name}>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -34,11 +34,10 @@ export default function PropTable(props) {
|
|||||||
Object.keys(type.propTypes).forEach(property => {
|
Object.keys(type.propTypes).forEach(property => {
|
||||||
const typeInfo = type.propTypes[property];
|
const typeInfo = type.propTypes[property];
|
||||||
const required = typeInfo.isRequired === undefined ? 'yes' : 'no';
|
const required = typeInfo.isRequired === undefined ? 'yes' : 'no';
|
||||||
const description = type.__docgenInfo &&
|
const description =
|
||||||
type.__docgenInfo.props &&
|
type.__docgenInfo && type.__docgenInfo.props && type.__docgenInfo.props[property]
|
||||||
type.__docgenInfo.props[property]
|
? type.__docgenInfo.props[property].description
|
||||||
? type.__docgenInfo.props[property].description
|
: null;
|
||||||
: null;
|
|
||||||
let propType = PropTypesMap.get(typeInfo) || 'other';
|
let propType = PropTypesMap.get(typeInfo) || 'other';
|
||||||
|
|
||||||
if (propType === 'other') {
|
if (propType === 'other') {
|
||||||
@ -100,15 +99,23 @@ export default function PropTable(props) {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{array.map(row =>
|
{array.map(row =>
|
||||||
<tr key={row.property}>
|
<tr key={row.property}>
|
||||||
<td>{row.property}</td>
|
<td>
|
||||||
<td>{row.propType}</td>
|
{row.property}
|
||||||
<td>{row.required}</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{row.propType}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{row.required}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{row.defaultValue === undefined
|
{row.defaultValue === undefined
|
||||||
? '-'
|
? '-'
|
||||||
: <PropVal val={row.defaultValue} {...propValProps} />}
|
: <PropVal val={row.defaultValue} {...propValProps} />}
|
||||||
</td>
|
</td>
|
||||||
<td>{row.description}</td>
|
<td>
|
||||||
|
{row.description}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -59,7 +59,11 @@ function previewObject(val, maxPropObjectKeys) {
|
|||||||
const names = Object.keys(val);
|
const names = Object.keys(val);
|
||||||
const items = {};
|
const items = {};
|
||||||
names.slice(0, maxPropObjectKeys).forEach((name, i) => {
|
names.slice(0, maxPropObjectKeys).forEach((name, i) => {
|
||||||
items[`k${i}`] = <span style={valueStyles.attr}>{name}</span>;
|
items[`k${i}`] = (
|
||||||
|
<span style={valueStyles.attr}>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
items[`c${i}`] = ': ';
|
items[`c${i}`] = ': ';
|
||||||
items[`v${i}`] = <PropVal val={val[name]} />;
|
items[`v${i}`] = <PropVal val={val[name]} />;
|
||||||
items[`m${i}`] = ', ';
|
items[`m${i}`] = ', ';
|
||||||
@ -71,7 +75,9 @@ function previewObject(val, maxPropObjectKeys) {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span style={valueStyles.object}>
|
<span style={valueStyles.object}>
|
||||||
{'{'}{createFragment(items)}{'}'}
|
{'{'}
|
||||||
|
{createFragment(items)}
|
||||||
|
{'}'}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -83,19 +89,31 @@ export default function PropVal(props) {
|
|||||||
let content = null;
|
let content = null;
|
||||||
|
|
||||||
if (typeof val === 'number') {
|
if (typeof val === 'number') {
|
||||||
content = <span style={valueStyles.number}>{val}</span>;
|
content = (
|
||||||
|
<span style={valueStyles.number}>
|
||||||
|
{val}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
} else if (typeof val === 'string') {
|
} else if (typeof val === 'string') {
|
||||||
if (val.length > maxPropStringLength) {
|
if (val.length > maxPropStringLength) {
|
||||||
val = `${val.slice(0, maxPropStringLength)}…`;
|
val = `${val.slice(0, maxPropStringLength)}…`;
|
||||||
}
|
}
|
||||||
content = <span style={valueStyles.string}>"{val}"</span>;
|
content = (
|
||||||
|
<span style={valueStyles.string}>
|
||||||
|
"{val}"
|
||||||
|
</span>
|
||||||
|
);
|
||||||
braceWrap = false;
|
braceWrap = false;
|
||||||
} else if (typeof val === 'boolean') {
|
} else if (typeof val === 'boolean') {
|
||||||
content = <span style={valueStyles.bool}>{`${val}`}</span>;
|
content = <span style={valueStyles.bool}>{`${val}`}</span>;
|
||||||
} else if (Array.isArray(val)) {
|
} else if (Array.isArray(val)) {
|
||||||
content = previewArray(val, maxPropArrayLength);
|
content = previewArray(val, maxPropArrayLength);
|
||||||
} else if (typeof val === 'function') {
|
} else if (typeof val === 'function') {
|
||||||
content = <span style={valueStyles.func}>{val.name ? `${val.name}()` : 'anonymous()'}</span>;
|
content = (
|
||||||
|
<span style={valueStyles.func}>
|
||||||
|
{val.name ? `${val.name}()` : 'anonymous()'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
} else if (!val) {
|
} else if (!val) {
|
||||||
content = <span style={valueStyles.empty}>{`${val}`}</span>;
|
content = <span style={valueStyles.empty}>{`${val}`}</span>;
|
||||||
} else if (typeof val !== 'object') {
|
} else if (typeof val !== 'object') {
|
||||||
@ -112,7 +130,11 @@ export default function PropVal(props) {
|
|||||||
|
|
||||||
if (!braceWrap) return content;
|
if (!braceWrap) return content;
|
||||||
|
|
||||||
return <span>{content}</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
{content}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropVal.propTypes = {
|
PropVal.propTypes = {
|
||||||
|
@ -32,8 +32,14 @@ export default function Props(props) {
|
|||||||
names.forEach((name, i) => {
|
names.forEach((name, i) => {
|
||||||
items.push(
|
items.push(
|
||||||
<span key={name}>
|
<span key={name}>
|
||||||
{breakIntoNewLines ? <span><br /> </span> : ' '}
|
{breakIntoNewLines
|
||||||
<span style={propNameStyle}>{name}</span>
|
? <span>
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
: ' '}
|
||||||
|
<span style={propNameStyle}>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
{/* Use implicit true: */}
|
{/* Use implicit true: */}
|
||||||
{(!nodeProps[name] || typeof nodeProps[name] !== 'boolean') &&
|
{(!nodeProps[name] || typeof nodeProps[name] !== 'boolean') &&
|
||||||
<span>
|
<span>
|
||||||
@ -53,7 +59,11 @@ export default function Props(props) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return <span>{items}</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
{items}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Props.defaultProps = {
|
Props.defaultProps = {
|
||||||
|
@ -180,9 +180,13 @@ export default class Story extends React.Component {
|
|||||||
<div style={this.state.stylesheet.children}>
|
<div style={this.state.stylesheet.children}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
<a style={linkStyle} onClick={openOverlay} role="button" tabIndex="0">Show Info</a>
|
<a style={linkStyle} onClick={openOverlay} role="button" tabIndex="0">
|
||||||
|
Show Info
|
||||||
|
</a>
|
||||||
<div style={infoStyle}>
|
<div style={infoStyle}>
|
||||||
<a style={linkStyle} onClick={closeOverlay} role="button" tabIndex="0">×</a>
|
<a style={linkStyle} onClick={closeOverlay} role="button" tabIndex="0">
|
||||||
|
×
|
||||||
|
</a>
|
||||||
<div style={this.state.stylesheet.infoPage}>
|
<div style={this.state.stylesheet.infoPage}>
|
||||||
<div style={this.state.stylesheet.infoBody}>
|
<div style={this.state.stylesheet.infoBody}>
|
||||||
{this._getInfoHeader()}
|
{this._getInfoHeader()}
|
||||||
@ -204,8 +208,12 @@ export default class Story extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={this.state.stylesheet.header.body}>
|
<div style={this.state.stylesheet.header.body}>
|
||||||
<h1 style={this.state.stylesheet.header.h1}>{this.props.context.kind}</h1>
|
<h1 style={this.state.stylesheet.header.h1}>
|
||||||
<h2 style={this.state.stylesheet.header.h2}>{this.props.context.story}</h2>
|
{this.props.context.kind}
|
||||||
|
</h1>
|
||||||
|
<h2 style={this.state.stylesheet.header.h2}>
|
||||||
|
{this.props.context.story}
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,11 @@ export function Pre(props) {
|
|||||||
lineHeight: 1.5,
|
lineHeight: 1.5,
|
||||||
overflowX: 'scroll',
|
overflowX: 'scroll',
|
||||||
};
|
};
|
||||||
return <pre style={style}>{props.children}</pre>;
|
return (
|
||||||
|
<pre style={style}>
|
||||||
|
{props.children}
|
||||||
|
</pre>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pre.propTypes = { children: PropTypes.node };
|
Pre.propTypes = { children: PropTypes.node };
|
||||||
@ -74,7 +78,11 @@ export function Blockquote(props) {
|
|||||||
borderLeft: '8px solid #fafafa',
|
borderLeft: '8px solid #fafafa',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
};
|
};
|
||||||
return <blockquote style={style}>{props.children}</blockquote>;
|
return (
|
||||||
|
<blockquote style={style}>
|
||||||
|
{props.children}
|
||||||
|
</blockquote>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Blockquote.propTypes = { children: PropTypes.node };
|
Blockquote.propTypes = { children: PropTypes.node };
|
||||||
|
@ -20,7 +20,11 @@ export function H1(props) {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
fontSize: '40px',
|
fontSize: '40px',
|
||||||
};
|
};
|
||||||
return <h1 id={props.id} style={styles}>{props.children}</h1>;
|
return (
|
||||||
|
<h1 id={props.id} style={styles}>
|
||||||
|
{props.children}
|
||||||
|
</h1>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
H1.defaultProps = defaultProps;
|
H1.defaultProps = defaultProps;
|
||||||
@ -34,7 +38,11 @@ export function H2(props) {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
fontSize: '30px',
|
fontSize: '30px',
|
||||||
};
|
};
|
||||||
return <h2 id={props.id} style={styles}>{props.children}</h2>;
|
return (
|
||||||
|
<h2 id={props.id} style={styles}>
|
||||||
|
{props.children}
|
||||||
|
</h2>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
H2.defaultProps = defaultProps;
|
H2.defaultProps = defaultProps;
|
||||||
@ -49,7 +57,11 @@ export function H3(props) {
|
|||||||
fontSize: '22px',
|
fontSize: '22px',
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
};
|
};
|
||||||
return <h3 id={props.id} style={styles}>{props.children}</h3>;
|
return (
|
||||||
|
<h3 id={props.id} style={styles}>
|
||||||
|
{props.children}
|
||||||
|
</h3>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
H3.defaultProps = defaultProps;
|
H3.defaultProps = defaultProps;
|
||||||
@ -63,7 +75,11 @@ export function H4(props) {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
fontSize: '20px',
|
fontSize: '20px',
|
||||||
};
|
};
|
||||||
return <h4 id={props.id} style={styles}>{props.children}</h4>;
|
return (
|
||||||
|
<h4 id={props.id} style={styles}>
|
||||||
|
{props.children}
|
||||||
|
</h4>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
H4.defaultProps = defaultProps;
|
H4.defaultProps = defaultProps;
|
||||||
@ -77,7 +93,11 @@ export function H5(props) {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
fontSize: '18px',
|
fontSize: '18px',
|
||||||
};
|
};
|
||||||
return <h5 id={props.id} style={styles}>{props.children}</h5>;
|
return (
|
||||||
|
<h5 id={props.id} style={styles}>
|
||||||
|
{props.children}
|
||||||
|
</h5>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
H5.defaultProps = defaultProps;
|
H5.defaultProps = defaultProps;
|
||||||
@ -91,7 +111,11 @@ export function H6(props) {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
fontSize: '18px',
|
fontSize: '18px',
|
||||||
};
|
};
|
||||||
return <h6 id={props.id} style={styles}>{props.children}</h6>;
|
return (
|
||||||
|
<h6 id={props.id} style={styles}>
|
||||||
|
{props.children}
|
||||||
|
</h6>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
H6.defaultProps = defaultProps;
|
H6.defaultProps = defaultProps;
|
||||||
|
@ -10,7 +10,11 @@ export function P(props) {
|
|||||||
...baseFonts,
|
...baseFonts,
|
||||||
fontSize: '15px',
|
fontSize: '15px',
|
||||||
};
|
};
|
||||||
return <p style={style}>{props.children}</p>;
|
return (
|
||||||
|
<p style={style}>
|
||||||
|
{props.children}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
P.defaultProps = defaultProps;
|
P.defaultProps = defaultProps;
|
||||||
@ -21,7 +25,11 @@ export function LI(props) {
|
|||||||
...baseFonts,
|
...baseFonts,
|
||||||
fontSize: '15px',
|
fontSize: '15px',
|
||||||
};
|
};
|
||||||
return <li style={style}>{props.children}</li>;
|
return (
|
||||||
|
<li style={style}>
|
||||||
|
{props.children}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LI.defaultProps = defaultProps;
|
LI.defaultProps = defaultProps;
|
||||||
@ -32,7 +40,11 @@ export function UL(props) {
|
|||||||
...baseFonts,
|
...baseFonts,
|
||||||
fontSize: '15px',
|
fontSize: '15px',
|
||||||
};
|
};
|
||||||
return <ul style={style}>{props.children}</ul>;
|
return (
|
||||||
|
<ul style={style}>
|
||||||
|
{props.children}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UL.defaultProps = defaultProps;
|
UL.defaultProps = defaultProps;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-knobs",
|
"name": "@storybook/addon-knobs",
|
||||||
"version": "3.1.8",
|
"version": "3.1.9",
|
||||||
"description": "Storybook Addon Prop Editor Component",
|
"description": "Storybook Addon Prop Editor Component",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
@ -141,7 +141,9 @@ export default class Panel extends React.Component {
|
|||||||
<div style={styles.panel}>
|
<div style={styles.panel}>
|
||||||
<PropForm knobs={knobsArray} onFieldChange={this.handleChange} />
|
<PropForm knobs={knobsArray} onFieldChange={this.handleChange} />
|
||||||
</div>
|
</div>
|
||||||
<button style={styles.resetButton} onClick={this.reset}>RESET</button>
|
<button style={styles.resetButton} onClick={this.reset}>
|
||||||
|
RESET
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ const stylesheet = {
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
verticalAlign: 'top',
|
verticalAlign: 'top',
|
||||||
paddingRight: 5,
|
paddingRight: 5,
|
||||||
paddingTop: 7,
|
paddingTop: 5,
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
width: 80,
|
width: 80,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
@ -5,7 +5,7 @@ const styles = {
|
|||||||
display: 'table-cell',
|
display: 'table-cell',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
height: '26px',
|
height: '25px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
border: '1px solid #f7f4f4',
|
border: '1px solid #f7f4f4',
|
||||||
|
@ -24,7 +24,11 @@ class SelectType extends React.Component {
|
|||||||
value: key,
|
value: key,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <option {...opts}>{val}</option>;
|
return (
|
||||||
|
<option {...opts}>
|
||||||
|
{val}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_options(values) {
|
_options(values) {
|
||||||
let data = [];
|
let data = [];
|
||||||
|
@ -32,6 +32,8 @@ Usually, you might already have completed this step. If not, here are some resou
|
|||||||
- If you are using Create React App, it's already configured for Jest. You just need to create a filename with the extension `.test.js`.
|
- If you are using Create React App, it's already configured for Jest. You just need to create a filename with the extension `.test.js`.
|
||||||
- Otherwise check this Egghead [lesson](https://egghead.io/lessons/javascript-test-javascript-with-jest).
|
- Otherwise check this Egghead [lesson](https://egghead.io/lessons/javascript-test-javascript-with-jest).
|
||||||
|
|
||||||
|
> Note: If you use React 16, you'll need to follow [these additional instructions](https://github.com/facebook/react/issues/9102#issuecomment-283873039).
|
||||||
|
|
||||||
## Configure Storyshots
|
## Configure Storyshots
|
||||||
|
|
||||||
Create a new test file with the name `Storyshots.test.js`. (Or whatever the name you prefer).
|
Create a new test file with the name `Storyshots.test.js`. (Or whatever the name you prefer).
|
||||||
@ -68,15 +70,15 @@ initStoryshots({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### `suit`
|
### `suite`
|
||||||
|
|
||||||
By default, Storyshots groups stories inside a Jest test suit called "Storyshots". You could change it like this:
|
By default, Storyshots groups stories inside a Jest test suite called "Storyshots". You could change it like this:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import initStoryshots from '@storybook/addon-storyshots';
|
import initStoryshots from '@storybook/addon-storyshots';
|
||||||
|
|
||||||
initStoryshots({
|
initStoryshots({
|
||||||
suit: 'MyStoryshots'
|
suite: 'MyStoryshots'
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/addon-storyshots",
|
"name": "@storybook/addon-storyshots",
|
||||||
"version": "3.1.8",
|
"version": "3.1.9",
|
||||||
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
@ -22,7 +22,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@storybook/addons": "^3.1.6",
|
"@storybook/addons": "^3.1.6",
|
||||||
"@storybook/channels": "^3.1.6",
|
"@storybook/channels": "^3.1.6",
|
||||||
"@storybook/react": "^3.1.8",
|
"@storybook/react": "^3.1.9",
|
||||||
"babel-cli": "^6.24.1",
|
"babel-cli": "^6.24.1",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
@ -33,7 +33,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@storybook/addons": "^3.1.6",
|
"@storybook/addons": "^3.1.6",
|
||||||
"@storybook/channels": "^3.1.6",
|
"@storybook/channels": "^3.1.6",
|
||||||
"@storybook/react": "^3.1.8",
|
"@storybook/react": "^3.1.9",
|
||||||
"babel-core": "^6.24.1",
|
"babel-core": "^6.24.1",
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-test-renderer": "*"
|
"react-test-renderer": "*"
|
||||||
|
@ -56,7 +56,8 @@ export default function testStorySnapshots(options = {}) {
|
|||||||
throw new Error('testStorySnapshots is intended only to be used inside jest');
|
throw new Error('testStorySnapshots is intended only to be used inside jest');
|
||||||
}
|
}
|
||||||
|
|
||||||
const suit = options.suit || 'Storyshots';
|
// NOTE: keep `suit` typo for backwards compatibility
|
||||||
|
const suite = options.suite || options.suit || 'Storyshots';
|
||||||
const stories = storybook.getStorybook();
|
const stories = storybook.getStorybook();
|
||||||
|
|
||||||
// Added not to break existing storyshots configs (can be removed in a future major release)
|
// Added not to break existing storyshots configs (can be removed in a future major release)
|
||||||
@ -72,7 +73,7 @@ export default function testStorySnapshots(options = {}) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe(suit, () => {
|
describe(suite, () => {
|
||||||
describe(group.kind, () => {
|
describe(group.kind, () => {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
for (const story of group.stories) {
|
for (const story of group.stories) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/react-native",
|
"name": "@storybook/react-native",
|
||||||
"version": "3.1.8",
|
"version": "3.1.9",
|
||||||
"description": "A better way to develop React Native Components for your app",
|
"description": "A better way to develop React Native Components for your app",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
@ -24,11 +24,11 @@
|
|||||||
"prepublish": "node ../../scripts/prepublish.js"
|
"prepublish": "node ../../scripts/prepublish.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@storybook/addon-actions": "^3.1.8",
|
"@storybook/addon-actions": "^3.1.9",
|
||||||
"@storybook/addon-links": "^3.1.6",
|
"@storybook/addon-links": "^3.1.6",
|
||||||
"@storybook/addons": "^3.1.6",
|
"@storybook/addons": "^3.1.6",
|
||||||
"@storybook/channel-websocket": "^3.1.6",
|
"@storybook/channel-websocket": "^3.1.6",
|
||||||
"@storybook/ui": "^3.1.6",
|
"@storybook/ui": "^3.1.9",
|
||||||
"autoprefixer": "^7.0.1",
|
"autoprefixer": "^7.0.1",
|
||||||
"babel-core": "^6.24.1",
|
"babel-core": "^6.24.1",
|
||||||
"babel-loader": "^7.0.0",
|
"babel-loader": "^7.0.0",
|
||||||
|
@ -28,27 +28,19 @@ const styles = {
|
|||||||
const PreviewHelp = () =>
|
const PreviewHelp = () =>
|
||||||
<div style={styles.main}>
|
<div style={styles.main}>
|
||||||
<h1>Welcome to storybook</h1>
|
<h1>Welcome to storybook</h1>
|
||||||
|
<p>This is a UI component dev environment for your app.</p>
|
||||||
<p>
|
<p>
|
||||||
This is a UI component dev environment for your app.
|
We've added some basic stories inside the <span style={styles.code}>
|
||||||
|
storybook/stories
|
||||||
|
</span>{' '}
|
||||||
|
directory. A story is a single state of one or more UI components. You can have as many
|
||||||
|
stories as you want. Basically a story is like a visual test case.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
We've added some basic stories inside the
|
To see your Storybook stories on the device, you should start your mobile app for the{' '}
|
||||||
{' '}
|
<span style={styles.code}><platform></span> of your choice (typically ios or android).
|
||||||
<span style={styles.code}>storybook/stories</span>
|
(Note that due to an implementation detail, your stories will only show up in the left-pane
|
||||||
{' '}
|
after your device has connected to this storybook server.)
|
||||||
directory.
|
|
||||||
{' '}
|
|
||||||
A story is a single state of one or more UI components. You can have as many stories as you
|
|
||||||
want. Basically a story is like a visual test case.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
To see your Storybook stories on the device, you should start your mobile app for the
|
|
||||||
{' '}
|
|
||||||
<span style={styles.code}><platform></span>
|
|
||||||
{' '}
|
|
||||||
of your choice (typically ios or android). (Note that due to an implementation detail, your
|
|
||||||
stories will only show up in the left-pane after your device has connected to this storybook
|
|
||||||
server.)
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
For <span style={styles.code}>create-react-native-app</span> apps:
|
For <span style={styles.code}>create-react-native-app</span> apps:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/react",
|
"name": "@storybook/react",
|
||||||
"version": "3.1.8",
|
"version": "3.1.9",
|
||||||
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
||||||
"homepage": "https://github.com/storybooks/storybook/tree/master/apps/react",
|
"homepage": "https://github.com/storybooks/storybook/tree/master/apps/react",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@ -22,11 +22,11 @@
|
|||||||
"prepublish": "node ../../scripts/prepublish.js"
|
"prepublish": "node ../../scripts/prepublish.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@storybook/addon-actions": "^3.1.8",
|
"@storybook/addon-actions": "^3.1.9",
|
||||||
"@storybook/addon-links": "^3.1.6",
|
"@storybook/addon-links": "^3.1.6",
|
||||||
"@storybook/addons": "^3.1.6",
|
"@storybook/addons": "^3.1.6",
|
||||||
"@storybook/channel-postmessage": "^3.1.6",
|
"@storybook/channel-postmessage": "^3.1.6",
|
||||||
"@storybook/ui": "^3.1.6",
|
"@storybook/ui": "^3.1.9",
|
||||||
"airbnb-js-shims": "^1.1.1",
|
"airbnb-js-shims": "^1.1.1",
|
||||||
"autoprefixer": "^7.1.1",
|
"autoprefixer": "^7.1.1",
|
||||||
"babel-core": "^6.24.1",
|
"babel-core": "^6.24.1",
|
||||||
@ -53,6 +53,7 @@
|
|||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"json-stringify-safe": "^5.0.1",
|
"json-stringify-safe": "^5.0.1",
|
||||||
"json5": "^0.5.1",
|
"json5": "^0.5.1",
|
||||||
|
"lodash.flattendeep": "^4.4.0",
|
||||||
"lodash.pick": "^4.4.0",
|
"lodash.pick": "^4.4.0",
|
||||||
"postcss-flexbugs-fixes": "^3.0.0",
|
"postcss-flexbugs-fixes": "^3.0.0",
|
||||||
"postcss-loader": "^2.0.5",
|
"postcss-loader": "^2.0.5",
|
||||||
|
41
app/react/src/client/preview/element_check.js
Normal file
41
app/react/src/client/preview/element_check.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import flattenDeep from 'lodash.flattendeep';
|
||||||
|
|
||||||
|
// return true if the element is renderable with react fiber
|
||||||
|
export const isValidFiberElement = element =>
|
||||||
|
typeof element === 'string' || typeof element === 'number' || React.isValidElement(element);
|
||||||
|
|
||||||
|
export const isPriorToFiber = version => {
|
||||||
|
const [majorVersion] = version.split('.');
|
||||||
|
|
||||||
|
return Number(majorVersion) < 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
// accepts an element and return true if renderable else return false
|
||||||
|
const isReactRenderable = element => {
|
||||||
|
// storybook is running with a version prior to fiber,
|
||||||
|
// run a simple check on the element
|
||||||
|
if (isPriorToFiber(React.version)) {
|
||||||
|
return React.isValidElement(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the element is not an array, check if its a fiber renderable element
|
||||||
|
if (!Array.isArray(element)) {
|
||||||
|
return isValidFiberElement(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the element is in fact a list of elements (array),
|
||||||
|
// loop on its elements to see if its ok to render them
|
||||||
|
const elementsList = element.map(isReactRenderable);
|
||||||
|
|
||||||
|
// flatten the list of elements (possibly deep nested)
|
||||||
|
const flatList = flattenDeep(elementsList);
|
||||||
|
|
||||||
|
// keep only invalid elements
|
||||||
|
const invalidElements = flatList.filter(elementIsRenderable => elementIsRenderable === false);
|
||||||
|
|
||||||
|
// it's ok to render this list if there is no invalid elements inside
|
||||||
|
return !invalidElements.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isReactRenderable;
|
86
app/react/src/client/preview/element_check.test.js
Normal file
86
app/react/src/client/preview/element_check.test.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import isReactRenderable, { isValidFiberElement, isPriorToFiber } from './element_check';
|
||||||
|
|
||||||
|
describe('element_check.utils.isValidFiberElement', () => {
|
||||||
|
it('should accept to render a string', () => {
|
||||||
|
const string = 'react is awesome';
|
||||||
|
|
||||||
|
expect(isValidFiberElement(string)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept to render a number', () => {
|
||||||
|
const number = 42;
|
||||||
|
|
||||||
|
expect(isValidFiberElement(number)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept to render a valid React element', () => {
|
||||||
|
const element = <button>Click me</button>;
|
||||||
|
|
||||||
|
expect(isValidFiberElement(element)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shouldn't accept to render an arbitrary object", () => {
|
||||||
|
const object = { key: 'bee bop' };
|
||||||
|
|
||||||
|
expect(isValidFiberElement(object)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shouldn't accept to render a function", () => {
|
||||||
|
const noop = () => {};
|
||||||
|
|
||||||
|
expect(isValidFiberElement(noop)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shouldn't accept to render undefined", () => {
|
||||||
|
expect(isValidFiberElement(undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('element_check.utils.isPriorToFiber', () => {
|
||||||
|
it('should return true if React version is prior to Fiber (< 16)', () => {
|
||||||
|
const oldVersion = '0.14.5';
|
||||||
|
const version = '15.5.4';
|
||||||
|
|
||||||
|
expect(isPriorToFiber(oldVersion)).toBe(true);
|
||||||
|
expect(isPriorToFiber(version)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if React version is using Fiber features (>= 16)', () => {
|
||||||
|
const alphaVersion = '16.0.0-alpha.13';
|
||||||
|
const version = '18.3.1';
|
||||||
|
|
||||||
|
expect(isPriorToFiber(alphaVersion)).toBe(false);
|
||||||
|
expect(isPriorToFiber(version)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('element_check.isReactRenderable', () => {
|
||||||
|
const string = 'yo';
|
||||||
|
const number = 1337;
|
||||||
|
const element = <span>what's up</span>;
|
||||||
|
const array = [string, number, element];
|
||||||
|
const object = { key: null };
|
||||||
|
|
||||||
|
it('allows rendering React elements only prior to React Fiber', () => {
|
||||||
|
// mutate version for the purpose of the test
|
||||||
|
React.version = '15.5.4';
|
||||||
|
|
||||||
|
expect(isReactRenderable(string)).toBe(false);
|
||||||
|
expect(isReactRenderable(number)).toBe(false);
|
||||||
|
expect(isReactRenderable(element)).toBe(true);
|
||||||
|
expect(isReactRenderable(array)).toBe(false);
|
||||||
|
expect(isReactRenderable(object)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows rendering string, numbers, arrays and React elements with React Fiber', () => {
|
||||||
|
// mutate version for the purpose of the test
|
||||||
|
React.version = '16.0.0-alpha.13';
|
||||||
|
|
||||||
|
expect(isReactRenderable(string)).toBe(true);
|
||||||
|
expect(isReactRenderable(number)).toBe(true);
|
||||||
|
expect(isReactRenderable(element)).toBe(true);
|
||||||
|
expect(isReactRenderable(array)).toBe(true);
|
||||||
|
expect(isReactRenderable(object)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -32,7 +32,9 @@ const codeStyle = {
|
|||||||
|
|
||||||
const ErrorDisplay = ({ error }) =>
|
const ErrorDisplay = ({ error }) =>
|
||||||
<div style={mainStyle}>
|
<div style={mainStyle}>
|
||||||
<div style={headingStyle}>{error.message}</div>
|
<div style={headingStyle}>
|
||||||
|
{error.message}
|
||||||
|
</div>
|
||||||
<pre style={codeStyle}>
|
<pre style={codeStyle}>
|
||||||
<code>
|
<code>
|
||||||
{error.stack}
|
{error.stack}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { stripIndents } from 'common-tags';
|
import { stripIndents } from 'common-tags';
|
||||||
|
import isReactRenderable from './element_check';
|
||||||
import ErrorDisplay from './error_display';
|
import ErrorDisplay from './error_display';
|
||||||
|
|
||||||
// check whether we're running on node/browser
|
// check whether we're running on node/browser
|
||||||
@ -83,13 +84,13 @@ export function renderMain(data, storyStore) {
|
|||||||
return renderError(error);
|
return renderError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element.type === undefined) {
|
if (!isReactRenderable(element)) {
|
||||||
const error = {
|
const error = {
|
||||||
title: `Expecting a valid React element from the story: "${selectedStory}" of "${selectedKind}".`,
|
title: `Expecting a valid React element from the story: "${selectedStory}" of "${selectedKind}".`,
|
||||||
description: stripIndents`
|
description: stripIndents`
|
||||||
Seems like you are not returning a correct React element from the story.
|
Seems like you are not returning a correct React element from the story.
|
||||||
Could you double check that?
|
Could you double check that?
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
return renderError(error);
|
return renderError(error);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,10 @@ export default function(configType, baseConfig, configDir) {
|
|||||||
...config.module,
|
...config.module,
|
||||||
// We need to use our and custom rules.
|
// We need to use our and custom rules.
|
||||||
...customConfig.module,
|
...customConfig.module,
|
||||||
rules: [...config.module.rules, ...(customConfig.module.rules || [])],
|
rules: [
|
||||||
|
...config.module.rules,
|
||||||
|
...((customConfig.module && customConfig.module.rules) || []),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
...config.resolve,
|
...config.resolve,
|
||||||
|
@ -8,7 +8,9 @@ import './style.css';
|
|||||||
const DocsContent = ({ title, content, editUrl }) =>
|
const DocsContent = ({ title, content, editUrl }) =>
|
||||||
<div id="docs-content">
|
<div id="docs-content">
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<h2 className="title">{title}</h2>
|
<h2 className="title">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
<a className="edit-link" href={editUrl} target="_blank" rel="noopener noreferrer">
|
<a className="edit-link" href={editUrl} target="_blank" rel="noopener noreferrer">
|
||||||
Edit this page
|
Edit this page
|
||||||
|
@ -24,11 +24,19 @@ class Nav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderNavOpts(nav) {
|
renderNavOpts(nav) {
|
||||||
return <option value={nav.id} key={nav.id}>{nav.title}</option>;
|
return (
|
||||||
|
<option value={nav.id} key={nav.id}>
|
||||||
|
{nav.title}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHeadingOpts(section) {
|
renderHeadingOpts(section) {
|
||||||
return <option value={section.id} key={section.id}>{section.heading}</option>;
|
return (
|
||||||
|
<option value={section.id} key={section.id}>
|
||||||
|
{section.heading}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { sections, selectedSection, selectedItem } = this.props;
|
const { sections, selectedSection, selectedItem } = this.props;
|
||||||
|
@ -7,18 +7,21 @@ const Nav = ({ sections, selectedSectionId, selectedItemId }) =>
|
|||||||
<div id="nav">
|
<div id="nav">
|
||||||
{sections.map(section =>
|
{sections.map(section =>
|
||||||
<div key={section.id}>
|
<div key={section.id}>
|
||||||
<h3>{section.heading}</h3>
|
<h3>
|
||||||
|
{section.heading}
|
||||||
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
{section.items.map(item => {
|
{section.items.map(item => {
|
||||||
const cssClass = section.id === selectedSectionId && item.id === selectedItemId
|
const cssClass =
|
||||||
? 'selected'
|
section.id === selectedSectionId && item.id === selectedItemId ? 'selected' : '';
|
||||||
: '';
|
|
||||||
|
|
||||||
const url = `/${section.id}/${item.id}/`;
|
const url = `/${section.id}/${item.id}/`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={item.id}>
|
<li key={item.id}>
|
||||||
<Link className={cssClass} to={url}>{item.title}</Link>
|
<Link className={cssClass} to={url}>
|
||||||
|
{item.title}
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -10,11 +10,7 @@ const Footer = () =>
|
|||||||
<div className="row logos">
|
<div className="row logos">
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
<center>
|
<center>
|
||||||
Maintained by the
|
Maintained by the <Link to="/basics/community/">Storybook Community</Link>
|
||||||
{' '}
|
|
||||||
<Link to="/basics/community/">
|
|
||||||
Storybook Community
|
|
||||||
</Link>
|
|
||||||
.
|
.
|
||||||
</center>
|
</center>
|
||||||
<center>
|
<center>
|
||||||
|
@ -14,11 +14,23 @@ const GridItem = ({ title, description, source, demo, thumbnail }) =>
|
|||||||
<div className="overlay" />
|
<div className="overlay" />
|
||||||
</div>
|
</div>
|
||||||
<div className="text">
|
<div className="text">
|
||||||
<h2>{title}</h2>
|
<h2>
|
||||||
<p className="desc">{description}</p>
|
{title}
|
||||||
|
</h2>
|
||||||
|
<p className="desc">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
<div className="button-row">
|
<div className="button-row">
|
||||||
{demo ? <a href={demo} {...linkProps}>Demo</a> : null}
|
{demo
|
||||||
{source ? <a href={source} {...linkProps}>Source</a> : null}
|
? <a href={demo} {...linkProps}>
|
||||||
|
Demo
|
||||||
|
</a>
|
||||||
|
: null}
|
||||||
|
{source
|
||||||
|
? <a href={source} {...linkProps}>
|
||||||
|
Source
|
||||||
|
</a>
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -17,7 +17,9 @@ const Item = ({ storybook, owner, source }) =>
|
|||||||
{storybook.name}
|
{storybook.name}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<a href={source} target="_blank" rel="noopener noreferrer">source</a>
|
<a href={source} target="_blank" rel="noopener noreferrer">
|
||||||
|
source
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
Item.propTypes = {
|
Item.propTypes = {
|
||||||
|
@ -46,23 +46,37 @@ const MainLinks = () =>
|
|||||||
id="search"
|
id="search"
|
||||||
placeholder="type to search"
|
placeholder="type to search"
|
||||||
/>
|
/>
|
||||||
<span className="form-control-feedback" aria-hidden="true">🔍</span>
|
<span className="form-control-feedback" aria-hidden="true">
|
||||||
|
🔍
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-sm-4 read-docs">
|
<div className="col-sm-4 read-docs">
|
||||||
<Link to="/basics/introduction/"><h3>Basics</h3></Link>
|
<Link to="/basics/introduction/">
|
||||||
|
<h3>Basics</h3>
|
||||||
|
</Link>
|
||||||
<ul>
|
<ul>
|
||||||
<li><Link to="/basics/quick-start-guide/">Quick setup</Link></li>
|
<li>
|
||||||
<li><Link to="/basics/slow-start-guide/">Adding to existing project</Link></li>
|
<Link to="/basics/quick-start-guide/">Quick setup</Link>
|
||||||
<li><Link to="/basics/writing-stories/">Writing stories</Link></li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link to="/basics/slow-start-guide/">Adding to existing project</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link to="/basics/writing-stories/">Writing stories</Link>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-sm-4 read-docs">
|
<div className="col-sm-4 read-docs">
|
||||||
<Link to="/configurations/default-config/"><h3>Configuration</h3></Link>
|
<Link to="/configurations/default-config/">
|
||||||
|
<h3>Configuration</h3>
|
||||||
|
</Link>
|
||||||
<ul>
|
<ul>
|
||||||
<li><Link to="/configurations/custom-babel-config/">Babel configurations</Link></li>
|
<li>
|
||||||
|
<Link to="/configurations/custom-babel-config/">Babel configurations</Link>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link to="/configurations/custom-webpack-config/">Webpack configurations</Link>
|
<Link to="/configurations/custom-webpack-config/">Webpack configurations</Link>
|
||||||
</li>
|
</li>
|
||||||
@ -76,9 +90,13 @@ const MainLinks = () =>
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-sm-4 read-docs">
|
<div className="col-sm-4 read-docs">
|
||||||
<Link to="/configurations/default-config/"><h3>Addons</h3></Link>
|
<Link to="/configurations/default-config/">
|
||||||
|
<h3>Addons</h3>
|
||||||
|
</Link>
|
||||||
<ul>
|
<ul>
|
||||||
<li><Link to="/addons/introduction/">Intro to Addons</Link></li>
|
<li>
|
||||||
|
<Link to="/addons/introduction/">Intro to Addons</Link>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link to="/addons/using-addons/">Using Addons</Link>
|
<Link to="/addons/using-addons/">Using Addons</Link>
|
||||||
</li>
|
</li>
|
||||||
|
@ -6,17 +6,14 @@ const Platform = () =>
|
|||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
<h3 className="built-for">Built for</h3>
|
<h3 className="built-for">Built for</h3>
|
||||||
<p className="platforms">
|
<p className="platforms">
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://github.com/storybooks/storybook/tree/master/app/react"
|
href="https://github.com/storybooks/storybook/tree/master/app/react"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
React
|
React
|
||||||
</a>
|
</a>{' '}
|
||||||
{' '}
|
&{' '}
|
||||||
&
|
|
||||||
{' '}
|
|
||||||
<a
|
<a
|
||||||
href="https://github.com/storybooks/storybook/tree/master/app/react-native"
|
href="https://github.com/storybooks/storybook/tree/master/app/react-native"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -67,9 +67,9 @@ const UsedBy = ({ users }) =>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Link to="/examples/" className="used-by-more-examples">
|
<div className="used-by-more-examples">
|
||||||
See more examples…
|
<Link to="/examples/">See more examples…</Link>
|
||||||
</Link>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
UsedBy.propTypes = {
|
UsedBy.propTypes = {
|
||||||
users: PropTypes.array, // eslint-disable-line
|
users: PropTypes.array, // eslint-disable-line
|
||||||
|
@ -63,5 +63,13 @@
|
|||||||
.used-by-more-examples {
|
.used-by-more-examples {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 10px;
|
margin-top: 50px;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.used-by-more-examples a {
|
||||||
|
background-color: #e4004f;
|
||||||
|
color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,9 @@ const HTML = props => {
|
|||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{title}</title>
|
<title>
|
||||||
|
{title}
|
||||||
|
</title>
|
||||||
<link rel="icon" href={favicon} type="image/x-icon" />
|
<link rel="icon" href={favicon} type="image/x-icon" />
|
||||||
{css}
|
{css}
|
||||||
</head>
|
</head>
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
"color-pairs-picker": "^1.3.5",
|
"color-pairs-picker": "^1.3.5",
|
||||||
"docsearch.js": "^2.3.3",
|
"docsearch.js": "^2.3.3",
|
||||||
"front-matter": "^2.1.2",
|
"front-matter": "^2.1.2",
|
||||||
"gatsby": "^0.12.45",
|
"gatsby": "0.12.48",
|
||||||
"gh-pages": "^0.12.0",
|
"gh-pages": "^1.0.0",
|
||||||
"global": "^4.3.2",
|
"global": "^4.3.2",
|
||||||
"highlight.js": "^9.12.0",
|
"highlight.js": "^9.12.0",
|
||||||
"loader-utils": "^1.1.0",
|
"loader-utils": "^1.1.0",
|
||||||
|
@ -97,3 +97,7 @@ With this addon you will have an additional panel at the bottom which provides y
|
|||||||
### [Versions](https://github.com/buildit/storybook-addon-versions)
|
### [Versions](https://github.com/buildit/storybook-addon-versions)
|
||||||
|
|
||||||
This addon lets you navigate different versions of static Storybook builds. As such you can see how a component has changed over time.
|
This addon lets you navigate different versions of static Storybook builds. As such you can see how a component has changed over time.
|
||||||
|
|
||||||
|
### [Apollo](https://github.com/abhiaiyer91/apollo-storybook-decorator)
|
||||||
|
|
||||||
|
Wrap your stories with the Apollo client for mocking GraphQL queries/mutations.
|
||||||
|
@ -65,6 +65,8 @@ configure(loadStories, module);
|
|||||||
|
|
||||||
Here we use Webpack's [require.context](https://webpack.github.io/docs/context.html#require-context) to load modules dynamically. Have a look at the relevant Webpack [docs](https://webpack.github.io/docs/context.html#require-context) to learn more about how to use require.context.
|
Here we use Webpack's [require.context](https://webpack.github.io/docs/context.html#require-context) to load modules dynamically. Have a look at the relevant Webpack [docs](https://webpack.github.io/docs/context.html#require-context) to learn more about how to use require.context.
|
||||||
|
|
||||||
|
The **React Native** packager resolves all the imports at build-time, so it's not possible to load modules dynamically. If you don't want to import all your stories manually you can use [react-native-storybook-loader](https://github.com/elderfo/react-native-storybook-loader) to automatically create the import statements for all of your stories.
|
||||||
|
|
||||||
## Using Decorators
|
## Using Decorators
|
||||||
|
|
||||||
A decorator is a way to wrap a story with a common set of component(s). Let's say you want to center all your stories. Here is how we can do this with a decorator:
|
A decorator is a way to wrap a story with a common set of component(s). Let's say you want to center all your stories. Here is how we can do this with a decorator:
|
||||||
|
@ -25,6 +25,13 @@ algolia:
|
|||||||
description: Lightning-fast, hyper-configurable search.
|
description: Lightning-fast, hyper-configurable search.
|
||||||
source: https://github.com/algolia/react-instantsearch/
|
source: https://github.com/algolia/react-instantsearch/
|
||||||
demo: https://community.algolia.com/react-instantsearch/storybook/
|
demo: https://community.algolia.com/react-instantsearch/storybook/
|
||||||
|
rebass:
|
||||||
|
thumbnail: ./thumbnails/rebass.png
|
||||||
|
title: Rebass
|
||||||
|
description: Functional React UI component library
|
||||||
|
demo: http://jxnblk.com/rebass/stories/
|
||||||
|
source: https://github.com/jxnblk/rebass
|
||||||
|
site: http://jxnblk.com/rebass
|
||||||
coursera:
|
coursera:
|
||||||
thumbnail: ./thumbnails/coursera-ui.png
|
thumbnail: ./thumbnails/coursera-ui.png
|
||||||
title: Coursera
|
title: Coursera
|
||||||
@ -34,7 +41,7 @@ artsy:
|
|||||||
thumbnail: ./thumbnails/artsy.png
|
thumbnail: ./thumbnails/artsy.png
|
||||||
title: Artsy Force
|
title: Artsy Force
|
||||||
description: Artsy's "Force" component library
|
description: Artsy's "Force" component library
|
||||||
demo: https://artsy.github.io/reaction-force/
|
demo: https://artsy.github.io/reaction/
|
||||||
source: https://github.com/artsy/reaction-force
|
source: https://github.com/artsy/reaction-force
|
||||||
site: https://artsy.net
|
site: https://artsy.net
|
||||||
necolas:
|
necolas:
|
||||||
|
BIN
docs/pages/examples/thumbnails/rebass.png
Normal file
BIN
docs/pages/examples/thumbnails/rebass.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
@ -34,31 +34,28 @@ Then, install StoryShots into your app with:
|
|||||||
npm i -D @storybook/addon-storyshots
|
npm i -D @storybook/addon-storyshots
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, add the following NPM script into your package.json:
|
Then, assuming you are using Jest for testing, you can create a test file `storyshots.test.js` that contains the following:
|
||||||
|
|
||||||
```json
|
```js
|
||||||
{
|
import initStoryshots from '@storybook/addon-storyshots';
|
||||||
"scripts": {
|
|
||||||
"test-storybook": "storyshots"
|
initStoryshots({ /* configuration options */ });
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can run the above command with:
|
Now you can snapshot test all of your stories with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm run test-storybook
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
This will save the initial set of snapshots inside your Storybook config directory.
|
This will save the initial set of snapshots inside your Storybook config directory.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
After you complete any changes, you can run the above NPM script again and find our structural changes.
|
After you complete any changes, you can run the test again and find all structural changes.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
* * *
|
* * *
|
||||||
|
|
||||||
StoryShots also comes with a few important [productive features](https://github.com/storybooks/storybook/tree/master/addons/storyshots#key-features) that can be customized.
|
StoryShots also comes with a variety of customization options. Have a look at the StoryShots [repo](https://github.com/storybooks/storybook/tree/master/addons/storyshots) for more information.
|
||||||
Have a look at the StoryShots [repo](https://github.com/storybooks/storybook/tree/master/addons/storyshots) for more information.
|
|
||||||
|
@ -10,7 +10,9 @@ const Markdown = ({ route }) => {
|
|||||||
return (
|
return (
|
||||||
<DocumentTitle title={`${post.title} | ${config.siteTitle}`}>
|
<DocumentTitle title={`${post.title} | ${config.siteTitle}`}>
|
||||||
<div className="markdown">
|
<div className="markdown">
|
||||||
<h1>{post.title}</h1>
|
<h1>
|
||||||
|
{post.title}
|
||||||
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
<a className="edit-link" href={editUrl} target="_blank" rel="noopener noreferrer">
|
<a className="edit-link" href={editUrl} target="_blank" rel="noopener noreferrer">
|
||||||
Edit this page
|
Edit this page
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
"@storybook/addon-storyshots": "^3.0.0",
|
"@storybook/addon-storyshots": "^3.0.0",
|
||||||
"@storybook/addons": "^3.0.0",
|
"@storybook/addons": "^3.0.0",
|
||||||
"@storybook/react": "^3.0.0",
|
"@storybook/react": "^3.0.0",
|
||||||
"react-scripts": "1.0.1"
|
"react-scripts": "1.0.10"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,12 @@ export default class Logger extends Component {
|
|||||||
<dl>
|
<dl>
|
||||||
{events.map(({ id, name, payload }) =>
|
{events.map(({ id, name, payload }) =>
|
||||||
<div style={styles.item} key={id}>
|
<div style={styles.item} key={id}>
|
||||||
<dt><b>Event name:</b> {name}</dt>
|
<dt>
|
||||||
<dd><b>Event payload:</b> {json.plain(payload)}</dd>
|
<b>Event name:</b> {name}
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<b>Event payload:</b> {json.plain(payload)}
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</dl>
|
</dl>
|
||||||
|
@ -74,14 +74,26 @@ storiesOf('Button', module)
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={style}>
|
<div style={style}>
|
||||||
<p>{intro}</p>
|
<p>
|
||||||
<p>My birthday is: {new Date(birthday).toLocaleDateString()}</p>
|
{intro}
|
||||||
<p>My wallet contains: ${dollars.toFixed(2)}</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
My birthday is: {new Date(birthday).toLocaleDateString()}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
My wallet contains: ${dollars.toFixed(2)}
|
||||||
|
</p>
|
||||||
<p>In my backpack, I have:</p>
|
<p>In my backpack, I have:</p>
|
||||||
<ul>
|
<ul>
|
||||||
{items.map(item => <li key={item}>{item}</li>)}
|
{items.map(item =>
|
||||||
|
<li key={item}>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
<p>{salutation}</p>
|
<p>
|
||||||
|
{salutation}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -12,7 +12,11 @@ import Welcome from './Welcome';
|
|||||||
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
||||||
|
|
||||||
storiesOf('Button', module)
|
storiesOf('Button', module)
|
||||||
.addDecorator(getStory => <CenterView>{getStory()}</CenterView>)
|
.addDecorator(getStory =>
|
||||||
|
<CenterView>
|
||||||
|
{getStory()}
|
||||||
|
</CenterView>
|
||||||
|
)
|
||||||
.add('with text', () =>
|
.add('with text', () =>
|
||||||
<Button onPress={action('clicked-text')}>
|
<Button onPress={action('clicked-text')}>
|
||||||
<Text>Hello Button</Text>
|
<Text>Hello Button</Text>
|
||||||
|
@ -23,5 +23,5 @@
|
|||||||
"examples/*"
|
"examples/*"
|
||||||
],
|
],
|
||||||
"concurrency": 1,
|
"concurrency": 1,
|
||||||
"version": "3.1.8"
|
"version": "3.1.9"
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,11 @@ import Welcome from './Welcome';
|
|||||||
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
||||||
|
|
||||||
storiesOf('Button', module)
|
storiesOf('Button', module)
|
||||||
.addDecorator(getStory => <CenterView>{getStory()}</CenterView>)
|
.addDecorator(getStory =>
|
||||||
|
<CenterView>
|
||||||
|
{getStory()}
|
||||||
|
</CenterView>
|
||||||
|
)
|
||||||
.add('with text', () =>
|
.add('with text', () =>
|
||||||
<Button onPress={action('clicked-text')}>
|
<Button onPress={action('clicked-text')}>
|
||||||
<Text>Hello Button</Text>
|
<Text>Hello Button</Text>
|
||||||
|
@ -12,7 +12,11 @@ import Welcome from './Welcome';
|
|||||||
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
|
||||||
|
|
||||||
storiesOf('Button', module)
|
storiesOf('Button', module)
|
||||||
.addDecorator(getStory => <CenterView>{getStory()}</CenterView>)
|
.addDecorator(getStory =>
|
||||||
|
<CenterView>
|
||||||
|
{getStory()}
|
||||||
|
</CenterView>
|
||||||
|
)
|
||||||
.add('with text', () =>
|
.add('with text', () =>
|
||||||
<Button onPress={action('clicked-text')}>
|
<Button onPress={action('clicked-text')}>
|
||||||
<Text>Hello Button</Text>
|
<Text>Hello Button</Text>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/cli",
|
"name": "@storybook/cli",
|
||||||
"version": "3.1.6",
|
"version": "3.1.9",
|
||||||
"description": "Storybook's CLI - easiest method of adding storybook to your projects",
|
"description": "Storybook's CLI - easiest method of adding storybook to your projects",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cli",
|
"cli",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@storybook/ui",
|
"name": "@storybook/ui",
|
||||||
"version": "3.1.6",
|
"version": "3.1.9",
|
||||||
"description": "Core Storybook UI",
|
"description": "Core Storybook UI",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
@ -40,16 +40,16 @@ class DownPanel extends Component {
|
|||||||
if (name === this.props.selectedPanel) {
|
if (name === this.props.selectedPanel) {
|
||||||
Object.assign(panelStyle, { flex: 1, display: 'flex' });
|
Object.assign(panelStyle, { flex: 1, display: 'flex' });
|
||||||
}
|
}
|
||||||
return <div key={name} style={panelStyle} role="tabpanel">{panel.render()}</div>;
|
return (
|
||||||
|
<div key={name} style={panelStyle} role="tabpanel">
|
||||||
|
{panel.render()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEmpty() {
|
renderEmpty() {
|
||||||
return (
|
return <div style={style.empty}>no panels available</div>;
|
||||||
<div style={style.empty}>
|
|
||||||
no panels available
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -58,8 +58,12 @@ class DownPanel extends Component {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div style={style.wrapper}>
|
<div style={style.wrapper}>
|
||||||
<div style={style.tabbar} role="tablist">{this.renderTabs()}</div>
|
<div style={style.tabbar} role="tablist">
|
||||||
<div style={style.content}>{this.renderPanels()}</div>
|
{this.renderTabs()}
|
||||||
|
</div>
|
||||||
|
<div style={style.content}>
|
||||||
|
{this.renderPanels()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,9 @@ class Layout extends React.Component {
|
|||||||
showLeftPanel,
|
showLeftPanel,
|
||||||
() =>
|
() =>
|
||||||
<div style={leftPanelStyle(leftPanelOnTop)}>
|
<div style={leftPanelStyle(leftPanelOnTop)}>
|
||||||
<div style={{ flexGrow: 1, height: '100%' }}>{leftPanel()}</div>
|
<div style={{ flexGrow: 1, height: '100%' }}>
|
||||||
|
{leftPanel()}
|
||||||
|
</div>
|
||||||
<USplit shift={5} split={storiesSplit} />
|
<USplit shift={5} split={storiesSplit} />
|
||||||
</div>,
|
</div>,
|
||||||
() => <span />
|
() => <span />
|
||||||
|
@ -50,9 +50,13 @@ const linkStyle = {
|
|||||||
|
|
||||||
const Header = ({ openShortcutsHelp, name, url }) =>
|
const Header = ({ openShortcutsHelp, name, url }) =>
|
||||||
<div style={wrapperStyle}>
|
<div style={wrapperStyle}>
|
||||||
<button style={shortcutIconStyle} onClick={openShortcutsHelp}>⌘</button>
|
<button style={shortcutIconStyle} onClick={openShortcutsHelp}>
|
||||||
|
⌘
|
||||||
|
</button>
|
||||||
<a style={linkStyle} href={url} target="_blank" rel="noopener noreferrer">
|
<a style={linkStyle} href={url} target="_blank" rel="noopener noreferrer">
|
||||||
<h3 style={headingStyle}>{name}</h3>
|
<h3 style={headingStyle}>
|
||||||
|
{name}
|
||||||
|
</h3>
|
||||||
</a>
|
</a>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
|
@ -62,19 +62,31 @@ export function getShortcuts(platform) {
|
|||||||
export const Keys = ({ shortcutKeys }) => {
|
export const Keys = ({ shortcutKeys }) => {
|
||||||
// if we have only one key combination for a shortcut
|
// if we have only one key combination for a shortcut
|
||||||
if (shortcutKeys.length === 1) {
|
if (shortcutKeys.length === 1) {
|
||||||
return <span><b style={commandStyle}>{shortcutKeys[0]}</b></span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<b style={commandStyle}>
|
||||||
|
{shortcutKeys[0]}
|
||||||
|
</b>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have multiple key combinations for a shortcut
|
// if we have multiple key combinations for a shortcut
|
||||||
const keys = shortcutKeys.map((key, index, arr) =>
|
const keys = shortcutKeys.map((key, index, arr) =>
|
||||||
<span key={key}>
|
<span key={key}>
|
||||||
<b style={commandStyle}>{key}</b>
|
<b style={commandStyle}>
|
||||||
|
{key}
|
||||||
|
</b>
|
||||||
{/* add / & space if it is not a last key combination */}
|
{/* add / & space if it is not a last key combination */}
|
||||||
{arr.length - 1 !== index ? <span>/ </span> : ''}
|
{arr.length - 1 !== index ? <span>/ </span> : ''}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <span>{keys}</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
{keys}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Keys.propTypes = {
|
Keys.propTypes = {
|
||||||
|
12
package.json
12
package.json
@ -39,9 +39,9 @@
|
|||||||
"babel-preset-env": "^1.5.1",
|
"babel-preset-env": "^1.5.1",
|
||||||
"babel-preset-react": "^6.24.1",
|
"babel-preset-react": "^6.24.1",
|
||||||
"babel-preset-stage-0": "^6.24.1",
|
"babel-preset-stage-0": "^6.24.1",
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^2.0.1",
|
||||||
"codecov": "^2.2.0",
|
"codecov": "^2.2.0",
|
||||||
"danger": "^0.21.0",
|
"danger": "^1.0.0",
|
||||||
"enzyme": "^2.8.2",
|
"enzyme": "^2.8.2",
|
||||||
"eslint": "^3.19.0",
|
"eslint": "^3.19.0",
|
||||||
"eslint-config-airbnb": "^15.0.1",
|
"eslint-config-airbnb": "^15.0.1",
|
||||||
@ -54,16 +54,14 @@
|
|||||||
"eslint-plugin-react": "^7.0.1",
|
"eslint-plugin-react": "^7.0.1",
|
||||||
"gh-pages": "^1.0.0",
|
"gh-pages": "^1.0.0",
|
||||||
"github-release-from-changelog": "^1.2.1",
|
"github-release-from-changelog": "^1.2.1",
|
||||||
"husky": "^0.13.4",
|
"husky": "^0.14.3",
|
||||||
"jest": "^20.0.4",
|
"jest": "^20.0.4",
|
||||||
"jest-enzyme": "^3.2.0",
|
"jest-enzyme": "^3.2.0",
|
||||||
"lerna": "2.0.0",
|
"lerna": "2.0.0",
|
||||||
"lint-staged": "^4.0.0",
|
"lint-staged": "^4.0.0",
|
||||||
"markdown-it-anchor": "^4.0.0",
|
|
||||||
"markdownlint-cli": "^0.3.1",
|
|
||||||
"nodemon": "^1.11.0",
|
"nodemon": "^1.11.0",
|
||||||
"npmc": "^5.0.3-canary.12",
|
"npmc": "^5.1.0-canary.2",
|
||||||
"prettier": "^1.3.1",
|
"prettier": "^1.5.2",
|
||||||
"react": "^15.5.4",
|
"react": "^15.5.4",
|
||||||
"react-dom": "^15.5.4",
|
"react-dom": "^15.5.4",
|
||||||
"react-test-renderer": "^15.5.4",
|
"react-test-renderer": "^15.5.4",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user