-
Notifications
You must be signed in to change notification settings - Fork 719
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sankey): add @visx/sankey (#1880)
* initialize package * add `Sankey` component * add exports * add default color * add docs page * fix package * fix import and tsconfig * extract to types * add example * change version to 1.0.0 * add to visx-visx * pin version * add controls to sankey example * add sankey tile * add styles to example * add example tile to docs page * add usage to readme * remove console.log * add class names * add tests * fix readme * add tooltip to example * update references * pin d3-shape version d3-sankey dep * revert automatically applied demo tsconfig changes * remove newline * build sizes * remove console.log * format Co-authored-by: Chris Williams <[email protected]> --------- Co-authored-by: Chris Williams <[email protected]>
- Loading branch information
1 parent
d920798
commit 07a91d8
Showing
26 changed files
with
856 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"visx-annotation":{"esm":31002,"lib":43431},"visx-axis":{"esm":21783,"lib":26434},"visx-bounds":{"esm":2948,"lib":3371},"visx-brush":{"esm":56194,"lib":60810},"visx-chord":{"esm":3478,"lib":4691},"visx-clip-path":{"esm":4524,"lib":6062},"visx-curve":{"esm":323,"lib":1462},"visx-delaunay":{"esm":2599,"lib":3428},"visx-demo":{"esm":0,"lib":36731},"visx-drag":{"esm":12756,"lib":14402},"visx-event":{"esm":3878,"lib":5194},"visx-geo":{"esm":13662,"lib":16903},"visx-glyph":{"esm":15177,"lib":19992},"visx-gradient":{"esm":18202,"lib":22847},"visx-grid":{"esm":18982,"lib":22665},"visx-group":{"esm":1648,"lib":2267},"visx-heatmap":{"esm":7394,"lib":8731},"visx-hierarchy":{"esm":12093,"lib":17910},"visx-legend":{"esm":26975,"lib":34055},"visx-marker":{"esm":9152,"lib":11350},"visx-mock-data":{"esm":326040,"lib":329480},"visx-network":{"esm":4674,"lib":6809},"visx-pattern":{"esm":11689,"lib":15763},"visx-point":{"esm":1003,"lib":1818},"visx-react-spring":{"esm":14040,"lib":17765},"visx-responsive":{"esm":16350,"lib":18791},"visx-scale":{"esm":18870,"lib":30555},"visx-shape":{"esm":86912,"lib":108820},"visx-stats":{"esm":13738,"lib":15320},"visx-text":{"esm":8567,"lib":10114},"visx-threshold":{"esm":2907,"lib":3806},"visx-tooltip":{"esm":15233,"lib":21734},"visx-vendor":{"esm":2492,"lib":2702},"visx-visx":{"esm":1524,"lib":4487},"visx-voronoi":{"esm":2314,"lib":3021},"visx-wordcloud":{"esm":2620,"lib":3455},"visx-xychart":{"esm":178473,"lib":240315},"visx-zoom":{"esm":16239,"lib":19297}} | ||
{"visx-annotation":{"esm":31002,"lib":43431},"visx-axis":{"esm":21783,"lib":26434},"visx-bounds":{"esm":2948,"lib":3371},"visx-brush":{"esm":56194,"lib":60810},"visx-chord":{"esm":3478,"lib":4691},"visx-clip-path":{"esm":4524,"lib":6062},"visx-curve":{"esm":323,"lib":1462},"visx-delaunay":{"esm":2599,"lib":3428},"visx-demo":{"esm":0,"lib":36869},"visx-drag":{"esm":12756,"lib":14402},"visx-event":{"esm":3878,"lib":5194},"visx-geo":{"esm":13662,"lib":16903},"visx-glyph":{"esm":15177,"lib":19992},"visx-gradient":{"esm":18202,"lib":22847},"visx-grid":{"esm":18982,"lib":22665},"visx-group":{"esm":1648,"lib":2267},"visx-heatmap":{"esm":7394,"lib":8731},"visx-hierarchy":{"esm":12093,"lib":17910},"visx-legend":{"esm":26975,"lib":34055},"visx-marker":{"esm":9152,"lib":11350},"visx-mock-data":{"esm":326040,"lib":329480},"visx-network":{"esm":4674,"lib":6809},"visx-pattern":{"esm":11689,"lib":15763},"visx-point":{"esm":1003,"lib":1818},"visx-react-spring":{"esm":14040,"lib":17765},"visx-responsive":{"esm":16350,"lib":18791},"visx-sankey":{"esm":3606,"lib":4677},"visx-scale":{"esm":18870,"lib":30555},"visx-shape":{"esm":86912,"lib":108820},"visx-stats":{"esm":13738,"lib":15320},"visx-text":{"esm":8567,"lib":10114},"visx-threshold":{"esm":2907,"lib":3806},"visx-tooltip":{"esm":15233,"lib":21734},"visx-vendor":{"esm":2492,"lib":2702},"visx-visx":{"esm":1524,"lib":4487},"visx-voronoi":{"esm":2314,"lib":3021},"visx-wordcloud":{"esm":2620,"lib":3455},"visx-xychart":{"esm":178473,"lib":240315},"visx-zoom":{"esm":16239,"lib":19297}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
import Sankey, { SankeyDemoProps, background, color } from '../../sandboxes/visx-sankey/Example'; | ||
import GalleryTile from '../GalleryTile'; | ||
|
||
export { default as packageJson } from '../../sandboxes/visx-sankey/package.json'; | ||
|
||
const tileStyles = { background }; | ||
const detailsStyles = { color }; | ||
const exampleProps = { showControls: false }; | ||
|
||
export default function SankeyTile() { | ||
return ( | ||
<GalleryTile<SankeyDemoProps> | ||
title="Sankey" | ||
description="<Sankey.Sankey />" | ||
exampleProps={exampleProps} | ||
exampleRenderer={Sankey} | ||
exampleUrl="/sankey" | ||
tileStyles={tileStyles} | ||
detailsStyles={detailsStyles} | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from 'react'; | ||
import SankeyReadme from '!!raw-loader!../../../../visx-sankey/Readme.md'; | ||
import Sankey from '../../../../visx-sankey/src/Sankey'; | ||
import DocPage from '../../components/DocPage'; | ||
import SankeyTile from '../../components/Gallery/SankeyTile'; | ||
|
||
const components = [Sankey]; | ||
|
||
const examples = [SankeyTile]; | ||
|
||
function SankeyDocs() { | ||
return ( | ||
<DocPage | ||
components={components} | ||
examples={examples} | ||
readme={SankeyReadme} | ||
visxPackage="sankey" | ||
/> | ||
); | ||
} | ||
export default SankeyDocs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react'; | ||
import Sankey from '../sandboxes/visx-sankey/Example'; | ||
import packageJson from '../sandboxes/visx-sankey/package.json'; | ||
import Show from '../components/Show'; | ||
import TreemapSource from '!!raw-loader!../sandboxes/visx-sankey/Example'; | ||
|
||
function SankeyPage() { | ||
return ( | ||
<Show | ||
component={Sankey} | ||
title="Sankey" | ||
codeSandboxDirectoryName="visx-sankey" | ||
packageJson={packageJson} | ||
> | ||
{TreemapSource} | ||
</Show> | ||
); | ||
} | ||
export default SankeyPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
189 changes: 189 additions & 0 deletions
189
packages/visx-demo/src/sandboxes/visx-sankey/Example.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import React, { useState } from 'react'; | ||
import { | ||
Sankey, | ||
sankeyCenter, | ||
sankeyRight, | ||
sankeyLeft, | ||
sankeyJustify, | ||
SankeyNode, | ||
} from '@visx/sankey'; | ||
import { Group } from '@visx/group'; | ||
import { BarRounded, LinkHorizontal } from '@visx/shape'; | ||
import { useTooltip, TooltipWithBounds } from '@visx/tooltip'; | ||
import { localPoint } from '@visx/event'; | ||
|
||
import energy from './energy.json'; | ||
|
||
export const background = '#84dccf'; | ||
export const color = '#392f5a'; | ||
|
||
type NodeDatum = { name: string }; | ||
type LinkDatum = {}; | ||
|
||
const nodeAlignments = { | ||
sankeyCenter, | ||
sankeyJustify, | ||
sankeyLeft, | ||
sankeyRight, | ||
} as const; | ||
|
||
const defaultMargin = { top: 10, left: 10, right: 10, bottom: 10 }; | ||
|
||
export type SankeyDemoProps = { | ||
width: number; | ||
height: number; | ||
showControls?: boolean; | ||
margin?: { top: number; right: number; bottom: number; left: number }; | ||
}; | ||
|
||
export default function SankeyDemo({ | ||
width, | ||
height, | ||
showControls = true, | ||
margin = defaultMargin, | ||
}: SankeyDemoProps) { | ||
const { tooltipData, tooltipLeft, tooltipTop, tooltipOpen, showTooltip, hideTooltip } = | ||
useTooltip(); | ||
const xMax = width - margin.left - margin.right; | ||
const yMax = height - margin.top - margin.bottom; | ||
|
||
const [nodeAlignment, setTileMethod] = useState<keyof typeof nodeAlignments>('sankeyCenter'); | ||
const [nodePadding, setNodePadding] = useState(10); | ||
const [nodeWidth, setNodeWidth] = useState(10); | ||
|
||
if (width < 10) return null; | ||
|
||
return ( | ||
<div> | ||
<style>{` | ||
.visx-sankey-link:hover { | ||
stroke-opacity: 0.7; | ||
} | ||
.visx-sankey-node:hover { | ||
filter: brightness(1.3); | ||
} | ||
.visx-sankey-demo-container { | ||
background: ${background}; | ||
padding: ${margin.top}px ${margin.right}px ${margin.bottom}px ${margin.left}px; | ||
border-radius: 5px; | ||
position: relative; | ||
} | ||
.visx-sankey-demo-controls { | ||
font-size: 12px; | ||
} | ||
`}</style> | ||
{showControls && ( | ||
<div className="visx-sankey-demo-controls"> | ||
<label> | ||
node alignment{' '} | ||
<select | ||
onClick={(e) => e.stopPropagation()} | ||
onChange={(e) => setTileMethod(e.target.value as keyof typeof nodeAlignments)} | ||
value={nodeAlignment} | ||
> | ||
{Object.keys(nodeAlignments).map((alignment) => ( | ||
<option key={alignment} value={alignment}> | ||
{alignment} | ||
</option> | ||
))} | ||
</select> | ||
</label>{' '} | ||
<label> | ||
node padding{' '} | ||
<input | ||
type="number" | ||
value={nodePadding} | ||
onChange={(e) => setNodePadding(Number(e.target.value))} | ||
/> | ||
</label>{' '} | ||
<label> | ||
node width{' '} | ||
<input | ||
type="number" | ||
value={nodeWidth} | ||
onChange={(e) => setNodeWidth(Number(e.target.value))} | ||
/> | ||
</label> | ||
</div> | ||
)} | ||
<div className="visx-sankey-demo-container"> | ||
<svg width={xMax} height={yMax}> | ||
<Sankey<NodeDatum, LinkDatum> | ||
root={energy} | ||
nodeWidth={nodeWidth} | ||
size={[xMax, yMax]} | ||
nodePadding={nodePadding} | ||
nodeAlign={nodeAlignments[nodeAlignment]} | ||
> | ||
{({ graph, createPath }) => ( | ||
<> | ||
<Group> | ||
{graph.links.map((link, i) => ( | ||
<LinkHorizontal | ||
key={i} | ||
className="visx-sankey-link" | ||
data={link} | ||
path={createPath} | ||
fill="transparent" | ||
stroke={color} | ||
strokeWidth={link.width} | ||
strokeOpacity={0.5} | ||
onPointerMove={(event) => { | ||
const coords = localPoint( | ||
(event.target as SVGElement).ownerSVGElement, | ||
event, | ||
); | ||
showTooltip({ | ||
tooltipData: `${ | ||
(link.source as SankeyNode<NodeDatum, LinkDatum>).name | ||
} > ${(link.target as SankeyNode<NodeDatum, LinkDatum>).name} = ${ | ||
link.value | ||
}`, | ||
tooltipTop: (coords?.y ?? 0) + 10, | ||
tooltipLeft: (coords?.x ?? 0) + 10, | ||
}); | ||
}} | ||
onMouseOut={hideTooltip} | ||
/> | ||
))} | ||
</Group> | ||
<Group> | ||
{graph.nodes.map(({ y0, y1, x0, x1, name }, i) => ( | ||
<BarRounded | ||
key={i} | ||
className="visx-sankey-node" | ||
width={x1 - x0} | ||
height={y1 - y0} | ||
x={x0} | ||
y={y0} | ||
radius={3} | ||
all | ||
fill={color} | ||
onPointerMove={(event) => { | ||
const coords = localPoint( | ||
(event.target as SVGElement).ownerSVGElement, | ||
event, | ||
); | ||
showTooltip({ | ||
tooltipData: name, | ||
tooltipTop: (coords?.y ?? 0) + 10, | ||
tooltipLeft: (coords?.x ?? 0) + 10, | ||
}); | ||
}} | ||
onMouseOut={hideTooltip} | ||
/> | ||
))} | ||
</Group> | ||
</> | ||
)} | ||
</Sankey> | ||
</svg> | ||
{tooltipOpen && ( | ||
<TooltipWithBounds key={Math.random()} top={tooltipTop} left={tooltipLeft}> | ||
{tooltipData} | ||
</TooltipWithBounds> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"nodes":[{"name":"Agricultural 'waste'"},{"name":"Bio-conversion"},{"name":"Liquid"},{"name":"Losses"},{"name":"Solid"},{"name":"Gas"},{"name":"Biofuel imports"},{"name":"Biomass imports"},{"name":"Coal imports"},{"name":"Coal"},{"name":"Coal reserves"},{"name":"District heating"},{"name":"Industry"},{"name":"Heating and cooling - commercial"},{"name":"Heating and cooling - homes"},{"name":"Electricity grid"},{"name":"Over generation / exports"},{"name":"H2 conversion"},{"name":"Road transport"},{"name":"Agriculture"},{"name":"Rail transport"},{"name":"Lighting & appliances - commercial"},{"name":"Lighting & appliances - homes"},{"name":"Gas imports"},{"name":"Ngas"},{"name":"Gas reserves"},{"name":"Thermal generation"},{"name":"Geothermal"},{"name":"H2"},{"name":"Hydro"},{"name":"International shipping"},{"name":"Domestic aviation"},{"name":"International aviation"},{"name":"National navigation"},{"name":"Marine algae"},{"name":"Nuclear"},{"name":"Oil imports"},{"name":"Oil"},{"name":"Oil reserves"},{"name":"Other waste"},{"name":"Pumped heat"},{"name":"Solar PV"},{"name":"Solar Thermal"},{"name":"Solar"},{"name":"Tidal"},{"name":"UK land based bioenergy"},{"name":"Wave"},{"name":"Wind"}],"links":[{"source":0,"target":1,"value":124.729},{"source":1,"target":2,"value":0.597},{"source":1,"target":3,"value":26.862},{"source":1,"target":4,"value":280.322},{"source":1,"target":5,"value":81.144},{"source":6,"target":2,"value":35},{"source":7,"target":4,"value":35},{"source":8,"target":9,"value":11.606},{"source":10,"target":9,"value":63.965},{"source":9,"target":4,"value":75.571},{"source":11,"target":12,"value":10.639},{"source":11,"target":13,"value":22.505},{"source":11,"target":14,"value":46.184},{"source":15,"target":16,"value":104.453},{"source":15,"target":14,"value":113.726},{"source":15,"target":17,"value":27.14},{"source":15,"target":12,"value":342.165},{"source":15,"target":18,"value":37.797},{"source":15,"target":19,"value":4.412},{"source":15,"target":13,"value":40.858},{"source":15,"target":3,"value":56.691},{"source":15,"target":20,"value":7.863},{"source":15,"target":21,"value":90.008},{"source":15,"target":22,"value":93.494},{"source":23,"target":24,"value":40.719},{"source":25,"target":24,"value":82.233},{"source":5,"target":13,"value":0.129},{"source":5,"target":3,"value":1.401},{"source":5,"target":26,"value":151.891},{"source":5,"target":19,"value":2.096},{"source":5,"target":12,"value":48.58},{"source":27,"target":15,"value":7.013},{"source":17,"target":28,"value":20.897},{"source":17,"target":3,"value":6.242},{"source":28,"target":18,"value":20.897},{"source":29,"target":15,"value":6.995},{"source":2,"target":12,"value":121.066},{"source":2,"target":30,"value":128.69},{"source":2,"target":18,"value":135.835},{"source":2,"target":31,"value":14.458},{"source":2,"target":32,"value":206.267},{"source":2,"target":19,"value":3.64},{"source":2,"target":33,"value":33.218},{"source":2,"target":20,"value":4.413},{"source":34,"target":1,"value":4.375},{"source":24,"target":5,"value":122.952},{"source":35,"target":26,"value":839.978},{"source":36,"target":37,"value":504.287},{"source":38,"target":37,"value":107.703},{"source":37,"target":2,"value":611.99},{"source":39,"target":4,"value":56.587},{"source":39,"target":1,"value":77.81},{"source":40,"target":14,"value":193.026},{"source":40,"target":13,"value":70.672},{"source":41,"target":15,"value":59.901},{"source":42,"target":14,"value":19.263},{"source":43,"target":42,"value":19.263},{"source":43,"target":41,"value":59.901},{"source":4,"target":19,"value":0.882},{"source":4,"target":26,"value":400.12},{"source":4,"target":12,"value":46.477},{"source":26,"target":15,"value":525.531},{"source":26,"target":3,"value":787.129},{"source":26,"target":11,"value":79.329},{"source":44,"target":15,"value":9.452},{"source":45,"target":1,"value":182.01},{"source":46,"target":15,"value":19.013},{"source":47,"target":15,"value":289.366}]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import { createRoot } from 'react-dom/client'; | ||
import ParentSize from '@visx/responsive/lib/components/ParentSize'; | ||
|
||
import Example from './Example'; | ||
import './sandbox-styles.css'; | ||
|
||
const root = createRoot(document.getElementById('root')!); | ||
|
||
root.render( | ||
<ParentSize>{({ width, height }) => <Example width={width} height={height} />}</ParentSize>, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "@visx/demo-sankey", | ||
"description": "Standalone visx sankey demo.", | ||
"main": "index.tsx", | ||
"private": true, | ||
"dependencies": { | ||
"@babel/runtime": "^7.8.4", | ||
"@types/react": "^18", | ||
"@types/react-dom": "^18" , | ||
"@visx/event": "latest", | ||
"@visx/group": "latest", | ||
"@visx/responsive": "latest", | ||
"@visx/sankey": "latest", | ||
"@visx/shape": "latest", | ||
"@visx/tooltip": "latest", | ||
"react": "^18", | ||
"react-dom": "^18", | ||
"react-scripts-ts": "3.1.0", | ||
"typescript": "^3" | ||
}, | ||
"keywords": [ | ||
"visualization", | ||
"d3", | ||
"react", | ||
"visx", | ||
"sankey" | ||
] | ||
} | ||
|
8 changes: 8 additions & 0 deletions
8
packages/visx-demo/src/sandboxes/visx-sankey/sandbox-styles.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
html, | ||
body, | ||
#root { | ||
height: 100%; | ||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, | ||
'Open Sans', 'Helvetica Neue', sans-serif; | ||
line-height: 2em; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,6 +105,9 @@ | |
{ | ||
"path": "../visx-responsive" | ||
}, | ||
{ | ||
"path": "../visx-sankey" | ||
}, | ||
{ | ||
"path": "../visx-scale" | ||
}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package-lock=false |
Oops, something went wrong.