/
ComponentTemplate.tsx
148 lines (134 loc) · 5.05 KB
/
ComponentTemplate.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import React, { useState, useCallback, useMemo } from 'react'
import { IGatsbyImageData } from 'gatsby-plugin-image'
import { useTheme } from 'styled-components'
import { Theme as NivoTheme } from '@nivo/core'
import { startCase } from 'lodash'
import { Seo } from '../Seo'
import Layout from '../Layout'
import { generateChartCode } from '../../lib/generateChartCode'
import { ComponentPage } from './ComponentPage'
import { ComponentHeader } from './ComponentHeader'
import { ComponentFlavorSelector } from './ComponentFlavorSelector'
import { ComponentDescription } from './ComponentDescription'
import { ComponentTabs } from './ComponentTabs'
import { ActionsLogger, useActionsLogger, ActionLoggerLogFn } from './ActionsLogger'
import { ComponentSettings } from './ComponentSettings'
import { Stories } from './Stories'
import { ChartMeta, ChartProperty, Flavor } from '../../types'
interface ComponentTemplateProps<
UnmappedProps extends object,
MappedProps extends object,
Data,
ComponentProps extends object
> {
name: string
meta: ChartMeta
icon: string
flavors: {
flavor: Flavor
path: string
}[]
currentFlavor: Flavor
properties: {
name: string
properties: ChartProperty[]
}[]
// initial props of the demo, unmapped
initialProperties: UnmappedProps
// default props as defined in the package component
defaultProperties?: Partial<ComponentProps>
propertiesMapper?: (props: UnmappedProps, data: Data) => MappedProps
codePropertiesMapper?: (props: MappedProps, data: Data) => MappedProps
generateData: (previousData?: Data | null) => Data
dataKey?: string
getDataSize?: (data: Data) => number
getTabData?: (data: Data) => Data
children: (
properties: MappedProps,
data: Data,
theme: NivoTheme,
logAction: ActionLoggerLogFn
) => JSX.Element
image?: IGatsbyImageData
}
export const ComponentTemplate = <
UnmappedProps extends object = any,
MappedProps extends object = any,
Data = any,
ComponentProps extends object = any
>({
name,
meta,
icon,
flavors,
currentFlavor,
properties,
initialProperties,
defaultProperties = {},
propertiesMapper,
codePropertiesMapper,
generateData,
dataKey = 'data',
getDataSize,
getTabData = data => data,
image,
children,
}: ComponentTemplateProps<UnmappedProps, MappedProps, Data, ComponentProps>) => {
const theme = useTheme()
const [settings, setSettings] = useState<UnmappedProps>(initialProperties)
const [data, setData] = useState<Data>(() => generateData())
const diceRoll = useCallback(() => {
setData(currentData => generateData(currentData))
}, [setData, generateData])
const [actions, logAction] = useActionsLogger()
let mappedProperties: MappedProps
if (propertiesMapper !== undefined) {
mappedProperties = propertiesMapper(settings, data)
} else {
mappedProperties = settings as unknown as MappedProps
}
let codeProperties = mappedProperties
if (codePropertiesMapper !== undefined) {
codeProperties = codePropertiesMapper(mappedProperties, data)
}
const code = generateChartCode(`Responsive${name}`, codeProperties, {
pkg: meta.package,
defaults: defaultProperties,
dataKey: data !== undefined ? dataKey : undefined,
})
const hasStories = meta.stories !== undefined && meta.stories.length > 0
const title = `${startCase(name)} chart`
const description = `${meta.package} package ${startCase(name)} chart.`
const tags = useMemo(() => [meta.package, ...meta.tags], [meta])
const flavorKeys = useMemo(() => flavors.map(flavor => flavor.flavor), [flavors])
const tabData = useMemo(() => getTabData(data), [data])
return (
<Layout>
<ComponentPage>
<Seo title={title} description={description} image={image} keywords={tags} />
<ComponentHeader chartClass={name} tags={tags} />
<ComponentFlavorSelector flavors={flavors} current={currentFlavor} />
<ComponentDescription description={meta.description} />
<ComponentTabs<Data>
chartClass={icon}
code={code}
data={tabData}
dataKey={dataKey}
nodeCount={getDataSize !== undefined ? getDataSize(data) : undefined}
diceRoll={data !== undefined ? diceRoll : undefined}
>
{children(mappedProperties, data, theme.nivo, logAction)}
</ComponentTabs>
<ActionsLogger actions={actions} isFullWidth={!hasStories} />
<ComponentSettings
settings={settings}
onChange={setSettings}
groups={properties}
flavors={flavorKeys}
currentFlavor={currentFlavor}
/>
{hasStories && <Stories stories={meta.stories} />}
</ComponentPage>
</Layout>
)
}