Skip to content

Commit

Permalink
feat(website): improve typings of ComponentTemplate and use it at its…
Browse files Browse the repository at this point in the history
… full potential for the heatmap
  • Loading branch information
plouc committed Jan 12, 2022
1 parent bda98c8 commit 37136c9
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 238 deletions.
5 changes: 4 additions & 1 deletion packages/heatmap/src/types.ts
Expand Up @@ -145,7 +145,10 @@ export type HeatMapCommonProps<Datum extends HeatMapDatum> = {
>
labelTextColor: InheritedColorConfig<Omit<ComputedCell<Datum>, 'labelTextColor'>>

legends: Omit<AnchoredContinuousColorsLegendProps, 'containerWidth' | 'containerHeight'>[]
legends: Omit<
AnchoredContinuousColorsLegendProps,
'scale' | 'containerWidth' | 'containerHeight'
>[]

annotations: AnnotationMatcher<ComputedCell<Datum>>[]

Expand Down
20 changes: 10 additions & 10 deletions website/src/components/components/ActionsLogger.tsx
@@ -1,13 +1,15 @@
import React, { useState, useCallback } from 'react'
import styled from 'styled-components'
import { FaRegHandPointer } from 'react-icons/fa'
import { ActionsLoggerLog } from './ActionsLoggerLog'
import { ActionsLoggerLog, ActionsLoggerLogData } from './ActionsLoggerLog'
import media from '../../theming/mediaQueries'

export const useActionsLogger = (): [any[], (action: any) => void] => {
const [actions, setActions] = useState<any[]>([])
export type ActionLoggerLogFn = (action: ActionsLoggerLogData) => void

export const useActionsLogger = (): [ActionsLoggerLogData[], ActionLoggerLogFn] => {
const [actions, setActions] = useState<ActionsLoggerLogData[]>([])
const logAction = useCallback(
action => {
(action: ActionsLoggerLogData) => {
setActions(actions => [action, ...actions])
},
[setActions]
Expand All @@ -17,7 +19,7 @@ export const useActionsLogger = (): [any[], (action: any) => void] => {
}

interface ActionsLoggerProps {
actions: any[]
actions: ActionsLoggerLogData[]
isFullWidth?: boolean
}

Expand All @@ -31,11 +33,9 @@ export const ActionsLogger = ({ actions, isFullWidth = false }: ActionsLoggerPro
<EmptyMessage>Start interacting with the chart to log actions</EmptyMessage>
</EmptyContainer>
)}
{actions.map((action, i) => {
return (
<ActionsLoggerLog key={`${i}.${action.type}.${action.label}`} action={action} />
)
})}
{actions.map((action, i) => (
<ActionsLoggerLog key={`${i}.${action.type}.${action.label}`} action={action} />
))}
</Wrapper>
)
}
Expand Down
9 changes: 8 additions & 1 deletion website/src/components/components/ActionsLoggerLog.tsx
@@ -1,7 +1,14 @@
import React, { useState, useCallback } from 'react'
import styled from 'styled-components'

export const ActionsLoggerLog = ({ action }: { action: any }) => {
export interface ActionsLoggerLogData {
type: string
label: string
color?: string
data?: object
}

export const ActionsLoggerLog = ({ action }: { action: ActionsLoggerLogData }) => {
const [isOpen, setIsOpen] = useState(false)
const toggle = useCallback(() => setIsOpen(flag => !flag), [setIsOpen])

Expand Down
61 changes: 36 additions & 25 deletions website/src/components/components/ComponentTemplate.tsx
Expand Up @@ -11,12 +11,17 @@ import { ComponentHeader } from './ComponentHeader'
import { ComponentFlavorSelector } from './ComponentFlavorSelector'
import { ComponentDescription } from './ComponentDescription'
import { ComponentTabs } from './ComponentTabs'
import { ActionsLogger, useActionsLogger } from './ActionsLogger'
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, Props extends object, Data> {
interface ComponentTemplateProps<
UnmappedProps extends object,
MappedProps extends object,
Data,
ComponentProps extends object
> {
name: string
meta: ChartMeta
icon: string
Expand All @@ -32,22 +37,27 @@ interface ComponentTemplateProps<UnmappedProps extends object, Props extends obj
// initial props of the demo, unmapped
initialProperties: UnmappedProps
// default props as defined in the package component
defaultProperties?: Partial<Props>
propertiesMapper?: (unmappedProps: UnmappedProps) => Props
codePropertiesMapper?: Function
hasData?: boolean
generateData?: (previousData?: Data | null) => Data | undefined
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: Props, data: Data, theme: NivoTheme, logAction: any) => JSX.Element
children: (
properties: MappedProps,
data: Data,
theme: NivoTheme,
logAction: ActionLoggerLogFn
) => JSX.Element
image?: IGatsbyImageData
}

export const ComponentTemplate = <
UnmappedProps extends object = any,
Props extends object = any,
Data = any
MappedProps extends object = any,
Data = any,
ComponentProps extends object = any
>({
name,
meta,
Expand All @@ -59,29 +69,30 @@ export const ComponentTemplate = <
defaultProperties = {},
propertiesMapper,
codePropertiesMapper,
hasData = true,
generateData = () => undefined,
dataKey,
generateData,
dataKey = 'data',
getDataSize,
getTabData = data => data,
image,
children,
}: ComponentTemplateProps<UnmappedProps, Props, Data>) => {
}: ComponentTemplateProps<UnmappedProps, MappedProps, Data, ComponentProps>) => {
const theme = useTheme()

const [settings, setSettings] = useState(initialProperties)
const [settings, setSettings] = useState<UnmappedProps>(initialProperties)

const [data, setData] = useState<Data>(() => generateData())

const initialData = useMemo(() => (hasData ? generateData() : null), [])
const [data, setData] = useState(initialData)
const diceRoll = useCallback(() => {
setData(currentData => generateData(currentData))
}, [setData])
}, [setData, generateData])

const [actions, logAction] = useActionsLogger()

let mappedProperties = settings as unknown as Props
let mappedProperties: MappedProps
if (propertiesMapper !== undefined) {
mappedProperties = propertiesMapper(settings, data)
} else {
mappedProperties = settings as unknown as MappedProps
}

let codeProperties = mappedProperties
Expand All @@ -92,7 +103,7 @@ export const ComponentTemplate = <
const code = generateChartCode(`Responsive${name}`, codeProperties, {
pkg: meta.package,
defaults: defaultProperties,
dataKey: hasData ? dataKey : undefined,
dataKey: data !== undefined ? dataKey : undefined,
})

const hasStories = meta.stories !== undefined && meta.stories.length > 0
Expand All @@ -103,6 +114,8 @@ export const ComponentTemplate = <

const flavorKeys = useMemo(() => flavors.map(flavor => flavor.flavor), [flavors])

const tabData = useMemo(() => getTabData(data), [data])

return (
<Layout>
<ComponentPage>
Expand All @@ -113,12 +126,10 @@ export const ComponentTemplate = <
<ComponentTabs<Data>
chartClass={icon}
code={code}
data={hasData ? getTabData(data!) : undefined}
data={tabData}
dataKey={dataKey}
nodeCount={
hasData && getDataSize !== undefined ? getDataSize(data!) : undefined
}
diceRoll={hasData ? diceRoll : undefined}
nodeCount={getDataSize !== undefined ? getDataSize(data) : undefined}
diceRoll={data !== undefined ? diceRoll : undefined}
>
{children(mappedProperties, data, theme.nivo, logAction)}
</ComponentTabs>
Expand Down
96 changes: 28 additions & 68 deletions website/src/data/components/heatmap/generator.ts
@@ -1,70 +1,30 @@
import { generateCountriesData } from '@nivo/generators'
import { generateXYSeries, sets } from '@nivo/generators'
import { Data } from './types'

const dishes = [
'hot dog',
'burger',
'sandwich',
'kebab',
'fries',
'donut',
'junk',
'sushi',
'ramen',
'curry',
'udon',
'bagel',
'yakitori',
'takoyaki',
'tacos',
'miso soup',
'tortilla',
'tapas',
'chipirones',
'gazpacho',
'soba',
'bavette',
'steak',
'pizza',
'spaghetti',
'ravioli',
'salad',
'pad thai',
'bun',
'waffle',
'crepe',
'churros',
'paella',
'empanadas',
'bruschetta',
'onion soup',
'cassoulet',
'bouillabaisse',
'unagi',
'tempura',
'tonkatsu',
'shabu-shabu',
'twinkies',
'jerky',
'fajitas',
'jambalaya',
'meatloaf',
`mac n' cheese`,
'baked beans',
'popcorn',
'buffalo wings',
'BBQ ribs',
'apple pie',
'nachos',
'risotto',
'tiramisu',
]
export const getLightData = () =>
generateXYSeries({
serieIds: ['Japan', 'France', 'US', 'Germany', 'Norway', 'Iceland', 'UK', 'Vietnam'],
x: {
values: ['Train', 'Subway', 'Bus', 'Car', 'Boat', 'Moto', 'Moped', 'Bicycle', 'Others'],
},
y: {
length: NaN,
min: -100_000,
max: 100_000,
round: true,
},
}) as Data

export const generateLightDataSet = () => ({
data: generateCountriesData(dishes.slice(0, 11), { size: 9, min: 0, max: 100 }),
keys: dishes.slice(0, 11),
})

export const generateHeavyDataSet = () => ({
data: generateCountriesData(dishes, { size: 22, min: 0, max: 100 }),
keys: dishes,
})
export const getHeavyData = () =>
generateXYSeries({
serieIds: sets.countryCodes.slice(0, 26),
x: {
values: sets.names,
},
y: {
length: NaN,
min: -100_000,
max: 100_000,
round: true,
},
}) as Data
21 changes: 21 additions & 0 deletions website/src/data/components/heatmap/mapper.ts
@@ -0,0 +1,21 @@
import { settingsMapper, mapAxis, mapFormat } from '../../../lib/settings'
import { SvgUnmappedProps, SvgMappedProps } from './types'

export default settingsMapper(
{
valueFormat: mapFormat,
axisTop: mapAxis('top'),
axisRight: mapAxis('right'),
axisBottom: mapAxis('bottom'),
axisLeft: mapAxis('left'),
legends: (legends: SvgUnmappedProps['legends'][number][]): SvgMappedProps['legends'] => {
return legends.map(legend => ({
...legend,
tickFormat: mapFormat(legend.tickFormat),
}))
},
},
{
exclude: ['enable axisTop', 'enable axisRight', 'enable axisBottom', 'enable axisLeft'],
}
)
62 changes: 0 additions & 62 deletions website/src/data/components/heatmap/mapper.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion website/src/data/components/heatmap/props.ts
Expand Up @@ -426,7 +426,7 @@ const props: ChartProperty[] = [
defaultValue: 'rect',
control: {
type: 'choices',
choices: ['rect', 'circle', 'CustomCell'].map(key => ({
choices: ['rect', 'circle'].map(key => ({
label: key,
value: key,
})),
Expand Down

0 comments on commit 37136c9

Please sign in to comment.