Skip to content

Commit

Permalink
feat(geo): migrate to react hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphaël Benitte authored and Raphaël Benitte committed Mar 27, 2019
1 parent a78b293 commit 9c5f187
Show file tree
Hide file tree
Showing 39 changed files with 4,356 additions and 11,900 deletions.
16 changes: 16 additions & 0 deletions conf/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ capture:
baseUrl: http://localhost:3000
pages:
# capture illustrations for readme
- path: /geomap
selector: .chart-tabs__content
output: ./packages/geo/doc/geomap.png

- path: /geomap/canvas
selector: .chart-tabs__content
output: ./packages/geo/doc/geomap-canvas.png

- path: /choropleth
selector: .chart-tabs__content
output: ./packages/geo/doc/choropleth.png

- path: /choropleth/canvas
selector: .chart-tabs__content
output: ./packages/geo/doc/choropleth-canvas.png

- path: /bar
selector: .chart-tabs__content
output: ./packages/bar/doc/bar.png
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,15 @@
},
"resolutions": {
"upath": "1.1.0",
"**/react": "16.8.4",
"**/react-dom": "16.8.4"
"react": "16.8.4",
"react-dom": "16.8.4"
},
"scripts": {
"changelog": "rm CHANGELOG.md && node scripts/generate-changelog.js"
},
"workspaces": [
"packages/*",
"api"
"api",
"website"
]
}
140 changes: 69 additions & 71 deletions packages/core/src/components/Container.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { Component } from 'react'
import React, { useRef, useState, useCallback } from 'react'
import PropTypes from 'prop-types'
import noop from '../lib/noop'
import { themeContext } from '../theming'
import { tooltipContext } from '../tooltip'

const containerStyle = {
position: 'relative',
Expand All @@ -25,78 +27,74 @@ const noopHandlers = {
hideTooltip: noop,
}

export default class Container extends Component {
static propTypes = {
children: PropTypes.func.isRequired,
isInteractive: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
}

static defaultProps = {
isInteractive: true,
}

state = {
const Container = ({ children, theme, isInteractive = true }) => {
const containerEl = useRef(null)
const [state, setState] = useState({
isTooltipVisible: false,
tooltipContent: null,
position: {},
}

showTooltip = (content, event) => {
const { clientX, clientY } = event
const bounds = this.container.getBoundingClientRect()

const x = clientX - bounds.left
const y = clientY - bounds.top

const position = {}

if (x < bounds.width / 2) position.left = x + 20
else position.right = bounds.width - x + 20

if (y < bounds.height / 2) position.top = y - 12
else position.bottom = bounds.height - y - 12

this.setState({
isTooltipVisible: true,
tooltipContent: content,
position,
})
}

hideTooltip = () => {
this.setState({ isTooltipVisible: false, tooltipContent: null })
}

render() {
const { children, isInteractive, theme } = this.props
const { isTooltipVisible, tooltipContent, position } = this.state

if (!isInteractive) return children(noopHandlers)
})
const showTooltip = useCallback(
(content, event) => {
if (!containerEl) return

const bounds = containerEl.current.getBoundingClientRect()

const { clientX, clientY } = event

const x = clientX - bounds.left
const y = clientY - bounds.top

const position = {}

if (x < bounds.width / 2) position.left = x + 20
else position.right = bounds.width - x + 20

if (y < bounds.height / 2) position.top = y - 12
else position.bottom = bounds.height - y - 12

setState({
isTooltipVisible: true,
tooltipContent: content,
position,
})
},
[containerEl]
)
const hideTooltip = useCallback(() => {
setState({ isTooltipVisible: false, tooltipContent: null })
})
const { isTooltipVisible, tooltipContent, position } = state

return (
<themeContext.Provider value={theme}>
<tooltipContext.Provider value={[showTooltip, hideTooltip]}>
<div style={containerStyle} ref={containerEl}>
{children({
showTooltip: isInteractive ? showTooltip : noop,
hideTooltip: isInteractive ? hideTooltip : noop,
})}
{isTooltipVisible && (
<div
style={{
...tooltipStyle,
...position,
...theme.tooltip,
}}
>
{tooltipContent}
</div>
)}
</div>
</tooltipContext.Provider>
</themeContext.Provider>
)
}

return (
<div
style={containerStyle}
ref={container => {
this.container = container
}}
>
{children({
showTooltip: this.showTooltip,
hideTooltip: this.hideTooltip,
})}
{isTooltipVisible && (
<div
style={{
...tooltipStyle,
...position,
...theme.tooltip,
}}
>
{tooltipContent}
</div>
)}
</div>
)
}
Container.propTypes = {
children: PropTypes.func.isRequired,
isInteractive: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
}

export default Container
1 change: 1 addition & 0 deletions packages/core/src/hocs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export { default as withDimensions } from './withDimensions'
export { default as withHierarchy } from './withHierarchy'
export { default as withMotion } from './withMotion'
export { default as withTheme } from './withTheme'
export * from './withContainer'
104 changes: 104 additions & 0 deletions packages/core/src/hocs/withContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* 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.
*/
import React, { Component, useRef, useState, useCallback } from 'react'
import PropTypes from 'prop-types'
import { themeContext } from '../theming'
import { tooltipContext } from '../tooltip'
import { usePartialTheme } from '../hooks'

const containerStyle = {
position: 'relative',
}

const tooltipStyle = {
pointerEvents: 'none',
position: 'absolute',
zIndex: 10,
}

const Container = ({ theme: partialTheme = {}, children }) => {
const containerEl = useRef(null)
const [state, setState] = useState({
isTooltipVisible: false,
tooltipContent: null,
position: {},
})
const showTooltip = useCallback(
(content, event) => {
if (!containerEl) return

const bounds = containerEl.current.getBoundingClientRect()

const { clientX, clientY } = event

const x = clientX - bounds.left
const y = clientY - bounds.top

const position = {}

if (x < bounds.width / 2) position.left = x + 20
else position.right = bounds.width - x + 20

if (y < bounds.height / 2) position.top = y - 12
else position.bottom = bounds.height - y - 12

setState({
isTooltipVisible: true,
tooltipContent: content,
position,
})
},
[containerEl]
)
const hideTooltip = useCallback(() => {
setState({ isTooltipVisible: false, tooltipContent: null })
})
const { isTooltipVisible, tooltipContent, position } = state
const theme = usePartialTheme(partialTheme)

return (
<themeContext.Provider value={theme}>
<tooltipContext.Provider value={[showTooltip, hideTooltip]}>
<div style={containerStyle} ref={containerEl}>
{children}
{isTooltipVisible && (
<div
style={{
...tooltipStyle,
...position,
...theme.tooltip,
}}
>
{tooltipContent}
</div>
)}
</div>
</tooltipContext.Provider>
</themeContext.Provider>
)
}

Container.propTypes = {
children: PropTypes.node.isRequired,
theme: PropTypes.object,
}

export const withContainer = WrappedComponent => {
return class extends Component {
render() {
const { theme, ...rest } = this.props

return (
<Container theme={theme}>
<WrappedComponent {...rest} />
</Container>
)
}
}
}
10 changes: 10 additions & 0 deletions packages/core/src/hooks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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 * from './useDimensions'
export * from './usePartialTheme'
33 changes: 33 additions & 0 deletions packages/core/src/hooks/useDimensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.
*/
import { useMemo } from 'react'
import { defaultMargin } from '../defaults'

export const useDimensions = (width, height, partialMargin = {}) =>
useMemo(() => {
const margin = {
...defaultMargin,
...partialMargin,
}

return {
margin,
innerWidth: width - margin.left - margin.right,
innerHeight: height - margin.top - margin.bottom,
outerWidth: width,
outerHeight: height,
}
}, [
width,
height,
partialMargin.top,
partialMargin.right,
partialMargin.bottom,
partialMargin.left,
])
13 changes: 13 additions & 0 deletions packages/core/src/hooks/usePartialTheme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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.
*/
import { useMemo } from 'react'
import { defaultTheme, extendDefaultTheme } from '../theming'

export const usePartialTheme = partialTheme =>
useMemo(() => extendDefaultTheme(defaultTheme, partialTheme), [partialTheme])
3 changes: 2 additions & 1 deletion packages/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ export { default as SvgWrapper } from './components/SvgWrapper'
export { default as SmartMotion } from './components/SmartMotion'
export * from './components/dots'
export * from './components/defs'
export * from './components/tooltip'
export * from './tooltip'
export * from './components/axes'
export * from './components/cartesian'
export * from './hocs'
export * from './hooks'
export { default as noop } from './lib/noop'
export * from './lib/propertiesConverters'
export * from './props'
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/theming/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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.
*/
import { createContext, useContext } from 'react'

export const themeContext = createContext()

export const useTheme = () => useContext(themeContext)
Loading

0 comments on commit 9c5f187

Please sign in to comment.