diff --git a/addons/info/package.json b/addons/info/package.json
index 6a880a325b10..394881b11a77 100644
--- a/addons/info/package.json
+++ b/addons/info/package.json
@@ -19,7 +19,8 @@
"global": "^4.3.2",
"marksy": "^2.0.0",
"prop-types": "^15.5.8",
- "react-addons-create-fragment": "^15.5.3"
+ "react-addons-create-fragment": "^15.5.3",
+ "util-deprecate": "^1.0.2"
},
"devDependencies": {
"git-url-parse": "^6.2.2",
diff --git a/addons/info/src/components/PropVal.js b/addons/info/src/components/PropVal.js
index 13901ab87fef..2012528afd7c 100644
--- a/addons/info/src/components/PropVal.js
+++ b/addons/info/src/components/PropVal.js
@@ -115,9 +115,16 @@ export default function PropVal(props) {
return {content} ;
}
+PropVal.defaultProps = {
+ val: null,
+ maxPropObjectKeys: 3,
+ maxPropArrayLength: 3,
+ maxPropStringLength: 50,
+};
+
PropVal.propTypes = {
- val: PropTypes.any.isRequired, // eslint-disable-line
- maxPropObjectKeys: PropTypes.number.isRequired,
- maxPropArrayLength: PropTypes.number.isRequired,
- maxPropStringLength: PropTypes.number.isRequired,
+ val: PropTypes.any, // eslint-disable-line
+ maxPropObjectKeys: PropTypes.number,
+ maxPropArrayLength: PropTypes.number,
+ maxPropStringLength: PropTypes.number,
};
diff --git a/addons/info/src/index.js b/addons/info/src/index.js
index 4567ed366ba5..3ff306f3ee55 100644
--- a/addons/info/src/index.js
+++ b/addons/info/src/index.js
@@ -1,7 +1,12 @@
import React from 'react';
+import deprecate from 'util-deprecate';
import _Story from './components/Story';
import { H1, H2, H3, H4, H5, H6, Code, P, UL, A, LI } from './components/markdown';
+function addonCompose(addonFn) {
+ return storyFn => context => addonFn(storyFn, context);
+}
+
export const Story = _Story;
const defaultOptions = {
@@ -29,59 +34,62 @@ const defaultMarksyConf = {
ul: UL,
};
-export default {
- addWithInfo(storyName, info, storyFn, _options) {
- if (typeof storyFn !== 'function') {
- if (typeof info === 'function') {
+export function addInfo(storyFn, context, info, _options) {
+ if (typeof storyFn !== 'function') {
+ if (typeof info === 'function') {
_options = storyFn; // eslint-disable-line
storyFn = info; // eslint-disable-line
info = ''; // eslint-disable-line
- } else {
- throw new Error('No story defining function has been specified');
- }
+ } else {
+ throw new Error('No story defining function has been specified');
}
+ }
- const options = {
- ...defaultOptions,
- ..._options,
- };
+ const options = {
+ ...defaultOptions,
+ ..._options,
+ };
- // props.propTables can only be either an array of components or null
- // propTables option is allowed to be set to 'false' (a boolean)
- // if the option is false, replace it with null to avoid react warnings
- if (!options.propTables) {
- options.propTables = null;
- }
+ // props.propTables can only be either an array of components or null
+ // propTables option is allowed to be set to 'false' (a boolean)
+ // if the option is false, replace it with null to avoid react warnings
+ if (!options.propTables) {
+ options.propTables = null;
+ }
- const marksyConf = { ...defaultMarksyConf };
- if (options && options.marksyConf) {
- Object.assign(marksyConf, options.marksyConf);
- }
+ const marksyConf = { ...defaultMarksyConf };
+ if (options && options.marksyConf) {
+ Object.assign(marksyConf, options.marksyConf);
+ }
+ const props = {
+ info,
+ context,
+ showInline: Boolean(options.inline),
+ showHeader: Boolean(options.header),
+ showSource: Boolean(options.source),
+ propTables: options.propTables,
+ propTablesExclude: options.propTablesExclude,
+ styles: typeof options.styles === 'function' ? options.styles : s => s,
+ marksyConf,
+ maxPropObjectKeys: options.maxPropObjectKeys,
+ maxPropArrayLength: options.maxPropArrayLength,
+ maxPropsIntoLine: options.maxPropsIntoLine,
+ maxPropStringLength: options.maxPropStringLength,
+ };
+ return (
+
+ {storyFn(context)}
+
+ );
+}
- return this.add(storyName, context => {
- const props = {
- info,
- context,
- showInline: Boolean(options.inline),
- showHeader: Boolean(options.header),
- showSource: Boolean(options.source),
- propTables: options.propTables,
- propTablesExclude: options.propTablesExclude,
- styles: typeof options.styles === 'function' ? options.styles : s => s,
- marksyConf,
- maxPropObjectKeys: options.maxPropObjectKeys,
- maxPropArrayLength: options.maxPropArrayLength,
- maxPropsIntoLine: options.maxPropsIntoLine,
- maxPropStringLength: options.maxPropStringLength,
- };
+export const withInfo = (info, _options) =>
+ addonCompose((storyFn, context) => addInfo(storyFn, context, info, _options));
- return (
-
- {storyFn(context)}
-
- );
- });
- },
+export default {
+ addWithInfo: deprecate(function addWithInfo(storyName, info, storyFn, _options) {
+ return this.add(storyName, withInfo(info, _options)(storyFn));
+ }, '@storybook/addon-info .addWithInfo() addon is deprecated, use withInfo() from the same package instead. \nSee https://github.com/storybooks/storybook/tree/master/addons/info'),
};
export function setDefaults(newDefaults) {
diff --git a/addons/info/src/index.test.js b/addons/info/src/index.test.js
new file mode 100644
index 000000000000..afbae389ce2c
--- /dev/null
+++ b/addons/info/src/index.test.js
@@ -0,0 +1,59 @@
+/* global document */
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import AddonInfo, { withInfo, setDefaults, addInfo } from './';
+
+/* eslint-disable */
+const TestComponent = ({ func, obj, array, number, string, bool, empty }) =>
+
+
{func}
+
{obj.toString()}
+
{array}
+
{number}
+
{string}
+
{bool}
+
{empty}
+
test
+
storiesOf
+
+ 1
+ 2
+
+
;
+/* eslint-enable */
+
+const testContext = { kind: 'addon_info', story: 'jest_test' };
+const testOptions = { propTables: false };
+
+describe('addon Info', () => {
+ const story = context =>
+
+ It's a {context.story} story:
+ x + 1}
+ obj={{ a: 'a', b: 'b' }}
+ array={[1, 2, 3]}
+ number={7}
+ string={'seven'}
+ bool
+ />
+
;
+ const api = {
+ add: (name, fn) => fn(testContext),
+ };
+ it('should render and markdown', () => {
+ const Info = withInfo(
+ '# Test story \n## with markdown info \ncontaing **bold**, *cursive* text and `code`'
+ )(story);
+ ReactDOM.render( , document.createElement('div'));
+ });
+ it('should render with missed info', () => {
+ setDefaults(testOptions);
+ addInfo(null, testContext, story, testOptions);
+ });
+ it('should show deprecation warning', () => {
+ const addWithInfo = AddonInfo.addWithInfo.bind(api);
+ addWithInfo('jest', story);
+ });
+});
diff --git a/examples/cra-kitchen-sink/src/stories/index.js b/examples/cra-kitchen-sink/src/stories/index.js
index 9c34858322d8..e308ad065114 100644
--- a/examples/cra-kitchen-sink/src/stories/index.js
+++ b/examples/cra-kitchen-sink/src/stories/index.js
@@ -19,6 +19,7 @@ import {
object,
} from '@storybook/addon-knobs';
import centered from '@storybook/addon-centered';
+import { withInfo } from '@storybook/addon-info';
import { Button, Welcome } from '@storybook/react/demo';
@@ -37,6 +38,22 @@ const emit = emiter.emit.bind(emiter);
storiesOf('Welcome', module).add('to Storybook', () => );
+const InfoButton = () =>
+
+ {' '}Show Info{' '}
+ ;
+
storiesOf('Button', module)
.addDecorator(withKnobs)
.add('with text', () => Hello Button )
@@ -75,21 +92,56 @@ storiesOf('Button', module)
return (
-
{intro}
-
My birthday is: {new Date(birthday).toLocaleDateString()}
-
My wallet contains: ${dollars.toFixed(2)}
+
+ {intro}
+
+
+ My birthday is: {new Date(birthday).toLocaleDateString()}
+
+
+ My wallet contains: ${dollars.toFixed(2)}
+
In my backpack, I have:
- {items.map(item => {item} )}
+ {items.map(item =>
+
+ {item}
+
+ )}
-
{salutation}
+
+ {salutation}
+
);
})
.addWithInfo(
'with some info',
'Use the [info addon](https://github.com/storybooks/storybook/tree/master/addons/info) with its painful API.',
- () => click the "?" in top right for info
+ context =>
+
+ click the label in top right for info about "{context.story}"
+
+ )
+ .add(
+ 'with new info',
+ withInfo(
+ 'Use the [info addon](https://github.com/storybooks/storybook/tree/master/addons/info) with its new painless API.'
+ )(context =>
+
+ click the label in top right for info about "{context.story}"
+
+ )
+ )
+ .add(
+ 'addons composition',
+ withInfo('see Notes panel for composition info')(
+ addonNotes({ notes: 'Composition: Info(Notes())' })(context =>
+
+ click the label in top right for info about "{context.story}"
+
+ )
+ )
);
storiesOf('App', module).add('full app', () => );
@@ -177,7 +229,11 @@ storiesOf('Addon Knobs deprecated Decorator', module)
const age = number('Age', 120);
const content = `I am ${name} and I'm ${age} years old.`;
- return {content}
;
+ return (
+
+ {content}
+
+ );
});
storiesOf('Addon Knobs', module).add(
@@ -187,14 +243,26 @@ storiesOf('Addon Knobs', module).add(
const age = number('Age', 89);
const content = `I am ${name} and I'm ${age} years old.`;
- return {content}
;
+ return (
+
+ {content}
+
+ );
})
);
storiesOf('component.base.Link')
.addDecorator(withKnobs)
- .add('first', () => {text('firstLink', 'first link')} )
- .add('second', () => {text('secondLink', 'second link')} );
+ .add('first', () =>
+
+ {text('firstLink', 'first link')}
+
+ )
+ .add('second', () =>
+
+ {text('secondLink', 'second link')}
+
+ );
storiesOf('component.base.Span')
.add('first', () => first span )
@@ -205,8 +273,20 @@ storiesOf('component.common.Div')
.add('second', () => second div
);
storiesOf('component.common.Table')
- .add('first', () => )
- .add('second', () => );
+ .add('first', () =>
+
+ )
+ .add('second', () =>
+
+ );
storiesOf('component.Button')
.add('first', () => first button )
@@ -216,7 +296,11 @@ storiesOf('component.Button')
storiesOf('Cellsยฏ\\_(ใ)_/ยฏMolecules.Atoms/simple', module)
.addDecorator(withKnobs)
- .add('with text', () => {text('buttonText', 'Hello Button')} )
+ .add('with text', () =>
+
+ {text('buttonText', 'Hello Button')}
+
+ )
.add('with some emoji', () => ๐ ๐ ๐ ๐ฏ );
storiesOf('Cells/Molecules/Atoms.more', module)
@@ -230,4 +314,3 @@ storiesOf('Cells/Molecules', module)
storiesOf('Cells.Molecules.Atoms', module)
.add('with text2', () => Hello Button )
.add('with some emoji2', () => ๐ ๐ ๐ ๐ฏ );
-