add react-docgen to provide props tables for UI component library
This commit is contained in:
1 parent
97805df68c
commit
d6877cfcf9
54 files changed
+537
-109
No files matched your search
@@ -0,0 +1,24 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { usePluginData } from '@docusaurus/useGlobalData';
|
||||
import { PropsTable } from '../react-docgen-props-table/PropsTable'
|
||||
|
||||
export function ComponentPropsTable({ componentName }) {
|
||||
if (!componentName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = usePluginData('docusaurus-plugin-react-docgen')
|
||||
const componentDocGenData = data[componentName.toLowerCase()]
|
||||
if (!componentDocGenData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<PropsTable className={'table-auto'} props={componentDocGenData.props}/>
|
||||
)
|
||||
}
|
||||
|
||||
ComponentPropsTable.PropTypes = {
|
||||
componentName: PropTypes.string.required
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import React from 'react';
|
||||
import get from 'lodash.get';
|
||||
import capitalize from 'capitalize';
|
||||
|
||||
import { humanize } from './humanize-prop';
|
||||
import { Table } from './components/Table';
|
||||
import { Tooltip } from './components/Tooltip';
|
||||
|
||||
const styles = {
|
||||
thead: {
|
||||
textAlign: 'left',
|
||||
},
|
||||
};
|
||||
|
||||
export const getPropType = (prop, Tooltip) => {
|
||||
const propName = prop.flowType ? prop.flowType.name : prop.type.name;
|
||||
const isEnum = propName.startsWith('"') || propName === 'enum';
|
||||
const name = capitalize(isEnum ? 'enum' : propName);
|
||||
const value = prop.type && prop.type.value;
|
||||
|
||||
if (!name) return null;
|
||||
|
||||
if (
|
||||
!Tooltip ||
|
||||
(isEnum && typeof value === 'string') ||
|
||||
(!prop.flowType && !isEnum && !value) ||
|
||||
(prop.flowType && !prop.flowType.elements)
|
||||
) {
|
||||
return name;
|
||||
}
|
||||
|
||||
return prop.flowType ? (
|
||||
<Tooltip text={humanize(prop.flowType)}>{name}</Tooltip>
|
||||
) : (
|
||||
<Tooltip text={humanize(prop.type)}>{name}</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export const PropsTable = ({ props, ...rest }) => {
|
||||
if (!props || typeof props !== 'object') {
|
||||
throw new Error('invalid props passed to PropsTable');
|
||||
}
|
||||
|
||||
const hasDescription = Object.keys(props).some(name => {
|
||||
const description = get(props, `${name}.description`);
|
||||
return Boolean(description) && Boolean(get(description, 'length'));
|
||||
});
|
||||
|
||||
const Thead = 'thead';
|
||||
const Tr = 'tr';
|
||||
const Th = 'th';
|
||||
const Tbody = 'tbody';
|
||||
const Td = 'td';
|
||||
|
||||
return (
|
||||
<Table {...rest}>
|
||||
<Thead style={styles.thead}>
|
||||
<Tr>
|
||||
<Th>Property</Th>
|
||||
<Th>Type</Th>
|
||||
<Th>Required</Th>
|
||||
<Th>Default</Th>
|
||||
|
||||
{hasDescription && <Th width="40%">Description</Th>}
|
||||
</Tr>
|
||||
</Thead>
|
||||
|
||||
<Tbody>
|
||||
{props &&
|
||||
Object.keys(props).map(name => {
|
||||
const prop = props[name];
|
||||
|
||||
if (!prop.flowType && !prop.type) return null;
|
||||
return (
|
||||
<Tr key={name}>
|
||||
<Td>{name}</Td>
|
||||
<Td>{getPropType(prop, Tooltip)}</Td>
|
||||
<Td>{String(prop.required)}</Td>
|
||||
{!prop.defaultValue ? (
|
||||
<Td>
|
||||
<em>-</em>
|
||||
</Td>
|
||||
) : (
|
||||
<Td>
|
||||
{prop.defaultValue.value === "''" ? (
|
||||
<em>[Empty String]</em>
|
||||
) : (
|
||||
prop.defaultValue &&
|
||||
prop.defaultValue.value.replace(/'/g, '')
|
||||
)}
|
||||
</Td>
|
||||
)}
|
||||
{hasDescription && (
|
||||
<Td>{prop.description && prop.description}</Td>
|
||||
)}
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
</Tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
|
||||
export const Table = props => {
|
||||
const { className, style, ...rest } = props;
|
||||
return (
|
||||
<div className={className}>
|
||||
<table className={className} {...rest} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
|
||||
export const Tooltip = ({ text, children }) => {
|
||||
const id = JSON.stringify(text);
|
||||
return (
|
||||
<React.Fragment>
|
||||
<a data-tip data-for={id} href="#" onClick={ev => ev.preventDefault()}>
|
||||
{children}
|
||||
</a>
|
||||
|
||||
<ReactTooltip id={id} effect="solid">
|
||||
{text}
|
||||
</ReactTooltip>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import capitalize from 'capitalize'
|
||||
import get from 'lodash.get'
|
||||
import { humanize } from './humanize-prop'
|
||||
|
||||
export const getPropType = (prop) => {
|
||||
const propName = get(prop.flowType || prop.type, 'name')
|
||||
if (!propName) return null
|
||||
|
||||
const isEnum = propName.startsWith('"') || propName === 'enum'
|
||||
const name = capitalize(isEnum ? 'enum' : propName)
|
||||
const value = get(prop, 'type.value')
|
||||
if (!name) return null
|
||||
|
||||
if (
|
||||
(isEnum && typeof value === 'string') ||
|
||||
(!prop.flowType && !isEnum && !value) ||
|
||||
(prop.flowType && !prop.flowType.elements)
|
||||
) {
|
||||
return name
|
||||
}
|
||||
|
||||
return prop.flowType ? humanize(prop.flowType) : humanize(prop.type)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import capitalize from 'capitalize'
|
||||
|
||||
const RE_OBJECTOF = /(?:React\.)?(?:PropTypes\.)?objectOf\((?:React\.)?(?:PropTypes\.)?(\w+)\)/
|
||||
|
||||
const getTypeStr = (type) => {
|
||||
switch (type.name.toLowerCase()) {
|
||||
case 'instanceof':
|
||||
return `Class(${type.value})`
|
||||
case 'enum':
|
||||
if (type.computed) return type.value
|
||||
return type.value
|
||||
? type.value.map((v) => `${v.value}`).join(' │ ')
|
||||
: type.raw
|
||||
case 'union':
|
||||
return type.value
|
||||
? type.value.map((t) => `${getTypeStr(t)}`).join(' │ ')
|
||||
: type.raw
|
||||
case 'array':
|
||||
return type.raw
|
||||
case 'arrayof':
|
||||
return `Array<${getTypeStr(type.value)}>`
|
||||
case 'custom':
|
||||
if (type.raw.indexOf('function') !== -1 || type.raw.indexOf('=>') !== -1) {
|
||||
return 'Custom(Function)'
|
||||
} else if (type.raw.toLowerCase().indexOf('objectof') !== -1) {
|
||||
const m = type.raw.match(RE_OBJECTOF)
|
||||
if (m && m[1]) return `ObjectOf(${capitalize(m[1])})`
|
||||
return 'ObjectOf'
|
||||
}
|
||||
return 'Custom'
|
||||
case 'bool':
|
||||
return 'Boolean'
|
||||
case 'func':
|
||||
return 'Function'
|
||||
case 'shape':
|
||||
const shape = type.value
|
||||
const rst = {}
|
||||
|
||||
Object.keys(shape).forEach(key => {
|
||||
rst[key] = getTypeStr(shape[key])
|
||||
})
|
||||
|
||||
return JSON.stringify(rst, null, 2)
|
||||
default:
|
||||
return capitalize(type.name)
|
||||
}
|
||||
}
|
||||
|
||||
export const humanize = (type) => getTypeStr(type)
|
||||
@@ -0,0 +1,2 @@
|
||||
import { PropsTable } from './PropsTable'
|
||||
export default PropsTable
|
||||
Reference in new issue
Block a user