move scripts to monorepro-scripts
This commit is contained in:
56
packages/react-docs/src/components/badge.tsx
Normal file
56
packages/react-docs/src/components/badge.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Styles } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
const styles: Styles = {
|
||||
badge: {
|
||||
width: 50,
|
||||
fontSize: 11,
|
||||
height: 10,
|
||||
borderRadius: 5,
|
||||
lineHeight: 0.9,
|
||||
fontFamily: 'Roboto Mono',
|
||||
marginLeft: 3,
|
||||
marginRight: 3,
|
||||
},
|
||||
};
|
||||
|
||||
export interface BadgeProps {
|
||||
title: string;
|
||||
backgroundColor: string;
|
||||
}
|
||||
|
||||
export interface BadgeState {
|
||||
isHovering: boolean;
|
||||
}
|
||||
|
||||
export class Badge extends React.Component<BadgeProps, BadgeState> {
|
||||
constructor(props: BadgeProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHovering: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const badgeStyle = {
|
||||
...styles.badge,
|
||||
backgroundColor: this.props.backgroundColor,
|
||||
opacity: this.state.isHovering ? 0.7 : 1,
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className="p1 center"
|
||||
style={badgeStyle}
|
||||
onMouseOver={this._setHoverState.bind(this, true)}
|
||||
onMouseOut={this._setHoverState.bind(this, false)}
|
||||
>
|
||||
{this.props.title}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _setHoverState(isHovering: boolean) {
|
||||
this.setState({
|
||||
isHovering,
|
||||
});
|
||||
}
|
||||
}
|
23
packages/react-docs/src/components/comment.tsx
Normal file
23
packages/react-docs/src/components/comment.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { MarkdownCodeBlock } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import * as ReactMarkdown from 'react-markdown';
|
||||
|
||||
export interface CommentProps {
|
||||
comment: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
|
||||
export const Comment: React.SFC<CommentProps> = (props: CommentProps) => {
|
||||
return (
|
||||
<div className={`${props.className} comment`}>
|
||||
<ReactMarkdown source={props.comment} renderers={{ code: MarkdownCodeBlock }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Comment.defaultProps = defaultProps;
|
33
packages/react-docs/src/components/custom_enum.tsx
Normal file
33
packages/react-docs/src/components/custom_enum.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { CustomType } from '../types';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
const STRING_ENUM_CODE_PREFIX = ' strEnum(';
|
||||
|
||||
export interface CustomEnumProps {
|
||||
type: CustomType;
|
||||
}
|
||||
|
||||
// This component renders custom string enums that was a work-around for versions of
|
||||
// TypeScript <2.4.0 that did not support them natively. We keep it around to support
|
||||
// older versions of 0x.js <0.9.0
|
||||
export function CustomEnum(props: CustomEnumProps) {
|
||||
const type = props.type;
|
||||
if (!_.startsWith(type.defaultValue, STRING_ENUM_CODE_PREFIX)) {
|
||||
utils.consoleLog('We do not yet support `Variable` types that are not strEnums');
|
||||
return null;
|
||||
}
|
||||
// Remove the prefix and postfix, leaving only the strEnum values without quotes.
|
||||
const enumValues = type.defaultValue.slice(10, -3).replace(/'/g, '');
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
{'\t'}
|
||||
{enumValues}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
375
packages/react-docs/src/components/documentation.tsx
Normal file
375
packages/react-docs/src/components/documentation.tsx
Normal file
@@ -0,0 +1,375 @@
|
||||
import {
|
||||
colors,
|
||||
constants as sharedConstants,
|
||||
EtherscanLinkSuffixes,
|
||||
MarkdownSection,
|
||||
MenuSubsectionsBySection,
|
||||
NestedSidebarMenu,
|
||||
Networks,
|
||||
SectionHeader,
|
||||
Styles,
|
||||
utils as sharedUtils,
|
||||
} from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import CircularProgress from 'material-ui/CircularProgress';
|
||||
import * as React from 'react';
|
||||
import { scroller } from 'react-scroll';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import {
|
||||
AddressByContractName,
|
||||
DocAgnosticFormat,
|
||||
DoxityDocObj,
|
||||
Event,
|
||||
Property,
|
||||
SolidityMethod,
|
||||
SupportedDocJson,
|
||||
TypeDefinitionByName,
|
||||
TypescriptMethod,
|
||||
} from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { Badge } from './badge';
|
||||
import { Comment } from './comment';
|
||||
import { EventDefinition } from './event_definition';
|
||||
import { MethodBlock } from './method_block';
|
||||
import { SourceLink } from './source_link';
|
||||
import { Type } from './type';
|
||||
import { TypeDefinition } from './type_definition';
|
||||
|
||||
const networkNameToColor: { [network: string]: string } = {
|
||||
[Networks.Kovan]: colors.purple,
|
||||
[Networks.Ropsten]: colors.red,
|
||||
[Networks.Mainnet]: colors.turquois,
|
||||
[Networks.Rinkeby]: colors.darkYellow,
|
||||
};
|
||||
|
||||
export interface DocumentationProps {
|
||||
selectedVersion: string;
|
||||
availableVersions: string[];
|
||||
docsInfo: DocsInfo;
|
||||
sourceUrl: string;
|
||||
onVersionSelected: (semver: string) => void;
|
||||
docAgnosticFormat?: DocAgnosticFormat;
|
||||
sidebarHeader?: React.ReactNode;
|
||||
topBarHeight?: number;
|
||||
}
|
||||
|
||||
export interface DocumentationState {
|
||||
isHoveringSidebar: boolean;
|
||||
}
|
||||
|
||||
export class Documentation extends React.Component<DocumentationProps, DocumentationState> {
|
||||
public static defaultProps: Partial<DocumentationProps> = {
|
||||
topBarHeight: 0,
|
||||
};
|
||||
constructor(props: DocumentationProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHoveringSidebar: false,
|
||||
};
|
||||
}
|
||||
public componentDidMount() {
|
||||
window.addEventListener('hashchange', this._onHashChanged.bind(this), false);
|
||||
}
|
||||
public componentWillUnmount() {
|
||||
window.removeEventListener('hashchange', this._onHashChanged.bind(this), false);
|
||||
}
|
||||
public componentDidUpdate(prevProps: DocumentationProps, prevState: DocumentationState) {
|
||||
if (!_.isEqual(prevProps.docAgnosticFormat, this.props.docAgnosticFormat)) {
|
||||
const hash = window.location.hash.slice(1);
|
||||
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
|
||||
}
|
||||
}
|
||||
public render() {
|
||||
const styles: Styles = {
|
||||
mainContainers: {
|
||||
position: 'absolute',
|
||||
top: 1,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
overflowZ: 'hidden',
|
||||
overflowY: 'scroll',
|
||||
minHeight: `calc(100vh - ${this.props.topBarHeight}px)`,
|
||||
WebkitOverflowScrolling: 'touch',
|
||||
},
|
||||
menuContainer: {
|
||||
borderColor: colors.grey300,
|
||||
maxWidth: 330,
|
||||
marginLeft: 20,
|
||||
},
|
||||
};
|
||||
const menuSubsectionsBySection = this.props.docsInfo.getMenuSubsectionsBySection(this.props.docAgnosticFormat);
|
||||
return (
|
||||
<div>
|
||||
{_.isUndefined(this.props.docAgnosticFormat) ? (
|
||||
this._renderLoading(styles.mainContainers)
|
||||
) : (
|
||||
<div style={{ width: '100%', height: '100%', backgroundColor: colors.gray40 }}>
|
||||
<div
|
||||
className="mx-auto max-width-4 flex"
|
||||
style={{ color: colors.grey800, height: `calc(100vh - ${this.props.topBarHeight}px)` }}
|
||||
>
|
||||
<div
|
||||
className="relative sm-hide xs-hide"
|
||||
style={{ width: '36%', height: `calc(100vh - ${this.props.topBarHeight}px)` }}
|
||||
>
|
||||
<div
|
||||
className="border-right absolute"
|
||||
style={{
|
||||
...styles.menuContainer,
|
||||
...styles.mainContainers,
|
||||
height: `calc(100vh - ${this.props.topBarHeight}px)`,
|
||||
overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden',
|
||||
}}
|
||||
onMouseEnter={this._onSidebarHover.bind(this)}
|
||||
onMouseLeave={this._onSidebarHoverOff.bind(this)}
|
||||
>
|
||||
<NestedSidebarMenu
|
||||
selectedVersion={this.props.selectedVersion}
|
||||
versions={this.props.availableVersions}
|
||||
sidebarHeader={this.props.sidebarHeader}
|
||||
topLevelMenu={this.props.docsInfo.getMenu(this.props.selectedVersion)}
|
||||
menuSubsectionsBySection={menuSubsectionsBySection}
|
||||
onVersionSelected={this.props.onVersionSelected}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="relative col lg-col-9 md-col-9 sm-col-12 col-12"
|
||||
style={{ backgroundColor: colors.white }}
|
||||
>
|
||||
<div
|
||||
id={sharedConstants.SCROLL_CONTAINER_ID}
|
||||
style={styles.mainContainers}
|
||||
className="absolute px1"
|
||||
>
|
||||
<div id={sharedConstants.SCROLL_TOP_ID} />
|
||||
{this._renderDocumentation()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderLoading(mainContainersStyles: React.CSSProperties) {
|
||||
return (
|
||||
<div className="col col-12" style={mainContainersStyles}>
|
||||
<div
|
||||
className="relative sm-px2 sm-pt2 sm-m1"
|
||||
style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
|
||||
>
|
||||
<div className="center pb2">
|
||||
<CircularProgress size={40} thickness={5} />
|
||||
</div>
|
||||
<div className="center pt2" style={{ paddingBottom: 11 }}>
|
||||
Loading documentation...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderDocumentation(): React.ReactNode {
|
||||
const subMenus = _.values(this.props.docsInfo.getMenu());
|
||||
const orderedSectionNames = _.flatten(subMenus);
|
||||
|
||||
const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.props.docAgnosticFormat);
|
||||
const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName));
|
||||
|
||||
return renderedSections;
|
||||
}
|
||||
private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
|
||||
const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName];
|
||||
if (!_.isUndefined(markdownFileIfExists)) {
|
||||
return (
|
||||
<MarkdownSection
|
||||
key={`markdown-section-${sectionName}`}
|
||||
sectionName={sectionName}
|
||||
markdownContent={markdownFileIfExists}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const docSection = this.props.docAgnosticFormat[sectionName];
|
||||
if (_.isUndefined(docSection)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sortedTypes = _.sortBy(docSection.types, 'name');
|
||||
const typeDefs = _.map(sortedTypes, customType => {
|
||||
return (
|
||||
<TypeDefinition
|
||||
sectionName={sectionName}
|
||||
key={`type-${customType.name}`}
|
||||
customType={customType}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const sortedProperties = _.sortBy(docSection.properties, 'name');
|
||||
const propertyDefs = _.map(sortedProperties, this._renderProperty.bind(this, sectionName));
|
||||
|
||||
const sortedMethods = _.sortBy(docSection.methods, 'name');
|
||||
const methodDefs = _.map(sortedMethods, method => {
|
||||
const isConstructor = false;
|
||||
return this._renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName);
|
||||
});
|
||||
|
||||
const sortedEvents = _.sortBy(docSection.events, 'name');
|
||||
const eventDefs = _.map(sortedEvents, (event: Event, i: number) => {
|
||||
return (
|
||||
<EventDefinition
|
||||
key={`event-${event.name}-${i}`}
|
||||
event={event}
|
||||
sectionName={sectionName}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
const headerStyle: React.CSSProperties = {
|
||||
fontWeight: 100,
|
||||
};
|
||||
return (
|
||||
<div key={`section-${sectionName}`} className="py2 pr3 md-pl2 sm-pl3">
|
||||
<div className="flex pb2">
|
||||
<div style={{ marginRight: 7 }}>
|
||||
<SectionHeader sectionName={sectionName} />
|
||||
</div>
|
||||
{this._renderNetworkBadgesIfExists(sectionName)}
|
||||
</div>
|
||||
{docSection.comment && <Comment comment={docSection.comment} />}
|
||||
{docSection.constructors.length > 0 &&
|
||||
this.props.docsInfo.isVisibleConstructor(sectionName) && (
|
||||
<div>
|
||||
<h2 style={headerStyle}>Constructor</h2>
|
||||
{this._renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)}
|
||||
</div>
|
||||
)}
|
||||
{docSection.properties.length > 0 && (
|
||||
<div>
|
||||
<h2 style={headerStyle}>Properties</h2>
|
||||
<div>{propertyDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
{docSection.methods.length > 0 && (
|
||||
<div>
|
||||
<h2 style={headerStyle}>Methods</h2>
|
||||
<div>{methodDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
{!_.isUndefined(docSection.events) &&
|
||||
docSection.events.length > 0 && (
|
||||
<div>
|
||||
<h2 style={headerStyle}>Events</h2>
|
||||
<div>{eventDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
{!_.isUndefined(typeDefs) &&
|
||||
typeDefs.length > 0 && (
|
||||
<div>
|
||||
<div>{typeDefs}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderNetworkBadgesIfExists(sectionName: string) {
|
||||
if (this.props.docsInfo.type !== SupportedDocJson.Doxity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const networkToAddressByContractName = this.props.docsInfo.contractsByVersionByNetworkId[
|
||||
this.props.selectedVersion
|
||||
];
|
||||
const badges = _.map(
|
||||
networkToAddressByContractName,
|
||||
(addressByContractName: AddressByContractName, networkName: string) => {
|
||||
const contractAddress = addressByContractName[sectionName];
|
||||
if (_.isUndefined(contractAddress)) {
|
||||
return null;
|
||||
}
|
||||
const linkIfExists = sharedUtils.getEtherScanLinkIfExists(
|
||||
contractAddress,
|
||||
sharedConstants.NETWORK_ID_BY_NAME[networkName],
|
||||
EtherscanLinkSuffixes.Address,
|
||||
);
|
||||
return (
|
||||
<a
|
||||
key={`badge-${networkName}-${sectionName}`}
|
||||
href={linkIfExists}
|
||||
target="_blank"
|
||||
style={{ color: colors.white, textDecoration: 'none' }}
|
||||
>
|
||||
<Badge title={networkName} backgroundColor={networkNameToColor[networkName]} />
|
||||
</a>
|
||||
);
|
||||
},
|
||||
);
|
||||
return badges;
|
||||
}
|
||||
private _renderConstructors(
|
||||
constructors: SolidityMethod[] | TypescriptMethod[],
|
||||
sectionName: string,
|
||||
typeDefinitionByName: TypeDefinitionByName,
|
||||
): React.ReactNode {
|
||||
const constructorDefs = _.map(constructors, constructor => {
|
||||
return this._renderMethodBlocks(constructor, sectionName, constructor.isConstructor, typeDefinitionByName);
|
||||
});
|
||||
return <div>{constructorDefs}</div>;
|
||||
}
|
||||
private _renderProperty(sectionName: string, property: Property): React.ReactNode {
|
||||
return (
|
||||
<div key={`property-${property.name}-${property.type.name}`} className="pb3">
|
||||
<code className={`hljs ${constants.TYPE_TO_SYNTAX[this.props.docsInfo.type]}`}>
|
||||
{property.name}:
|
||||
<Type type={property.type} sectionName={sectionName} docsInfo={this.props.docsInfo} />
|
||||
</code>
|
||||
{property.source && (
|
||||
<SourceLink
|
||||
version={this.props.selectedVersion}
|
||||
source={property.source}
|
||||
sourceUrl={this.props.sourceUrl}
|
||||
/>
|
||||
)}
|
||||
{property.comment && <Comment comment={property.comment} className="py2" />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderMethodBlocks(
|
||||
method: SolidityMethod | TypescriptMethod,
|
||||
sectionName: string,
|
||||
isConstructor: boolean,
|
||||
typeDefinitionByName: TypeDefinitionByName,
|
||||
): React.ReactNode {
|
||||
return (
|
||||
<MethodBlock
|
||||
key={`method-${method.name}-${sectionName}`}
|
||||
sectionName={sectionName}
|
||||
method={method}
|
||||
typeDefinitionByName={typeDefinitionByName}
|
||||
libraryVersion={this.props.selectedVersion}
|
||||
docsInfo={this.props.docsInfo}
|
||||
sourceUrl={this.props.sourceUrl}
|
||||
/>
|
||||
);
|
||||
}
|
||||
private _onSidebarHover(event: React.FormEvent<HTMLInputElement>) {
|
||||
this.setState({
|
||||
isHoveringSidebar: true,
|
||||
});
|
||||
}
|
||||
private _onSidebarHoverOff() {
|
||||
this.setState({
|
||||
isHoveringSidebar: false,
|
||||
});
|
||||
}
|
||||
private _onHashChanged(event: any) {
|
||||
const hash = window.location.hash.slice(1);
|
||||
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
|
||||
}
|
||||
}
|
23
packages/react-docs/src/components/enum.tsx
Normal file
23
packages/react-docs/src/components/enum.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { EnumValue } from '../types';
|
||||
|
||||
export interface EnumProps {
|
||||
values: EnumValue[];
|
||||
}
|
||||
|
||||
export function Enum(props: EnumProps) {
|
||||
const values = _.map(props.values, (value, i) => {
|
||||
const defaultValueIfAny = !_.isUndefined(value.defaultValue) ? ` = ${value.defaultValue}` : '';
|
||||
return `\n\t${value.name}${defaultValueIfAny},`;
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
{values}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
84
packages/react-docs/src/components/event_definition.tsx
Normal file
84
packages/react-docs/src/components/event_definition.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import { AnchorTitle, colors, HeaderSizes } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Event, EventArg } from '../types';
|
||||
|
||||
import { Type } from './type';
|
||||
|
||||
export interface EventDefinitionProps {
|
||||
event: Event;
|
||||
sectionName: string;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
export interface EventDefinitionState {
|
||||
shouldShowAnchor: boolean;
|
||||
}
|
||||
|
||||
export class EventDefinition extends React.Component<EventDefinitionProps, EventDefinitionState> {
|
||||
constructor(props: EventDefinitionProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shouldShowAnchor: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const event = this.props.event;
|
||||
const id = `${this.props.sectionName}-${event.name}`;
|
||||
return (
|
||||
<div
|
||||
id={id}
|
||||
className="pb2"
|
||||
style={{ overflow: 'hidden', width: '100%' }}
|
||||
onMouseOver={this._setAnchorVisibility.bind(this, true)}
|
||||
onMouseOut={this._setAnchorVisibility.bind(this, false)}
|
||||
>
|
||||
<AnchorTitle
|
||||
headerSize={HeaderSizes.H3}
|
||||
title={`Event ${event.name}`}
|
||||
id={id}
|
||||
shouldShowAnchor={this.state.shouldShowAnchor}
|
||||
/>
|
||||
<div style={{ fontSize: 16 }}>
|
||||
<pre>
|
||||
<code className="hljs solidity">{this._renderEventCode()}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderEventCode() {
|
||||
const indexed = <span style={{ color: colors.green }}> indexed</span>;
|
||||
const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => {
|
||||
const type = (
|
||||
<Type type={eventArg.type} sectionName={this.props.sectionName} docsInfo={this.props.docsInfo} />
|
||||
);
|
||||
return (
|
||||
<span key={`eventArg-${eventArg.name}`}>
|
||||
{eventArg.name}
|
||||
{eventArg.isIndexed ? indexed : ''}: {type},
|
||||
</span>
|
||||
);
|
||||
});
|
||||
const argList = _.reduce(eventArgs, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '\n\t', curr];
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
<br />
|
||||
{'\t'}
|
||||
{argList}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
private _setAnchorVisibility(shouldShowAnchor: boolean) {
|
||||
this.setState({
|
||||
shouldShowAnchor,
|
||||
});
|
||||
}
|
||||
}
|
63
packages/react-docs/src/components/interface.tsx
Normal file
63
packages/react-docs/src/components/interface.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { CustomType, TypeDocTypes } from '../types';
|
||||
|
||||
import { MethodSignature } from './method_signature';
|
||||
import { Type } from './type';
|
||||
|
||||
export interface InterfaceProps {
|
||||
type: CustomType;
|
||||
sectionName: string;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
export function Interface(props: InterfaceProps) {
|
||||
const type = props.type;
|
||||
const properties = _.map(type.children, property => {
|
||||
return (
|
||||
<span key={`property-${property.name}-${property.type}-${type.name}`}>
|
||||
{property.name}:{' '}
|
||||
{property.type.typeDocType !== TypeDocTypes.Reflection ? (
|
||||
<Type type={property.type} sectionName={props.sectionName} docsInfo={props.docsInfo} />
|
||||
) : (
|
||||
<MethodSignature
|
||||
method={property.type.method}
|
||||
sectionName={props.sectionName}
|
||||
shouldHideMethodName={true}
|
||||
shouldUseArrowSyntax={true}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
)},
|
||||
</span>
|
||||
);
|
||||
});
|
||||
const hasIndexSignature = !_.isUndefined(type.indexSignature);
|
||||
if (hasIndexSignature) {
|
||||
const is = type.indexSignature;
|
||||
const param = (
|
||||
<span key={`indexSigParams-${is.keyName}-${is.keyType}-${type.name}`}>
|
||||
{is.keyName}: <Type type={is.keyType} sectionName={props.sectionName} docsInfo={props.docsInfo} />
|
||||
</span>
|
||||
);
|
||||
properties.push(
|
||||
<span key={`indexSignature-${type.name}-${is.keyType.name}`}>
|
||||
[{param}]: {is.valueName},
|
||||
</span>,
|
||||
);
|
||||
}
|
||||
const propertyList = _.reduce(properties, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '\n\t', curr];
|
||||
});
|
||||
return (
|
||||
<span>
|
||||
{`{`}
|
||||
<br />
|
||||
{'\t'}
|
||||
{propertyList}
|
||||
<br />
|
||||
{`}`}
|
||||
</span>
|
||||
);
|
||||
}
|
150
packages/react-docs/src/components/method_block.tsx
Normal file
150
packages/react-docs/src/components/method_block.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import { AnchorTitle, colors, HeaderSizes, Styles } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
import { typeDocUtils } from '../utils/typedoc_utils';
|
||||
|
||||
import { Comment } from './comment';
|
||||
import { MethodSignature } from './method_signature';
|
||||
import { SourceLink } from './source_link';
|
||||
|
||||
export interface MethodBlockProps {
|
||||
method: SolidityMethod | TypescriptMethod;
|
||||
sectionName: string;
|
||||
libraryVersion: string;
|
||||
typeDefinitionByName: TypeDefinitionByName;
|
||||
docsInfo: DocsInfo;
|
||||
sourceUrl: string;
|
||||
}
|
||||
|
||||
export interface MethodBlockState {
|
||||
shouldShowAnchor: boolean;
|
||||
}
|
||||
|
||||
const styles: Styles = {
|
||||
chip: {
|
||||
fontSize: 13,
|
||||
backgroundColor: colors.lightBlueA700,
|
||||
color: colors.white,
|
||||
height: 11,
|
||||
borderRadius: 14,
|
||||
lineHeight: 0.9,
|
||||
},
|
||||
};
|
||||
|
||||
export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockState> {
|
||||
constructor(props: MethodBlockProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shouldShowAnchor: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const method = this.props.method;
|
||||
if (typeDocUtils.isPrivateOrProtectedProperty(method.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id={`${this.props.sectionName}-${method.name}`}
|
||||
style={{ overflow: 'hidden', width: '100%' }}
|
||||
className="pb4"
|
||||
onMouseOver={this._setAnchorVisibility.bind(this, true)}
|
||||
onMouseOut={this._setAnchorVisibility.bind(this, false)}
|
||||
>
|
||||
{!method.isConstructor && (
|
||||
<div className="flex pb2 pt2">
|
||||
{(method as TypescriptMethod).isStatic && this._renderChip('Static')}
|
||||
{(method as SolidityMethod).isConstant && this._renderChip('Constant')}
|
||||
{(method as SolidityMethod).isPayable && this._renderChip('Payable')}
|
||||
<div style={{ lineHeight: 1.3 }}>
|
||||
<AnchorTitle
|
||||
headerSize={HeaderSizes.H3}
|
||||
title={method.name}
|
||||
id={`${this.props.sectionName}-${method.name}`}
|
||||
shouldShowAnchor={this.state.shouldShowAnchor}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<code className={`hljs ${constants.TYPE_TO_SYNTAX[this.props.docsInfo.type]}`}>
|
||||
<MethodSignature
|
||||
method={method}
|
||||
sectionName={this.props.sectionName}
|
||||
typeDefinitionByName={this.props.typeDefinitionByName}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
</code>
|
||||
{(method as TypescriptMethod).source && (
|
||||
<SourceLink
|
||||
version={this.props.libraryVersion}
|
||||
source={(method as TypescriptMethod).source}
|
||||
sourceUrl={this.props.sourceUrl}
|
||||
/>
|
||||
)}
|
||||
{method.comment && <Comment comment={method.comment} className="py2" />}
|
||||
{method.parameters &&
|
||||
!_.isEmpty(method.parameters) && (
|
||||
<div>
|
||||
<h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
|
||||
ARGUMENTS
|
||||
</h4>
|
||||
{this._renderParameterDescriptions(method.parameters)}
|
||||
</div>
|
||||
)}
|
||||
{method.returnComment && (
|
||||
<div className="pt1 comment">
|
||||
<h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
|
||||
RETURNS
|
||||
</h4>
|
||||
<Comment comment={method.returnComment} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderChip(text: string) {
|
||||
return (
|
||||
<div className="p1 mr1" style={styles.chip}>
|
||||
{text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderParameterDescriptions(parameters: Parameter[]) {
|
||||
const descriptions = _.map(parameters, parameter => {
|
||||
const isOptional = parameter.isOptional;
|
||||
return (
|
||||
<div
|
||||
key={`param-description-${parameter.name}`}
|
||||
className="flex pb1 mb2"
|
||||
style={{ borderBottom: '1px solid #f0f4f7' }}
|
||||
>
|
||||
<div className="pl2 col lg-col-4 md-col-4 sm-col-12 col-12">
|
||||
<div
|
||||
className="bold"
|
||||
style={{ overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}
|
||||
>
|
||||
{parameter.name}
|
||||
</div>
|
||||
<div className="pt1" style={{ color: colors.grey, fontSize: 14 }}>
|
||||
{isOptional && 'optional'}
|
||||
</div>
|
||||
</div>
|
||||
<div className="col lg-col-8 md-col-8 sm-col-12 col-12" style={{ paddingLeft: 5 }}>
|
||||
{parameter.comment && <Comment comment={parameter.comment} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return descriptions;
|
||||
}
|
||||
private _setAnchorVisibility(shouldShowAnchor: boolean) {
|
||||
this.setState({
|
||||
shouldShowAnchor,
|
||||
});
|
||||
}
|
||||
}
|
128
packages/react-docs/src/components/method_signature.tsx
Normal file
128
packages/react-docs/src/components/method_signature.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
|
||||
import { Type } from './type';
|
||||
|
||||
export interface MethodSignatureProps {
|
||||
method: TypescriptMethod | SolidityMethod;
|
||||
sectionName: string;
|
||||
shouldHideMethodName?: boolean;
|
||||
shouldUseArrowSyntax?: boolean;
|
||||
typeDefinitionByName?: TypeDefinitionByName;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
shouldHideMethodName: false,
|
||||
shouldUseArrowSyntax: false,
|
||||
};
|
||||
|
||||
export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSignatureProps) => {
|
||||
const sectionName = constants.TYPES_SECTION_NAME;
|
||||
const parameters = renderParameters(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
|
||||
const paramStringArray: any[] = [];
|
||||
// HACK: For now we don't put params on newlines if there are less then 2 of them.
|
||||
// Ideally we would check the character length of the resulting method signature and
|
||||
// if it exceeds the available space, put params on their own lines.
|
||||
const hasMoreThenTwoParams = parameters.length > 2;
|
||||
_.each(parameters, (param: React.ReactNode, i: number) => {
|
||||
const finalParam = hasMoreThenTwoParams ? (
|
||||
<span className="pl2" key={`param-${i}`}>
|
||||
{param}
|
||||
</span>
|
||||
) : (
|
||||
param
|
||||
);
|
||||
paramStringArray.push(finalParam);
|
||||
const comma = hasMoreThenTwoParams ? (
|
||||
<span key={`param-comma-${i}`}>
|
||||
, <br />
|
||||
</span>
|
||||
) : (
|
||||
', '
|
||||
);
|
||||
paramStringArray.push(comma);
|
||||
});
|
||||
if (!hasMoreThenTwoParams) {
|
||||
paramStringArray.pop();
|
||||
}
|
||||
const methodName = props.shouldHideMethodName ? '' : props.method.name;
|
||||
const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter)
|
||||
? undefined
|
||||
: renderTypeParameter(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
|
||||
return (
|
||||
<span style={{ fontSize: 15 }}>
|
||||
{props.method.callPath}
|
||||
{methodName}
|
||||
{typeParameterIfExists}({hasMoreThenTwoParams && <br />}
|
||||
{paramStringArray})
|
||||
{props.method.returnType && (
|
||||
<span>
|
||||
{props.shouldUseArrowSyntax ? ' => ' : ': '}{' '}
|
||||
<Type
|
||||
type={props.method.returnType}
|
||||
sectionName={sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
MethodSignature.defaultProps = defaultProps;
|
||||
|
||||
function renderParameters(
|
||||
method: TypescriptMethod | SolidityMethod,
|
||||
docsInfo: DocsInfo,
|
||||
sectionName: string,
|
||||
typeDefinitionByName?: TypeDefinitionByName,
|
||||
) {
|
||||
const parameters = method.parameters;
|
||||
const params = _.map(parameters, (p: Parameter) => {
|
||||
const isOptional = p.isOptional;
|
||||
const type = (
|
||||
<Type
|
||||
type={p.type}
|
||||
sectionName={sectionName}
|
||||
typeDefinitionByName={typeDefinitionByName}
|
||||
docsInfo={docsInfo}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<span key={`param-${p.type}-${p.name}`}>
|
||||
{p.name}
|
||||
{isOptional && '?'}: {type}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
return params;
|
||||
}
|
||||
|
||||
function renderTypeParameter(
|
||||
method: TypescriptMethod,
|
||||
docsInfo: DocsInfo,
|
||||
sectionName: string,
|
||||
typeDefinitionByName?: TypeDefinitionByName,
|
||||
) {
|
||||
const typeParameter = method.typeParameter;
|
||||
const typeParam = (
|
||||
<span>
|
||||
{`<${typeParameter.name} extends `}
|
||||
<Type
|
||||
type={typeParameter.type}
|
||||
sectionName={sectionName}
|
||||
typeDefinitionByName={typeDefinitionByName}
|
||||
docsInfo={docsInfo}
|
||||
/>
|
||||
{`>`}
|
||||
</span>
|
||||
);
|
||||
return typeParam;
|
||||
}
|
23
packages/react-docs/src/components/source_link.tsx
Normal file
23
packages/react-docs/src/components/source_link.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { colors } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Source } from '../types';
|
||||
|
||||
export interface SourceLinkProps {
|
||||
source: Source;
|
||||
sourceUrl: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export function SourceLink(props: SourceLinkProps) {
|
||||
const src = props.source;
|
||||
const sourceCodeUrl = `${props.sourceUrl}/${src.fileName}#L${src.line}`;
|
||||
return (
|
||||
<div className="pt2" style={{ fontSize: 14 }}>
|
||||
<a href={sourceCodeUrl} target="_blank" className="underline" style={{ color: colors.grey }}>
|
||||
Source
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
227
packages/react-docs/src/components/type.tsx
Normal file
227
packages/react-docs/src/components/type.tsx
Normal file
@@ -0,0 +1,227 @@
|
||||
import { colors, constants as sharedConstants, utils as sharedUtils } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import { Link as ScrollLink } from 'react-scroll';
|
||||
import * as ReactTooltip from 'react-tooltip';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { Type as TypeDef, TypeDefinitionByName, TypeDocTypes } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { TypeDefinition } from './type_definition';
|
||||
|
||||
const typeToSection: { [typeName: string]: string } = {
|
||||
ExchangeWrapper: 'exchange',
|
||||
TokenWrapper: 'token',
|
||||
TokenRegistryWrapper: 'tokenRegistry',
|
||||
EtherTokenWrapper: 'etherToken',
|
||||
ProxyWrapper: 'proxy',
|
||||
TokenTransferProxyWrapper: 'proxy',
|
||||
OrderStateWatcher: 'orderWatcher',
|
||||
};
|
||||
|
||||
export interface TypeProps {
|
||||
type: TypeDef;
|
||||
docsInfo: DocsInfo;
|
||||
sectionName: string;
|
||||
typeDefinitionByName?: TypeDefinitionByName;
|
||||
}
|
||||
|
||||
// The return type needs to be `any` here so that we can recursively define <Type /> components within
|
||||
// <Type /> components (e.g when rendering the union type).
|
||||
export function Type(props: TypeProps): any {
|
||||
const type = props.type;
|
||||
const isReference = type.typeDocType === TypeDocTypes.Reference;
|
||||
const isArray = type.typeDocType === TypeDocTypes.Array;
|
||||
let typeNameColor = 'inherit';
|
||||
let typeName: string | React.ReactNode;
|
||||
let typeArgs: React.ReactNode[] = [];
|
||||
switch (type.typeDocType) {
|
||||
case TypeDocTypes.Intrinsic:
|
||||
case TypeDocTypes.Unknown:
|
||||
typeName = type.name;
|
||||
typeNameColor = colors.orange;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Reference:
|
||||
typeName = type.name;
|
||||
typeArgs = _.map(type.typeArguments, (arg: TypeDef) => {
|
||||
if (arg.typeDocType === TypeDocTypes.Array) {
|
||||
const key = `type-${arg.elementType.name}-${arg.elementType.typeDocType}`;
|
||||
return (
|
||||
<span>
|
||||
<Type
|
||||
key={key}
|
||||
type={arg.elementType}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>[]
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
const subType = (
|
||||
<Type
|
||||
key={`type-${arg.name}-${arg.value}-${arg.typeDocType}`}
|
||||
type={arg}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
);
|
||||
return subType;
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case TypeDocTypes.StringLiteral:
|
||||
typeName = `'${type.value}'`;
|
||||
typeNameColor = colors.green;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Array:
|
||||
typeName = type.elementType.name;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Union:
|
||||
const unionTypes = _.map(type.types, t => {
|
||||
return (
|
||||
<Type
|
||||
key={`type-${t.name}-${t.value}-${t.typeDocType}`}
|
||||
type={t}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
typeName = _.reduce(unionTypes, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '|', curr];
|
||||
});
|
||||
break;
|
||||
|
||||
case TypeDocTypes.TypeParameter:
|
||||
typeName = type.name;
|
||||
break;
|
||||
|
||||
case TypeDocTypes.Intersection:
|
||||
const intersectionsTypes = _.map(type.types, t => {
|
||||
return (
|
||||
<Type
|
||||
key={`type-${t.name}-${t.value}-${t.typeDocType}`}
|
||||
type={t}
|
||||
sectionName={props.sectionName}
|
||||
typeDefinitionByName={props.typeDefinitionByName}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
);
|
||||
});
|
||||
typeName = _.reduce(intersectionsTypes, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, '&', curr];
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
throw utils.spawnSwitchErr('type.typeDocType', type.typeDocType);
|
||||
}
|
||||
// HACK: Normalize BigNumber to simply BigNumber. For some reason the type
|
||||
// name is unpredictably one or the other.
|
||||
if (typeName === 'BigNumber') {
|
||||
typeName = 'BigNumber';
|
||||
}
|
||||
const commaSeparatedTypeArgs = _.reduce(typeArgs, (prev: React.ReactNode, curr: React.ReactNode) => {
|
||||
return [prev, ', ', curr];
|
||||
});
|
||||
|
||||
let typeNameUrlIfExists;
|
||||
let typePrefixIfExists;
|
||||
let sectionNameIfExists;
|
||||
if (!_.isUndefined(props.docsInfo.typeConfigs)) {
|
||||
typeNameUrlIfExists = !_.isUndefined(props.docsInfo.typeConfigs.typeNameToExternalLink)
|
||||
? props.docsInfo.typeConfigs.typeNameToExternalLink[typeName as string]
|
||||
: undefined;
|
||||
typePrefixIfExists = !_.isUndefined(props.docsInfo.typeConfigs.typeNameToPrefix)
|
||||
? props.docsInfo.typeConfigs.typeNameToPrefix[typeName as string]
|
||||
: undefined;
|
||||
sectionNameIfExists = !_.isUndefined(props.docsInfo.typeConfigs.typeNameToDocSection)
|
||||
? props.docsInfo.typeConfigs.typeNameToDocSection[typeName as string]
|
||||
: undefined;
|
||||
}
|
||||
if (!_.isUndefined(typeNameUrlIfExists)) {
|
||||
typeName = (
|
||||
<a
|
||||
href={typeNameUrlIfExists}
|
||||
target="_blank"
|
||||
className="text-decoration-none"
|
||||
style={{ color: colors.lightBlueA700 }}
|
||||
>
|
||||
{!_.isUndefined(typePrefixIfExists) ? `${typePrefixIfExists}.` : ''}
|
||||
{typeName}
|
||||
</a>
|
||||
);
|
||||
} else if (
|
||||
(isReference || isArray) &&
|
||||
(props.docsInfo.isPublicType(typeName as string) || !_.isUndefined(sectionNameIfExists))
|
||||
) {
|
||||
const id = Math.random().toString();
|
||||
const typeDefinitionAnchorId = _.isUndefined(sectionNameIfExists)
|
||||
? `${props.sectionName}-${typeName}`
|
||||
: sectionNameIfExists;
|
||||
let typeDefinition;
|
||||
if (props.typeDefinitionByName) {
|
||||
typeDefinition = props.typeDefinitionByName[typeName as string];
|
||||
}
|
||||
typeName = (
|
||||
<ScrollLink
|
||||
to={typeDefinitionAnchorId}
|
||||
offset={0}
|
||||
duration={sharedConstants.DOCS_SCROLL_DURATION_MS}
|
||||
containerId={sharedConstants.DOCS_CONTAINER_ID}
|
||||
>
|
||||
{_.isUndefined(typeDefinition) || sharedUtils.isUserOnMobile() ? (
|
||||
<span
|
||||
onClick={sharedUtils.setUrlHash.bind(null, typeDefinitionAnchorId)}
|
||||
style={{ color: colors.lightBlueA700, cursor: 'pointer' }}
|
||||
>
|
||||
{typeName}
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
data-tip={true}
|
||||
data-for={id}
|
||||
onClick={sharedUtils.setUrlHash.bind(null, typeDefinitionAnchorId)}
|
||||
style={{
|
||||
color: colors.lightBlueA700,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
{typeName}
|
||||
<ReactTooltip type="light" effect="solid" id={id} className="typeTooltip">
|
||||
<TypeDefinition
|
||||
sectionName={props.sectionName}
|
||||
customType={typeDefinition}
|
||||
shouldAddId={false}
|
||||
docsInfo={props.docsInfo}
|
||||
/>
|
||||
</ReactTooltip>
|
||||
</span>
|
||||
)}
|
||||
</ScrollLink>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: typeNameColor }}>{typeName}</span>
|
||||
{isArray && '[]'}
|
||||
{!_.isEmpty(typeArgs) && (
|
||||
<span>
|
||||
{'<'}
|
||||
{commaSeparatedTypeArgs}
|
||||
{'>'}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
131
packages/react-docs/src/components/type_definition.tsx
Normal file
131
packages/react-docs/src/components/type_definition.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import { AnchorTitle, colors, HeaderSizes } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { DocsInfo } from '../docs_info';
|
||||
import { CustomType, CustomTypeChild, KindString, TypeDocTypes } from '../types';
|
||||
import { constants } from '../utils/constants';
|
||||
import { utils } from '../utils/utils';
|
||||
|
||||
import { Comment } from './comment';
|
||||
import { CustomEnum } from './custom_enum';
|
||||
import { Enum } from './enum';
|
||||
import { Interface } from './interface';
|
||||
import { MethodSignature } from './method_signature';
|
||||
import { Type } from './type';
|
||||
|
||||
export interface TypeDefinitionProps {
|
||||
sectionName: string;
|
||||
customType: CustomType;
|
||||
shouldAddId?: boolean;
|
||||
docsInfo: DocsInfo;
|
||||
}
|
||||
|
||||
export interface TypeDefinitionState {
|
||||
shouldShowAnchor: boolean;
|
||||
}
|
||||
|
||||
export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDefinitionState> {
|
||||
public static defaultProps: Partial<TypeDefinitionProps> = {
|
||||
shouldAddId: true,
|
||||
};
|
||||
constructor(props: TypeDefinitionProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shouldShowAnchor: false,
|
||||
};
|
||||
}
|
||||
public render() {
|
||||
const customType = this.props.customType;
|
||||
if (!this.props.docsInfo.isPublicType(customType.name)) {
|
||||
return null; // no-op
|
||||
}
|
||||
|
||||
let typePrefix: string;
|
||||
let codeSnippet: React.ReactNode;
|
||||
switch (customType.kindString) {
|
||||
case KindString.Interface:
|
||||
typePrefix = 'Interface';
|
||||
codeSnippet = (
|
||||
<Interface type={customType} sectionName={this.props.sectionName} docsInfo={this.props.docsInfo} />
|
||||
);
|
||||
break;
|
||||
|
||||
case KindString.Variable:
|
||||
typePrefix = 'Enum';
|
||||
codeSnippet = <CustomEnum type={customType} />;
|
||||
break;
|
||||
|
||||
case KindString.Enumeration:
|
||||
typePrefix = 'Enum';
|
||||
const enumValues = _.map(customType.children, (c: CustomTypeChild) => {
|
||||
return {
|
||||
name: c.name,
|
||||
defaultValue: c.defaultValue,
|
||||
};
|
||||
});
|
||||
codeSnippet = <Enum values={enumValues} />;
|
||||
break;
|
||||
|
||||
case KindString.TypeAlias:
|
||||
typePrefix = 'Type Alias';
|
||||
codeSnippet = (
|
||||
<span>
|
||||
<span style={{ color: colors.lightPurple }}>type</span> {customType.name} ={' '}
|
||||
{customType.type.typeDocType !== TypeDocTypes.Reflection ? (
|
||||
<Type
|
||||
type={customType.type}
|
||||
sectionName={this.props.sectionName}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
) : (
|
||||
<MethodSignature
|
||||
method={customType.type.method}
|
||||
sectionName={this.props.sectionName}
|
||||
shouldHideMethodName={true}
|
||||
shouldUseArrowSyntax={true}
|
||||
docsInfo={this.props.docsInfo}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw utils.spawnSwitchErr('type.kindString', customType.kindString);
|
||||
}
|
||||
|
||||
const typeDefinitionAnchorId = `${this.props.sectionName}-${customType.name}`;
|
||||
return (
|
||||
<div
|
||||
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
|
||||
className="pb2"
|
||||
style={{ overflow: 'hidden', width: '100%' }}
|
||||
onMouseOver={this._setAnchorVisibility.bind(this, true)}
|
||||
onMouseOut={this._setAnchorVisibility.bind(this, false)}
|
||||
>
|
||||
<AnchorTitle
|
||||
headerSize={HeaderSizes.H3}
|
||||
title={`${typePrefix} ${customType.name}`}
|
||||
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
|
||||
shouldShowAnchor={this.state.shouldShowAnchor}
|
||||
/>
|
||||
<div style={{ fontSize: 16 }}>
|
||||
<pre>
|
||||
<code className={`hljs ${constants.TYPE_TO_SYNTAX[this.props.docsInfo.type]}`}>
|
||||
{codeSnippet}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
<div style={{ maxWidth: 620 }}>
|
||||
{customType.comment && <Comment comment={customType.comment} className="py2" />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _setAnchorVisibility(shouldShowAnchor: boolean) {
|
||||
this.setState({
|
||||
shouldShowAnchor,
|
||||
});
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user