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', () => ) @@ -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.', - () => + 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', () =>
    first table
    ) - .add('second', () =>
    first table
    ); + .add('first', () => + + + + +
    first table
    + ) + .add('second', () => + + + + +
    first table
    + ); storiesOf('component.Button') .add('first', () => ) @@ -216,7 +296,11 @@ storiesOf('component.Button') storiesOf('Cellsยฏ\\_(ใƒ„)_/ยฏMolecules.Atoms/simple', module) .addDecorator(withKnobs) - .add('with text', () => ) + .add('with text', () => + + ) .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', () => ) .add('with some emoji2', () => ); -