Skip to content

Commit

Permalink
feat: new Props component
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronauck committed Feb 19, 2019
1 parent 0b1799d commit 80451b1
Show file tree
Hide file tree
Showing 22 changed files with 236 additions and 220 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ Then create some `.mdx` anywhere inside your project:
name: Button
---

import { Playground, PropsTable } from 'docz'
import { Playground, Props } from 'docz'
import Button from './'

# Button

<PropsTable of={Button} />
<Props of={Button} />

## Basic usage

Expand Down
93 changes: 93 additions & 0 deletions core/docz-theme-default/src/components/ui/Props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as React from 'react'
import { useMemo } from 'react'
import { PropsComponentProps, useComponents } from 'docz'
import styled from 'styled-components'

import { get } from '@utils/theme'

const Wrapper = styled.div`
display: flex;
flex-direction: column;
& ~ & {
margin-top: 20px;
}
`

const Title = styled.div`
display: flex;
border-bottom: 1px solid ${get('colors.sidebarBg')};
`

const PropName = styled.span`
background: ${get('colors.sidebarBg')};
color: ${get('colors.sidebarText')};
padding: 5px 10px;
border-radius: 4px 4px 0 0;
font-size: 14px;
& ~ & {
margin-left: 5px;
}
`

const PropType = styled(PropName)`
color: ${get('colors.blockquoteColor')};
`

const PropDefaultValue = styled(PropType)`
background: transparent;
padding-left: 0;
padding-right: 0;
`

const PropRequired = styled(PropType)`
flex: 1;
text-align: right;
background: transparent;
color: ${get('colors.blockquoteColor')};
opacity: 0.5;
`

export const Props: React.SFC<PropsComponentProps> = ({
props,
getPropType,
}) => {
const entries = Object.entries(props)
const components = useComponents()
const Paragraph = useMemo(
() => styled(components.P || 'p')`
font-size: 14px;
color: ${get('colors.sidebarTex')};
`,
[]
)

return (
<React.Fragment>
{entries.map(([key, prop]) => (
<Wrapper key={key}>
<Title>
<PropName>{key}</PropName>
<PropType>{getPropType(prop)}</PropType>
{prop.defaultValue && (
<PropDefaultValue>
{prop.defaultValue.value === "''" ? (
<em>= [Empty String]</em>
) : (
<em>= {prop.defaultValue.value.replace(/\'/g, '"')}</em>
)}
</PropDefaultValue>
)}
{prop.required && (
<PropRequired>
<em>required</em>
</PropRequired>
)}
</Title>
{prop.description && <Paragraph>{prop.description}</Paragraph>}
</Wrapper>
))}
</React.Fragment>
)
}
1 change: 1 addition & 0 deletions core/docz-theme-default/src/components/ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export { OrderedList } from './OrderedList'
export { Page } from './Page'
export { Paragraph } from './Paragraph'
export { Pre } from './Pre'
export { Props } from './Props'
export { Table } from './Table'
export { UnorderedList } from './UnorderedList'
1 change: 1 addition & 0 deletions core/docz-theme-default/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const componentsMap = {
page: components.Page,
playground: components.AsyncPlayground,
pre: components.Pre,
props: components.Props,
table: components.Table,
ul: components.UnorderedList,
}
Expand Down
109 changes: 109 additions & 0 deletions core/docz/src/components/Props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import * as React from 'react'
import { SFC, ComponentType } from 'react'
import { last, get } from 'lodash/fp'
import capitalize from 'capitalize'

import { doczState } from '../state'
import { useComponents } from '../hooks'
import { humanize } from '../utils/humanize-prop'

export interface EnumValue {
value: string
computed: boolean
}

export interface FlowTypeElement {
name: string
value: string
}

export interface FlowTypeArgs {
name: string
type: {
name: string
}
}

export interface PropType {
name: string
value?: any
raw?: any
computed?: boolean
}

export interface FlowType extends PropType {
elements: FlowTypeElement[]
name: string
raw: string
type?: string
computed?: boolean
signature?: {
arguments: FlowTypeArgs[]
return: {
name: string
}
}
}

export interface Prop {
required: boolean
description?: string
type: PropType
defaultValue?: {
value: string
computed: boolean
}
flowType?: FlowType
}

export type ComponentWithDocGenInfo = ComponentType & {
__docgenInfo: {
description?: string
props?: Record<string, Prop>
}
}

export interface PropsProps {
of: ComponentWithDocGenInfo
}

export const getPropType = (prop: Prop) => {
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 (
(isEnum && typeof value === 'string') ||
(!prop.flowType && !isEnum && !value) ||
(prop.flowType && !prop.flowType.elements)
) {
return name
}

return prop.flowType ? humanize(prop.flowType) : humanize(prop.type)
}

export interface PropsComponentProps {
props: Record<string, Prop>
getPropType(prop: Prop): string
}

export const Props: SFC<PropsProps> = ({ of: component }) => {
const components = useComponents()
const { props: stateProps } = React.useContext(doczState.context)
const filename = get('__filemeta.filename', component)
const found =
stateProps &&
stateProps.length > 0 &&
stateProps.find(item => item.key === filename)

const definition = last(found ? found.value : [])
const props = get('props', definition)

if (!props) return null
if (!components.props) return null
return <components.props props={props} getPropType={getPropType} />
}
Loading

0 comments on commit 80451b1

Please sign in to comment.