11import { cloneElement } from 'react'
22import { action } from '@kadira/storybook'
3- import { text , boolean , number , object , select } from '@kadira/storybook-addon-knobs'
3+ import { withKnobs , text , boolean , number , object , select } from '@kadira/storybook-addon-knobs'
44
55const knobResolvers = { }
66export const addKnobResolver = ( { name, resolver, weight = 0 } ) => ( knobResolvers [ name ] = { name, resolver, weight } )
@@ -10,69 +10,75 @@ export const addKnobResolver = ({ name, resolver, weight = 0 }) => (knobResolver
1010 * --------------------------------
1111 */
1212
13- export const propTypeKnobResolver = ( test , knob , ...args ) =>
14- ( name , validate , value , propTypes , defaultProps ) => ! validate ( { 'prop' : test } , 'prop' )
15- ? knob ( name , value , ...args ) : undefined
13+ export const propTypeKnobResolver = ( name , knob , ...args ) =>
14+ ( propName , propType , value , propTypes , defaultProps ) =>
15+ propType . type . name === name ? knob ( propName , value , ...args ) : undefined
1616
1717/* eslint-disable no-multi-spaces */
1818// Default simple PropType based knob map.
1919const propTypeKnobsMap = [
20- { name : 'string' , test : '' , knob : text } ,
21- { name : 'number' , test : 0 , knob : number } ,
22- { name : 'bool' , test : true , knob : boolean } ,
23- { name : 'func' , test : ( ) => { } , knob : ( name , value ) => value || action ( name ) } ,
24- { name : 'object' , test : { } , knob : object }
20+ { name : 'string' , knob : text } ,
21+ { name : 'number' , knob : number } ,
22+ { name : 'bool' , knob : boolean } ,
23+ { name : 'func' , knob : ( name , value ) => value || action ( name ) } ,
24+ { name : 'object' , knob : object } ,
25+ { name : 'node' , knob : text } ,
26+ { name : 'element' , knob : text } ,
2527]
2628
27- propTypeKnobsMap . forEach ( ( { name, test, knob, args = [ ] } ) => addKnobResolver ( {
28- name,
29- resolver : propTypeKnobResolver ( test , knob , ...args )
29+ propTypeKnobsMap . forEach ( ( { name, knob, args = [ ] } , weight ) => addKnobResolver ( {
30+ weight : weight * 10 ,
31+ name : `PropTypes.${ name } ` ,
32+ resolver : propTypeKnobResolver ( name , knob , ...args )
3033} ) )
3134
32- // Defalt oneOf PropType knob resolver.
35+ // Register ' oneOf' PropType knob resolver.
3336addKnobResolver ( {
34- name : 'oneOf' ,
35- resolver : ( name , validate , value , propTypes , defaultProps ) => {
36- const error = validate ( { 'prop' : '' } , 'prop' )
37- const match = error ? / e x p e c t e d o n e o f ( \[ .* \] ) / . exec ( error . message ) : null
37+ name : 'PropTypes.oneOf' ,
38+ resolver : ( propName , propType , value , propTypes , defaultProps ) => {
39+ /* eslint-disable quotes */
40+ if ( propType . type . name === 'enum' && propType . type . value . length ) {
41+ try {
42+ const options = propType . type . value
43+ . map ( value => value . value )
44+ // Cleanup string quotes, if any.
45+ . map ( value => value [ 0 ] === "'" && value [ value . length - 1 ] === "'"
46+ ? '"' + value . replace ( / ' " ' / g, '\\"' ) . slice ( 1 , value . length - 1 ) + '"' : value )
47+ . map ( JSON . parse )
48+ . reduce ( ( res , value ) => ( { ...res , [ value ] : value } ) , { } )
3849
39- if ( match && match [ 1 ] ) {
40- const parsedOptions = JSON . parse ( match [ 1 ] )
41- const options = parsedOptions . reduce ( ( res , value ) => ( { ...res , [ value ] : value } ) , { } )
42-
43- return select ( name , {
44- '' : '--' ,
45- ...options
46- } , defaultProps [ name ] )
50+ return select ( propName , { '' : '--' , ...options } , defaultProps [ propName ] )
51+ }
52+ catch ( e ) { }
4753 }
4854 }
4955} )
5056
5157export const withSmartKnobs = ( story , context ) => {
52- const component = story ( )
53- const propTypes = component . type . propTypes
58+ const component = story ( context )
59+ const { __docgenInfo : { props } = { props : { } } } = component . type
5460 const defaultProps = {
55- ...component . type . defaultProps ,
61+ ...( component . type . defaultProps || { } ) ,
5662 ...component . props
5763 }
5864
59- return cloneElement ( component , resolvePropValues ( propTypes , defaultProps ) )
65+ return withKnobs ( ( ) => cloneElement ( component , resolvePropValues ( props , defaultProps ) ) , context )
6066}
6167
6268const resolvePropValues = ( propTypes , defaultProps ) => {
63- const propKeys = Object . keys ( propTypes )
69+ const propNames = Object . keys ( propTypes )
6470 const resolvers = Object . keys ( knobResolvers )
6571 . sort ( ( a , b ) => knobResolvers [ a ] . weight < knobResolvers [ b ] . weight )
6672 . map ( name => knobResolvers [ name ] . resolver )
6773
68- return propKeys
69- . map ( prop => resolvers . reduce (
74+ return propNames
75+ . map ( propName => resolvers . reduce (
7076 ( value , resolver ) => value !== undefined ? value
71- : resolver ( prop , propTypes [ prop ] , defaultProps [ prop ] , propTypes , defaultProps ) ,
77+ : resolver ( propName , propTypes [ propName ] , defaultProps [ propName ] , propTypes , defaultProps ) ,
7278 undefined
7379 ) )
7480 . reduce ( ( props , value , i ) => ( {
7581 ...props ,
76- [ propKeys [ i ] ] : value
82+ [ propNames [ i ] ] : value
7783 } ) , defaultProps )
7884}
0 commit comments