Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More detailed props table #1485

Merged
merged 24 commits into from
Sep 6, 2017
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bc63adf
Detailed formatting of arrayOf, shape, oneOf
billyvg Jul 18, 2017
1d54f15
Add babel watch task
billyvg Jul 18, 2017
aa44f18
Merge branch 'master' into prop-table-detailed
ndelangen Jul 19, 2017
ba35434
Merge branch 'master' into prop-table-detailed
ndelangen Jul 28, 2017
bd7b139
Merge branch 'master' into prop-table-detailed
ndelangen Aug 18, 2017
093dd01
Merge branch 'master' into prop-table-detailed
billyvg Aug 23, 2017
7ce5673
addon info: make propTypes table better
billyvg Aug 23, 2017
2f62f90
Merge branch 'master' into prop-table-detailed
billyvg Aug 23, 2017
eda55b9
Merge branch 'release/3.3' into prop-table-detailed
ndelangen Aug 24, 2017
e5152f5
Merge branch 'release/3.3' into prop-table-detailed
ndelangen Aug 24, 2017
40a229e
cleanup deprecated tests
billyvg Aug 28, 2017
a54f714
cleanup <PrettyPropType>
billyvg Aug 28, 2017
34333bd
add: styled components
billyvg Aug 28, 2017
ff6d332
Merge branch 'release/3.3' into prop-table-detailed
ndelangen Aug 28, 2017
2fdeff5
removed in favor of glamorous component
billyvg Aug 28, 2017
4c1ce1f
Merge branch 'release/3.3' into prop-table-detailed
Hypnosphi Aug 30, 2017
81dae0b
Merge branch 'release/3.3' into prop-table-detailed
ndelangen Aug 30, 2017
738a8c5
Merge branch 'release/3.3' into prop-table-detailed
billyvg Sep 5, 2017
c90b09e
fix: add key for OneOfType
billyvg Sep 5, 2017
691771f
fix: use native buttons
billyvg Sep 5, 2017
05e43d7
Merge branch 'release/3.3' into prop-table-detailed
Hypnosphi Sep 5, 2017
569d3a2
Merge branch 'release/3.3' into prop-table-detailed
ndelangen Sep 6, 2017
e43d49b
ADD an example usage of complex PropType and add descriptions for Con…
ndelangen Sep 6, 2017
f2a9b66
Merge branch 'release/3.3' into prop-table-detailed
ndelangen Sep 6, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions addons/info/example/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ Object.assign(Button, {
style: PropTypes.object,
disabled: PropTypes.bool,
onClick: PropTypes.func,
array: PropTypes.array,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if we could add example usages to the examples/cra-kitchen-sink.

The examples inside the packages are unofficially deprecated..

arrayOf: PropTypes.arrayOf(PropTypes.string),
oneOf: PropTypes.oneOf(['foo', 'bar']),
shape: PropTypes.shape({
foo: PropTypes.string,
bar: PropTypes.number,
}),
nestedArrayOf: PropTypes.arrayOf(PropTypes.shape({
foo: PropTypes.shape({
baz: PropTypes.string,
bar: PropTypes.arrayOf({
PropTypes.string
}),
}),
})),
},
});

Expand Down
1 change: 1 addition & 0 deletions addons/info/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"scripts": {
"prepublish": "node ../../scripts/prepublish.js",
"publish-storybook": "bash .scripts/publish_storybook.sh",
"dev": "babel --watch --ignore tests,__tests__,test.js,stories/,story.jsx --plugins transform-runtime ./src --out-dir ./dist --copy-files",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to have development script/setup on every individual package in the monorepo.
We want to do development on the entire codebase as a whole.

If you bootstrap the codebase and run yarn dev (in the root)
and then start the cra-kitchen-sink example. You should see addons change after a refresh.

"storybook": "start-storybook -p 9010"
},
"dependencies": {
Expand Down
82 changes: 24 additions & 58 deletions addons/info/src/components/PropTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import PropTypes from 'prop-types';
import React from 'react';

import styles from './styles';
import PropVal from './PropVal';
import PrettyPropType from './types/PrettyPropType';

const PropTypesMap = new Map();

Expand All @@ -13,41 +16,10 @@ Object.keys(PropTypes).forEach(typeName => {
PropTypesMap.set(type.isRequired, typeName);
});

const stylesheet = {
propTable: {
marginLeft: -10,
borderSpacing: '10px 5px',
borderCollapse: 'separate',
},
};

const isNotEmpty = obj => obj && obj.props && Object.keys(obj.props).length > 0;

const renderDocgenPropType = propType => {
if (!propType) {
return 'unknown';
}

const name = propType.name;

switch (name) {
case 'arrayOf':
return `${propType.value.name}[]`;
case 'instanceOf':
return propType.value;
case 'union':
return propType.raw;
case 'signature':
return propType.raw;
default:
return name;
}
};

const hasDocgen = type => isNotEmpty(type.__docgenInfo);

const boolToString = value => (value ? 'yes' : 'no');

const propsFromDocgen = type => {
const props = {};
const docgenInfoProps = type.__docgenInfo.props;
Expand All @@ -59,8 +31,8 @@ const propsFromDocgen = type => {

props[property] = {
property,
propType: renderDocgenPropType(propType),
required: boolToString(docgenInfoProp.required),
propType,
required: docgenInfoProp.required,
description: docgenInfoProp.description,
defaultValue: defaultValueDesc.value,
};
Expand All @@ -75,21 +47,15 @@ const propsFromPropTypes = type => {
if (type.propTypes) {
Object.keys(type.propTypes).forEach(property => {
const typeInfo = type.propTypes[property];
const required = boolToString(typeInfo.isRequired === undefined);
const description =
type.__docgenInfo && type.__docgenInfo.props && type.__docgenInfo.props[property]
? type.__docgenInfo.props[property].description
: null;
const required = typeInfo.isRequired === undefined;
const docgenInfo =
type.__docgenInfo && type.__docgenInfo.props && type.__docgenInfo.props[property];
const description = docgenInfo ? docgenInfo.description : null;
let propType = PropTypesMap.get(typeInfo) || 'other';

if (propType === 'other') {
if (
type.__docgenInfo &&
type.__docgenInfo.props &&
type.__docgenInfo.props[property] &&
type.__docgenInfo.props[property].type
) {
propType = type.__docgenInfo.props[property].type.name;
if (docgenInfo && docgenInfo.type) {
propType = docgenInfo.type.name;
}
}

Expand Down Expand Up @@ -137,34 +103,34 @@ export default function PropTable(props) {
};

return (
<table style={stylesheet.propTable}>
<table style={styles.propTable}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a requirement for this PR, but I'd really really like it if we could move the styling components into lib/components. and style them using glamorous. Styling using inline-styles give pretty poor development experience and makes it very hard for us to add theming support in the long run.

Again: not a requirement to get this merged, just a head's up if we don't do this in this PR, it will be done in a refactor later.

<thead>
<tr>
<th>property</th>
<th>propType</th>
<th>required</th>
<th>default</th>
<th>description</th>
<th style={styles.propTableCell}>property</th>
<th style={styles.propTableCell}>propType</th>
<th style={styles.propTableCell}>required</th>
<th style={styles.propTableCell}>default</th>
<th style={styles.propTableCell}>description</th>
</tr>
</thead>
<tbody>
{array.map(row =>
<tr key={row.property}>
<td>
<td style={{ ...styles.propTableCell, ...styles.code }}>
{row.property}
</td>
<td>
{row.propType}
<td style={{ ...styles.propTableCell, ...styles.code }}>
<PrettyPropType propType={row.propType} />
</td>
<td>
{row.required}
<td style={styles.propTableCell}>
{row.required ? 'yes' : '-'}
</td>
<td>
<td style={styles.propTableCell}>
{row.defaultValue === undefined
? '-'
: <PropVal val={row.defaultValue} {...propValProps} />}
</td>
<td>
<td style={styles.propTableCell}>
{row.description}
</td>
</tr>
Expand Down
17 changes: 17 additions & 0 deletions addons/info/src/components/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
hasProperty: {
whiteSpace: 'nowrap',
},
code: {
whiteSpace: 'nowrap',
fontFamily: 'Monaco, Consolas, "Courier New", monospace',
},
propTable: {
marginTop: 10,
borderCollapse: 'collapse',
},
propTableCell: {
border: '1px solid #ccc',
padding: '2px 6px',
},
};
19 changes: 19 additions & 0 deletions addons/info/src/components/types/ArrayOf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

import PrettyPropType from './PrettyPropType';
import { TypeInfo } from './proptypes';

const ArrayOf = ({ propType }) =>
<span>
<span>[</span>
<span>
<PrettyPropType propType={propType.value} />
</span>
<span>]</span>
</span>;

ArrayOf.propTypes = {
propType: TypeInfo.isRequired,
};

export default ArrayOf;
56 changes: 56 additions & 0 deletions addons/info/src/components/types/HighlightButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import PropTypes from 'prop-types';
import React from 'react';

export default class HighlightButton extends React.Component {
static propTypes = {
children: PropTypes.node.isRequired,
highlight: PropTypes.bool,
};

static defaultProps = {
highlight: false,
};

constructor(props) {
super(props);
this.state = {
hover: false,
};
}

handleMouseEnter = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding state to a component to add a hover state.. This calls for glamorous component styling too.

this.setState({ hover: true });
};

handleMouseLeave = () => {
this.setState({ hover: false });
};

render() {
const { children, highlight, ...otherProps } = this.props;
const style =
highlight || this.state.hover
? {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
border: '1px solid #ccc',
}
: {};
return (
<span
role="button"
tabIndex={-1}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={{
...style,
...{
cursor: 'pointer',
},
}}
{...otherProps}
>
{children}
</span>
);
}
}
28 changes: 28 additions & 0 deletions addons/info/src/components/types/ObjectOf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

import PrettyPropType from './PrettyPropType';
import { TypeInfo } from './proptypes';

const ObjectOf = ({ propType }) =>
<span>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<span>
{'{'}
</span>
<span />
<span>
{'[<key>]:'}
</span>
<span />
<span>
<PrettyPropType propType={propType.value} />
</span>
<span>
{'}'}
</span>
</span>;

ObjectOf.propTypes = {
propType: TypeInfo.isRequired,
};

export default ObjectOf;
79 changes: 79 additions & 0 deletions addons/info/src/components/types/ObjectType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import PropTypes from 'prop-types';
import React from 'react';

import PrettyPropType from './PrettyPropType';
import PropertyLabel from './PropertyLabel';
import HighlightButton from './HighlightButton';

import { TypeInfo } from './proptypes';

const MARGIN_SIZE = 15;

export default class ObjectType extends React.Component {
static propTypes = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems inconsistent with the rest of the codebase. I would prefer if we discuss adding proptypes like this overall before actually doing it.

If you'd like you can start a discussion about it on slack in #maintenance. For this PR, I'd refer it if we can stick to what we do everywhere else.

propType: TypeInfo,
depth: PropTypes.number.isRequired,
};

static defaultProps = {
propType: null,
};

constructor(props) {
super(props);
this.state = {
minimized: false,
};
}

handleToggle = () => {
this.setState({
minimized: !this.state.minimized,
});
};

handleMouseEnter = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please convert to glamorous component to do hover styling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the hover state is required because I highlight the matching bracket.

this.setState({ hover: true });
};

handleMouseLeave = () => {
this.setState({ hover: false });
};

render() {
const { propType, depth } = this.props;
return (
<span>
<HighlightButton
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
highlight={this.state.hover}
onClick={this.handleToggle}
>
{'{'}
</HighlightButton>
<HighlightButton onClick={this.handleToggle}>...</HighlightButton>
{!this.state.minimized &&
Object.keys(propType.value).map(childProperty =>
<div key={childProperty} style={{ marginLeft: depth * MARGIN_SIZE }}>
<PropertyLabel
property={childProperty}
required={propType.value[childProperty].required}
/>
<PrettyPropType depth={depth + 1} propType={propType.value[childProperty]} />
,
</div>
)}

<HighlightButton
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
highlight={this.state.hover}
onClick={this.handleToggle}
>
{'}'}
</HighlightButton>
</span>
);
}
}
22 changes: 22 additions & 0 deletions addons/info/src/components/types/OneOfType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

import PrettyPropType from './PrettyPropType';
import { TypeInfo } from './proptypes';

const OneOfType = ({ propType }) => {
const length = propType.value.length;
return (
<span>
{propType.value
.map((value, i) => [
<PrettyPropType propType={value} />,
i < length - 1 ? <span> | </span> : null,
])
.reduce((acc, tuple) => acc.concat(tuple), [])}
</span>
);
};
OneOfType.propTypes = {
propType: TypeInfo.isRequired,
};
export default OneOfType;
Loading