@catho/quantum-storybook-ui
Version:
A **Design System** is the complete set of design standards, documentation, and principles along with the toolkit (UI patterns and code components) to achieve those standards. Over time, these 'systems' are growing in popularity - a very popular one is [Q
120 lines (98 loc) • 3.19 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import SimpleHighlight from '../SimpleHighlight';
import Title from '../Title';
import { FORBIDDEN_PROPS } from '../shared';
const MainTitle = styled(Title)`
padding: 0;
margin: 25px 0;
`;
const formatJSON = (key, value) => {
if (typeof value === 'function') return '() => {}';
if (typeof value === 'string') return `'${value}'`;
return value;
};
const INDENTATION_SIZE = 2;
const spaces = size => ' '.repeat(size);
const jsonStr = (json, indentation) =>
JSON.stringify(json, formatJSON, INDENTATION_SIZE)
.replace(/\n/g, `\n${indentation}${spaces(INDENTATION_SIZE)}`)
.replace(/"/g, '');
const renderPropValue = (propValue, indentation) => {
if (typeof propValue === 'object' && propValue instanceof RegExp) {
return `{${propValue}}`;
}
const types = {
function: () => '{() => {}}',
string: prop => `"${prop}"`,
number: prop => `{${prop}}`,
object: prop => `{${jsonStr(prop, indentation)}}`,
instanceOf: prop => `{${prop}}`
};
const fn = types[typeof propValue];
return fn ? fn(propValue) : propValue;
};
function getProps(props, indentation) {
const breakline = `\n${indentation}${spaces(INDENTATION_SIZE)}`;
return Object.entries(props)
.filter(([name, value]) => value && !FORBIDDEN_PROPS.includes(name))
.map(([prop, value], index) => {
const propText =
typeof value === 'boolean'
? prop
: `${prop}=${renderPropValue(value, indentation)}`;
return `${index === 0 ? breakline : ''}${propText}`;
})
.join(breakline);
}
const componentToString = (component, state, level = 0) => {
let content;
const indentation = spaces(level);
if (typeof component === 'object') {
const { type, props } = component;
const name = type.displayName || type.name || type;
const children = props ? props.children : null;
content = `${indentation}<${name}${
Object.keys(state).length ? getProps(state, indentation) : ''
}`;
content += children
? `>\n${React.Children.map(children, child =>
componentToString(child, child.props, level + INDENTATION_SIZE)
).join('\n')}\n${indentation}</${name}>`
: `\n${indentation}/>`;
} else {
content = component ? `${indentation}${component}` : '';
}
return content;
};
const msg = importModules =>
`import ${'{'} ${importModules} ${'}'} from '@catho/quantum';\n\n`;
const CodeExample = ({ component, state, code, withImport, title }) => {
const codeStr =
code || componentToString(component, state || component.props);
return (
<>
{title && <MainTitle as="h2">{title}</MainTitle>}
<SimpleHighlight>
{withImport && msg(withImport)}
{codeStr}
</SimpleHighlight>
</>
);
};
CodeExample.defaultProps = {
code: '',
title: '',
withImport: '',
state: null,
component: {}
};
CodeExample.propTypes = {
component: PropTypes.instanceOf(Object),
state: PropTypes.instanceOf(Object),
code: PropTypes.string,
title: PropTypes.string,
withImport: PropTypes.string
};
export default CodeExample;