Skip to content

Commit

Permalink
Merge pull request #90 from newrelic/jerel/method-defs
Browse files Browse the repository at this point in the history
Method definitions
  • Loading branch information
timglaser authored Jun 4, 2020
2 parents bf9eea3 + aad5354 commit a8db4f8
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 32 deletions.
54 changes: 54 additions & 0 deletions src/components/FunctionDefinition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import PropTypes from 'prop-types';
import Markdown from 'react-markdown';
import styles from './FunctionDefinition.module.scss';

const ParamDescription = ({ children, ...props }) => (
<span {...props} className={styles.paramDescription}>
{'//'} {children}
</span>
);

ParamDescription.propTypes = {
children: PropTypes.node,
};

const FunctionDefinition = ({ params, returnValue }) => {
return (
<div className={styles.container}>
<span className={styles.keyword}>
{params.length > 0 ? 'function (' : 'function ()'}
</span>
{params.map((param, i) => (
<div key={i} className={styles.param}>
<span className={styles.paramName}>{param.name}: </span>
<span className={styles.type}>{param.type} </span>
<Markdown
source={param.description}
renderers={{
root: ParamDescription,
}}
/>
</div>
))}
{params.length > 0 && <span className={styles.keyword}>) </span>}
<span className={styles.keyword}>=> </span>
<span className={styles.type}>{returnValue.type}</span>
</div>
);
};

FunctionDefinition.propTypes = {
params: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string,
type: PropTypes.string,
description: PropTypes.string,
})
),
returnValue: PropTypes.shape({
type: PropTypes.string.isRequired,
}),
};

export default FunctionDefinition;
35 changes: 35 additions & 0 deletions src/components/FunctionDefinition.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.container {
font-family: 'Menlo', 'Consolas', monospace;
font-size: 0.875rem;
line-height: 1.5;
}

.line:not(:last-child) {
margin-bottom: 0.5rem;
}

.param {
margin-left: 1rem;
}

.paramName {
color: var(--color-neutrals-700);
}

.paramDescription {
color: var(--color-neutrals-500);

> p {
color: inherit;
display: inline;
}
}

.keyword {
color: var(--color-neutrals-600);
}

.type {
color: var(--color-green-500);
background: var(--color-green-050);
}
22 changes: 22 additions & 0 deletions src/components/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@
--color-red-800: #390000;
--color-red-900: #1b0000;

--color-green-050: #f1fdf2;
--color-green-100: #d1f7d9;
--color-green-200: #7fe898;
--color-green-300: #22e749;
--color-green-400: #00d100;
--color-green-500: #00a500;
--color-green-600: #008200;
--color-green-700: #004d00;
--color-green-800: #0d290a;
--color-green-900: #021200;

--color-teal-050: #f1fbfc;
--color-teal-100: #d2f3f6;
--color-teal-200: #85e0e7;
--color-teal-300: #70ccd3;
--color-teal-400: #00b3c3;
--color-teal-500: #008c99;
--color-teal-600: #006c75;
--color-teal-700: #00484e;
--color-teal-800: #003539;
--color-teal-900: #002123;

--boxshadow: 0px 2.76726px 2.21381px rgba(0, 85, 90, 0.0168687),
0px 6.6501px 5.32008px rgba(0, 85, 90, 0.0242336),
0px 12.5216px 10.0172px rgba(0, 85, 90, 0.03),
Expand Down
4 changes: 4 additions & 0 deletions src/data/sidenav.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@
"displayName": "AccountStorageMutation",
"url": "/components/account-storage-mutation"
},
{
"displayName": "AccountsQuery",
"url": "/components/accounts-query"
},
{
"displayName": "NerdGraphQuery",
"url": "/components/nerd-graph-query"
Expand Down
49 changes: 49 additions & 0 deletions src/hooks/useComponentDoc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useMemo } from 'react';

const IGNORED_METHODS = [
'prototype',
'length',
'name',
'propTypes',
'getDerivedStateFromProps',
'defaultProps',
];

const useComponentDoc = (componentName) => {
if (typeof window === 'undefined') global.window = {};

return useMemo(() => {
const sdk = window.__NR1_SDK__?.default ?? {};
const component = sdk[componentName];

if (!component) {
return null;
}

const componentDocs = component?.__docs__;

return {
description: componentDocs?.text,
examples: componentDocs?.tags.examples ?? [],
usage: `import { ${componentName} } from 'nr1'`,
methods: Object.getOwnPropertyNames(component)
.filter(
(member) =>
!IGNORED_METHODS.includes(member) &&
typeof component[member] === 'function'
)
.map((member) => {
const methodDocs = component[member].__docs__;

return {
name: `${componentName}.${member}`,
description: methodDocs?.text,
returnValue: methodDocs?.tags.return?.[0] ?? { type: 'undefined' },
params: methodDocs?.tags.param,
};
}),
};
}, [componentName, window?.__NR1_SDK__]);
};

export default useComponentDoc;
7 changes: 7 additions & 0 deletions src/markdown-pages/components/accounts-query.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
path: '/components/accounts-query'
title: 'AccountsQuery'
description: 'A AccountsQuery component!'
component: 'AccountsQuery'
template: 'ReferenceTemplate'
---
82 changes: 50 additions & 32 deletions src/templates/ReferenceTemplate.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React, { useState } from 'react';
import React, { Fragment, useState } from 'react';
import cx from 'classnames';
import { graphql } from 'gatsby';
import PropTypes from 'prop-types';
import InlineCodeSnippet from '../components/InlineCodeSnippet';
import ReactMarkdown from 'react-markdown';
import Container from '../components/Container';
import ComponentExample from '../components/ComponentExample';
import FunctionDefinition from '../components/FunctionDefinition';
import Layout from '../components/Layout';
import Sidebar from '../components/Sidebar';
import SEO from '../components/Seo';

import pages from '../data/sidenav.json';

import styles from './ReferenceTemplate.module.scss';
import useComponentDoc from '../hooks/useComponentDoc';

const previewStyles = {
Spinner: {
Expand All @@ -25,10 +25,14 @@ const ReferenceTemplate = ({ data }) => {
const { mdx } = data;
const { frontmatter } = mdx;
const { title, description, component } = frontmatter;
const componentDoc = useComponentDoc(component);

if (typeof window === 'undefined') global.window = {};
const componentData = window?.__NR1_SDK__?.default?.[component];
const examples = componentData?.__docs__.tags.examples || [];
const {
examples = [],
description: componentDescription,
methods = [],
usage = '',
} = componentDoc ?? {};

return (
<Layout>
Expand All @@ -42,32 +46,46 @@ const ReferenceTemplate = ({ data }) => {
/>
<main className={styles.content}>
<h1>{component}</h1>
{componentData && componentData.__docs__ && (
<>
<section className={cx(styles.section, styles.description)}>
<ReactMarkdown source={componentData.__docs__.text} />
</section>
<section>
<h2>Usage</h2>
<InlineCodeSnippet language="js">{`import { ${component} } from 'nr1'`}</InlineCodeSnippet>
</section>
{examples.length > 0 && (
<section className={styles.section}>
<h2>Examples</h2>
<div>
{examples.map((example, i) => (
<ComponentExample
key={i}
useToastManager={component === 'Toast'}
className={styles.componentExample}
example={example}
previewStyle={previewStyles[component]}
/>
))}
</div>
</section>
)}
</>
<section className={cx(styles.section, styles.description)}>
<ReactMarkdown source={componentDescription} />
</section>
<section className={styles.section}>
<h2>Usage</h2>
<InlineCodeSnippet language="js">{usage}</InlineCodeSnippet>
</section>
{examples.length > 0 && (
<section className={styles.section}>
<h2>Examples</h2>
<div>
{examples.map((example, i) => (
<ComponentExample
key={i}
useToastManager={component === 'Toast'}
className={styles.componentExample}
example={example}
previewStyle={previewStyles[component]}
/>
))}
</div>
</section>
)}
{methods.length > 0 && (
<section className={styles.section}>
<h2>Methods</h2>
{methods.map((method, i) => (
<Fragment key={i}>
<h3 className={styles.methodName}>{method.name}</h3>
<ReactMarkdown
className={styles.methodDescription}
source={method.description}
/>
<FunctionDefinition
params={method.params}
returnValue={method.returnValue}
/>
</Fragment>
))}
</section>
)}
</main>
</Container>
Expand Down
12 changes: 12 additions & 0 deletions src/templates/ReferenceTemplate.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,15 @@
z-index: 200;
min-height: 9999px;
}

.methodDescription {
margin-top: 1rem;
margin-bottom: 1rem;
}

.methodName {
padding: 0.125rem 0.25rem;
display: inline;
color: var(--color-teal-500);
background: var(--color-teal-050);
}

0 comments on commit a8db4f8

Please sign in to comment.