Skip to content

Commit

Permalink
feat(circle-packing): init hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc authored and wyze committed Apr 26, 2021
1 parent 1f5290a commit 6fb27f7
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 15 deletions.
3 changes: 2 additions & 1 deletion packages/circle-packing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"recompose": "^0.30.0"
},
"devDependencies": {
"@nivo/core": "0.68.0"
"@nivo/core": "0.68.0",
"@types/d3-hierarchy": "^1.1.7"
},
"peerDependencies": {
"@nivo/core": "0.68.0",
Expand Down
97 changes: 97 additions & 0 deletions packages/circle-packing/src/CirclePack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { createElement, Fragment, ReactNode } from 'react'
import {
// @ts-ignore
bindDefs,
useDimensions,
Container,
SvgWrapper,
usePropertyAccessor,
} from '@nivo/core'
import { CirclePackLayerId, CirclePackSvgProps } from './types'
import { useCirclePack } from './hooks'

const defaultProps = {
id: 'id',
value: 'value',

layers: ['circles', 'labels'] as CirclePackLayerId[],

isInteractive: true,

animate: true,
motionConfig: 'gentle',

role: 'img',
}

const InnerCirclePack = <RawDatum,>({
data,
id = defaultProps.id,
value = defaultProps.value,
valueFormat,

width,
height,
margin: partialMargin,

layers = defaultProps.layers,

role = defaultProps.role,
}: Partial<CirclePackSvgProps<RawDatum>>) => {
const { outerWidth, outerHeight, margin, innerWidth, innerHeight } = useDimensions(
width,
height,
partialMargin
)

useCirclePack<RawDatum>({
data,
id,
value,
})
const layerById: Record<CirclePackLayerId, ReactNode> = {
circles: null,
labels: null,
}

const layerContext = {}

return (
<SvgWrapper
width={outerWidth}
height={outerHeight}
margin={margin}
//defs={boundDefs}
role={role}
>
{layers.map((layer, i) => {
if (layerById[layer as CirclePackLayerId] !== undefined) {
return layerById[layer as CirclePackLayerId]
}

if (typeof layer === 'function') {
return <Fragment key={i}>{createElement(layer, layerContext)}</Fragment>
}

return null
})}
</SvgWrapper>
)
}

export const CirclePack = <RawDatum,>({
isInteractive = defaultProps.isInteractive,
animate = defaultProps.animate,
motionConfig = defaultProps.motionConfig,
theme,
...otherProps
}: CirclePackSvgProps<RawDatum>) => (
<Container
isInteractive={isInteractive}
animate={animate}
motionConfig={motionConfig}
theme={theme}
>
<InnerCirclePack<RawDatum> isInteractive={isInteractive} {...otherProps} />
</Container>
)
14 changes: 14 additions & 0 deletions packages/circle-packing/src/ResponsiveCirclePack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'
import { ResponsiveWrapper } from '@nivo/core'
import { CirclePack } from './CirclePack'
import { CirclePackSvgProps } from './types'

export const ResponsiveCirclePack = <RawDatum,>(
props: Omit<CirclePackSvgProps<RawDatum>, 'width' | 'height'>
) => (
<ResponsiveWrapper>
{({ width, height }: { width: number; height: number }) => (
<CirclePack<RawDatum> width={width} height={height} {...props} />
)}
</ResponsiveWrapper>
)
21 changes: 21 additions & 0 deletions packages/circle-packing/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { usePropertyAccessor } from '@nivo/core'
import { DatumWithChildren, CirclePackSvgProps } from './types'

export const useCirclePack = <RawDatum extends DatumWithChildren<RawDatum>>({
data,
id,
value,
}: {
data: RawDatum
id: CirclePackSvgProps<RawDatum>['id']
value: CirclePackSvgProps<RawDatum>['value']
}) => {
const getId = usePropertyAccessor<RawDatum, string | number>(id)
const getValue = usePropertyAccessor<RawDatum, number>(value)

console.log({
data,
getId,
getValue,
})
}
12 changes: 4 additions & 8 deletions packages/circle-packing/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
/*
* This file is part of the nivo project.
*
* Copyright 2016-present, Raphaël Benitte.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { default as Bubble } from './Bubble'
export { default as ResponsiveBubble } from './ResponsiveBubble'
export { default as BubbleHtml } from './BubbleHtml'
export { default as ResponsiveBubbleHtml } from './ResponsiveBubbleHtml'
export { default as BubbleCanvas } from './BubbleCanvas'
export { default as ResponsiveBubbleCanvas } from './ResponsiveBubbleCanvas'
export * from './props'

export * from './CirclePack'
export * from './ResponsiveCirclePack'
export * from './types'
43 changes: 43 additions & 0 deletions packages/circle-packing/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react'
import {
Box,
Dimensions,
ModernMotionProps,
Theme,
PropertyAccessor,
ValueFormat,
} from '@nivo/core'

export interface DatumWithChildren<RawDatum extends DatumWithChildren<RawDatum>> {
children?: RawDatum[]
}

export type CirclePackLayerId = 'circles' | 'labels'

export interface CirclePackCustomLayerProps<RawDatum extends DatumWithChildren<RawDatum>> {}

export type CirclePackCustomLayer<RawDatum> = React.FC<CirclePackCustomLayerProps<RawDatum>>

export type CirclePackLayer<RawDatum> = CirclePackLayerId | CirclePackCustomLayer<RawDatum>

export interface CirclePackSvgProps<RawDatum extends DatumWithChildren<RawDatum>>
extends Dimensions {
data: RawDatum

id: PropertyAccessor<RawDatum, string | number>
value: PropertyAccessor<RawDatum, number>
valueFormat?: ValueFormat<number>

margin: Box

layers: CirclePackLayer<RawDatum>[]

theme: Theme

isInteractive: boolean

animate: boolean
motionConfig: ModernMotionProps['motionConfig']

role: string
}
2 changes: 1 addition & 1 deletion website/src/data/components/bubble/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {

const props = [
{
key: 'root',
key: 'data',
help: 'The hierarchical data object.',
type: 'object',
required: true,
Expand Down
9 changes: 4 additions & 5 deletions website/src/pages/bubble/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/
import React from 'react'
import { patternLinesDef } from '@nivo/core'
import { ResponsiveBubble, BubbleDefaultProps } from '@nivo/circle-packing'
import { ResponsiveCirclePack, BubbleDefaultProps } from '@nivo/circle-packing'
import { generateLibTree } from '@nivo/generators'
import ComponentTemplate from '../../components/components/ComponentTemplate'
import meta from '../../data/components/bubble/meta.yml'
Expand Down Expand Up @@ -65,7 +65,7 @@ const initialProperties = {
const Bubble = () => {
return (
<ComponentTemplate
name="Bubble"
name="CirclePack"
meta={meta.Bubble}
icon="circle-packing"
flavors={meta.flavors}
Expand All @@ -75,12 +75,11 @@ const Bubble = () => {
defaultProperties={BubbleDefaultProps}
propertiesMapper={mapper}
generateData={generateLibTree}
dataKey="root"
>
{(properties, data, theme, logAction) => {
return (
<ResponsiveBubble
root={data}
<ResponsiveCirclePack
data={data}
{...properties}
theme={theme}
onClick={({ children, parent, ...node }) => {
Expand Down

0 comments on commit 6fb27f7

Please sign in to comment.