Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit d878354

Browse files
Updated code to use docgen.
1 parent d084fc1 commit d878354

File tree

14 files changed

+238
-55
lines changed

14 files changed

+238
-55
lines changed

.storybook/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import { configure } from '@kadira/storybook'
77

8+
window.STORYBOOK_REACT_CLASSES = {}
9+
810
function loadStories () {
911
require('../example/stories')
1012
}

.storybook/webpack.config.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,10 @@
44
// Do not modify this file.
55
// Use `.storybook/user/modify_webpack_config.js instead`.
66

7-
const path = require('path')
8-
97
const config = {
108
module: {
119
loaders: [
12-
{
13-
test: /\.css?$/,
14-
loaders: ['style', 'raw'],
15-
include: path.resolve(__dirname, '../'),
16-
},
10+
{ test: /\.css?$/, loader: 'style!css' },
1711
],
1812
},
1913
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.SmartKnobedComponent {
2+
border: 1px solid #999;
3+
color: #333;
4+
font-family: monospace;
5+
border-collapse:collapse;
6+
font-size: 1.5em;
7+
text-align: left;
8+
}
9+
10+
.SmartKnobedComponent thead {
11+
font-style: italic;
12+
font-size: 0.85em;
13+
}
14+
15+
.SmartKnobedComponent th {
16+
background-color: #eee;
17+
}
18+
19+
.SmartKnobedComponent th,
20+
.SmartKnobedComponent td {
21+
border: 0.05em solid #999;
22+
min-width: 1em;
23+
padding: 0.4em;
24+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React, { PropTypes } from 'react'
2+
3+
import './SmartKnobedComponent.css'
4+
5+
const SmartKnobedComponent = props => (
6+
<table className='SmartKnobedComponent'>
7+
<thead>
8+
<tr>
9+
<th>Property</th>
10+
<th>PropType</th>
11+
<th>Value</th>
12+
<th>typeof</th>
13+
</tr>
14+
</thead>
15+
16+
{ Object.keys(props).map(prop => (
17+
<tr key={ prop }>
18+
<th>{ prop }</th>
19+
<td>{ SmartKnobedComponent.__docgenInfo.props[prop].type.name }</td>
20+
<td>{ typeof props[prop] === 'function' ? <i>function</i> : JSON.stringify(props[prop]) || '(empty)' }</td>
21+
<td>{ typeof props[prop] }</td>
22+
</tr>
23+
)) }
24+
</table>
25+
)
26+
27+
SmartKnobedComponent.propTypes = {
28+
bool: PropTypes.bool,
29+
number: PropTypes.number,
30+
string: PropTypes.string,
31+
func: PropTypes.func,
32+
oneOf: PropTypes.oneOf(['one', 'two', 'three']),
33+
object: PropTypes.object,
34+
element: PropTypes.element,
35+
node: PropTypes.node,
36+
}
37+
38+
export default SmartKnobedComponent

example/stories/index.js

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
1-
import React, { PropTypes } from 'react'
1+
import React from 'react'
22
import { storiesOf } from '@kadira/storybook'
3-
import { withKnobs } from '@kadira/storybook-addon-knobs'
43
import { withSmartKnobs } from '../../src'
54

6-
const Button = ({ children, onClick }) => (
7-
<button onClick={ onClick }>{ children }</button>
8-
)
5+
import SmartKnobedComponent from './SmartKnobedComponent'
96

10-
Button.propTypes = {
11-
onClick: PropTypes.func,
12-
children: PropTypes.string,
13-
}
14-
15-
storiesOf('Example of Knobs', module)
7+
storiesOf('Example of smart Knobs', module)
168
.addDecorator(withSmartKnobs)
17-
.addDecorator(withKnobs)
18-
.add('simple example', () => (
19-
<Button>My button</Button>
9+
.add('full example', () => (
10+
<SmartKnobedComponent />
2011
))
12+
13+
14+
console.log(SmartKnobedComponent.__docgenInfo)

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
"@kadira/storybook": "^2.25.0",
2121
"@kadira/storybook-addon-knobs": "^1.3.0",
2222
"babel-cli": "^6.16.0",
23+
"babel-plugin-react-docgen": "^1.3.0",
2324
"babel-preset-es2015": "^6.16.0",
2425
"babel-preset-react": "^6.16.0",
2526
"babel-preset-stage-0": "^6.16.0",
27+
"css-loader": "^0.25.0",
2628
"eslint-config-taller": "^1.0.2",
2729
"react": "^0.14.7 || ^15.0.0",
2830
"react-dom": "^15.3.2"

src/index.js

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { cloneElement } from 'react'
22
import { 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

55
const knobResolvers = {}
66
export 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.
1919
const 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.
3336
addKnobResolver({
34-
name: 'oneOf',
35-
resolver: (name, validate, value, propTypes, defaultProps) => {
36-
const error = validate({ 'prop': '' }, 'prop')
37-
const match = error ? /expected one of (\[.*\])/.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

5157
export 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

6268
const 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
}

storybook-static/favicon.ico

7.1 KB
Binary file not shown.

storybook-static/iframe.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
<!DOCTYPE html>
3+
<html>
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<script>
8+
if (window.parent !== window) {
9+
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
10+
}
11+
</script>
12+
<title>React Storybook</title>
13+
14+
</head>
15+
<body>
16+
<div id="root"></div>
17+
<div id="error-display"></div>
18+
<script src="static/preview.bundle.js"></script>
19+
</body>
20+
</html>
21+

storybook-static/index.html

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
<!DOCTYPE html>
3+
<html>
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<title>React Storybook</title>
8+
<style>
9+
/*
10+
When resizing panels, the drag event breaks if the cursor
11+
moves over the iframe. Add the 'dragging' class to the body
12+
at drag start and remove it when the drag ends.
13+
*/
14+
.dragging iframe {
15+
pointer-events: none;
16+
}
17+
18+
/* Styling the fuzzy search box placeholders */
19+
.searchBox::-webkit-input-placeholder { /* Chrome/Opera/Safari */
20+
color: #ddd;
21+
font-size: 16px;
22+
}
23+
24+
.searchBox::-moz-placeholder { /* Firefox 19+ */
25+
color: #ddd;
26+
font-size: 16px;
27+
}
28+
29+
.searchBox:focus{
30+
border-color: #EEE !important;
31+
}
32+
33+
.btn:hover{
34+
background-color: #eee
35+
}
36+
</style>
37+
</head>
38+
<body style="margin: 0;">
39+
<div id="root"></div>
40+
<script src="static/manager.bundle.js"></script>
41+
</body>
42+
</html>
43+

0 commit comments

Comments
 (0)