diff --git a/packages/vx-demo/src/components/Gallery.tsx b/packages/vx-demo/src/components/Gallery.tsx index 195631bb4..95787a6bf 100644 --- a/packages/vx-demo/src/components/Gallery.tsx +++ b/packages/vx-demo/src/components/Gallery.tsx @@ -54,7 +54,7 @@ import Radar, { import Responsive from '../docs-v2/examples/vx-responsive/Example'; import DragI from '../docs-v2/examples/vx-drag-i/Example'; import DragII from '../docs-v2/examples/vx-drag-ii/Example'; -import LinkTypes from './tiles/LinkTypes'; +import LinkTypes from '../docs-v2/examples/vx-linktypes/Example'; import Threshold, { background as thresholdBackground, } from '../docs-v2/examples/vx-threshold/Example'; diff --git a/packages/vx-demo/src/components/tiles/LinkTypes.tsx b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/Example.tsx similarity index 53% rename from packages/vx-demo/src/components/tiles/LinkTypes.tsx rename to packages/vx-demo/src/docs-v2/examples/vx-linktypes/Example.tsx index 889dfd4b2..dc7fa903d 100644 --- a/packages/vx-demo/src/components/tiles/LinkTypes.tsx +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/Example.tsx @@ -1,294 +1,207 @@ -/* eslint-disable @typescript-eslint/no-use-before-define */ -import React, { useState } from 'react'; -import { Group } from '@vx/group'; -import { hierarchy, Tree } from '@vx/hierarchy'; -import { LinearGradient } from '@vx/gradient'; -import { pointRadial } from 'd3-shape'; - -import { - LinkHorizontal, - LinkVertical, - LinkRadial, - LinkHorizontalStep, - LinkVerticalStep, - LinkRadialStep, - LinkHorizontalCurve, - LinkVerticalCurve, - LinkRadialCurve, - LinkHorizontalLine, - LinkVerticalLine, - LinkRadialLine, -} from '@vx/shape'; -import { ShowProvidedProps } from '../../types'; - -interface TreeNode { - name: string; - isExpanded?: boolean; - children?: TreeNode[]; -} - -const data: TreeNode = { - name: 'T', - children: [ - { - name: 'A', - children: [ - { name: 'A1' }, - { name: 'A2' }, - { name: 'A3' }, - { - name: 'C', - children: [ - { - name: 'C1', - }, - { - name: 'D', - children: [ - { - name: 'D1', - }, - { - name: 'D2', - }, - { - name: 'D3', - }, - ], - }, - ], - }, - ], - }, - { name: 'Z' }, - { - name: 'B', - children: [{ name: 'B1' }, { name: 'B2' }, { name: 'B3' }], - }, - ], -}; - -export default function LinkTypes({ - width: totalWidth, - height: totalHeight, - margin = { - top: 30, - left: 30, - right: 30, - bottom: 30, - }, -}: ShowProvidedProps) { - const [layout, setLayout] = useState('cartesian'); - const [orientation, setOrientation] = useState('horizontal'); - const [linkType, setLinkType] = useState('diagonal'); - const [stepPercent, setStepPercent] = useState(0.5); - const forceUpdate = useForceUpdate(); - - if (totalWidth < 10) return null; - - const innerWidth = totalWidth - margin.left - margin.right; - const innerHeight = totalHeight - margin.top - margin.bottom; - - let origin: { x: number; y: number }; - let sizeWidth: number; - let sizeHeight: number; - - if (layout === 'polar') { - origin = { - x: innerWidth / 2, - y: innerHeight / 2, - }; - sizeWidth = 2 * Math.PI; - sizeHeight = Math.min(innerWidth, innerHeight) / 2; - } else { - origin = { x: 0, y: 0 }; - if (orientation === 'vertical') { - sizeWidth = innerWidth; - sizeHeight = innerHeight; - } else { - sizeWidth = innerHeight; - sizeHeight = innerWidth; - } - } - - return ( -
-
- - - - - - - - - - - e.stopPropagation()} - type="range" - min={0} - max={1} - step={0.1} - onChange={e => setStepPercent(Number(e.target.value))} - value={stepPercent} - disabled={linkType !== 'step' || layout === 'polar'} - /> -
- - - - - - (d.isExpanded ? null : d.children))} - size={[sizeWidth, sizeHeight]} - separation={(a, b) => (a.parent === b.parent ? 1 : 0.5) / a.depth} - > - {tree => ( - - {tree.links().map((link, i) => { - let LinkComponent: React.ComponentType; - - if (layout === 'polar') { - if (linkType === 'step') { - LinkComponent = LinkRadialStep; - } else if (linkType === 'curve') { - LinkComponent = LinkRadialCurve; - } else if (linkType === 'line') { - LinkComponent = LinkRadialLine; - } else { - LinkComponent = LinkRadial; - } - } else if (orientation === 'vertical') { - if (linkType === 'step') { - LinkComponent = LinkVerticalStep; - } else if (linkType === 'curve') { - LinkComponent = LinkVerticalCurve; - } else if (linkType === 'line') { - LinkComponent = LinkVerticalLine; - } else { - LinkComponent = LinkVertical; - } - } else if (linkType === 'step') { - LinkComponent = LinkHorizontalStep; - } else if (linkType === 'curve') { - LinkComponent = LinkHorizontalCurve; - } else if (linkType === 'line') { - LinkComponent = LinkHorizontalLine; - } else { - LinkComponent = LinkHorizontal; - } - - return ( - - ); - })} - - {tree.descendants().map((node, key) => { - const width = 40; - const height = 20; - - let top: number; - let left: number; - if (layout === 'polar') { - const [radialX, radialY] = pointRadial(node.x, node.y); - top = radialY; - left = radialX; - } else if (orientation === 'vertical') { - top = node.y; - left = node.x; - } else { - top = node.x; - left = node.y; - } - - return ( - - {node.depth === 0 && ( - { - node.data.isExpanded = !node.data.isExpanded; - console.log(node); - forceUpdate(); - }} - /> - )} - {node.depth !== 0 && ( - { - node.data.isExpanded = !node.data.isExpanded; - console.log(node); - forceUpdate(); - }} - /> - )} - - {node.data.name} - - - ); - })} - - )} - - - -
- ); -} - -function useForceUpdate() { - const [, setValue] = useState(0); - return () => setValue(value => value + 1); // update state to force render -} +import React, { useState } from 'react'; +import { Group } from '@vx/group'; +import { hierarchy, Tree } from '@vx/hierarchy'; +import { LinearGradient } from '@vx/gradient'; +import { pointRadial } from 'd3-shape'; +import useForceUpdate from './useForceUpdate'; +import LinkControls from './LinkControls'; +import getLinkComponent from './getLinkComponent'; + +interface TreeNode { + name: string; + isExpanded?: boolean; + children?: TreeNode[]; +} + +const data: TreeNode = { + name: 'T', + children: [ + { + name: 'A', + children: [ + { name: 'A1' }, + { name: 'A2' }, + { name: 'A3' }, + { + name: 'C', + children: [ + { + name: 'C1', + }, + { + name: 'D', + children: [ + { + name: 'D1', + }, + { + name: 'D2', + }, + { + name: 'D3', + }, + ], + }, + ], + }, + ], + }, + { name: 'Z' }, + { + name: 'B', + children: [{ name: 'B1' }, { name: 'B2' }, { name: 'B3' }], + }, + ], +}; + +const defaultMargin = { top: 30, left: 30, right: 30, bottom: 30 }; + +type Props = { + width: number; + height: number; + margin?: { top: number; right: number; bottom: number; left: number }; +}; + +export default function Example({ + width: totalWidth, + height: totalHeight, + margin = defaultMargin, +}: Props) { + const [layout, setLayout] = useState('cartesian'); + const [orientation, setOrientation] = useState('horizontal'); + const [linkType, setLinkType] = useState('diagonal'); + const [stepPercent, setStepPercent] = useState(0.5); + const forceUpdate = useForceUpdate(); + + const innerWidth = totalWidth - margin.left - margin.right; + const innerHeight = totalHeight - margin.top - margin.bottom; + + let origin: { x: number; y: number }; + let sizeWidth: number; + let sizeHeight: number; + + if (layout === 'polar') { + origin = { + x: innerWidth / 2, + y: innerHeight / 2, + }; + sizeWidth = 2 * Math.PI; + sizeHeight = Math.min(innerWidth, innerHeight) / 2; + } else { + origin = { x: 0, y: 0 }; + if (orientation === 'vertical') { + sizeWidth = innerWidth; + sizeHeight = innerHeight; + } else { + sizeWidth = innerHeight; + sizeHeight = innerWidth; + } + } + + const LinkComponent = getLinkComponent({ layout, linkType, orientation }); + + return totalWidth < 10 ? null : ( +
+ + + + + + (d.isExpanded ? null : d.children))} + size={[sizeWidth, sizeHeight]} + separation={(a, b) => (a.parent === b.parent ? 1 : 0.5) / a.depth} + > + {tree => ( + + {tree.links().map((link, i) => ( + + ))} + + {tree.descendants().map((node, key) => { + const width = 40; + const height = 20; + + let top: number; + let left: number; + if (layout === 'polar') { + const [radialX, radialY] = pointRadial(node.x, node.y); + top = radialY; + left = radialX; + } else if (orientation === 'vertical') { + top = node.y; + left = node.x; + } else { + top = node.x; + left = node.y; + } + + return ( + + {node.depth === 0 && ( + { + node.data.isExpanded = !node.data.isExpanded; + console.log(node); + forceUpdate(); + }} + /> + )} + {node.depth !== 0 && ( + { + node.data.isExpanded = !node.data.isExpanded; + console.log(node); + forceUpdate(); + }} + /> + )} + + {node.data.name} + + + ); + })} + + )} + + + +
+ ); +} diff --git a/packages/vx-demo/src/docs-v2/examples/vx-linktypes/LinkControls.tsx b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/LinkControls.tsx new file mode 100644 index 000000000..64a544986 --- /dev/null +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/LinkControls.tsx @@ -0,0 +1,78 @@ +import React from 'react'; + +const controlStyles = { fontSize: 10 }; + +type Props = { + layout: string; + orientation: string; + linkType: string; + stepPercent: number; + setLayout: (layout: string) => void; + setOrientation: (orientation: string) => void; + setLinkType: (linkType: string) => void; + setStepPercent: (percent: number) => void; +}; + +export default function LinkControls({ + layout, + orientation, + linkType, + stepPercent, + setLayout, + setOrientation, + setLinkType, + setStepPercent, +}: Props) { + return ( +
+   + +    +   + +    +   + + {linkType === 'step' && layout !== 'polar' && ( + <> +    +   + e.stopPropagation()} + type="range" + min={0} + max={1} + step={0.1} + onChange={e => setStepPercent(Number(e.target.value))} + value={stepPercent} + disabled={linkType !== 'step' || layout === 'polar'} + /> + + )} +
+ ); +} diff --git a/packages/vx-demo/src/docs-v2/examples/vx-linktypes/getLinkComponent.ts b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/getLinkComponent.ts new file mode 100644 index 000000000..4fc0ee85b --- /dev/null +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/getLinkComponent.ts @@ -0,0 +1,57 @@ +import { + LinkHorizontal, + LinkVertical, + LinkRadial, + LinkHorizontalStep, + LinkVerticalStep, + LinkRadialStep, + LinkHorizontalCurve, + LinkVerticalCurve, + LinkRadialCurve, + LinkHorizontalLine, + LinkVerticalLine, + LinkRadialLine, +} from '@vx/shape'; + +export default function getLinkComponent({ + layout, + linkType, + orientation, +}: { + layout: string; + linkType: string; + orientation: string; +}): React.ComponentType { + let LinkComponent: React.ComponentType; + + if (layout === 'polar') { + if (linkType === 'step') { + LinkComponent = LinkRadialStep; + } else if (linkType === 'curve') { + LinkComponent = LinkRadialCurve; + } else if (linkType === 'line') { + LinkComponent = LinkRadialLine; + } else { + LinkComponent = LinkRadial; + } + } else if (orientation === 'vertical') { + if (linkType === 'step') { + LinkComponent = LinkVerticalStep; + } else if (linkType === 'curve') { + LinkComponent = LinkVerticalCurve; + } else if (linkType === 'line') { + LinkComponent = LinkVerticalLine; + } else { + LinkComponent = LinkVertical; + } + } else if (linkType === 'step') { + LinkComponent = LinkHorizontalStep; + } else if (linkType === 'curve') { + LinkComponent = LinkHorizontalCurve; + } else if (linkType === 'line') { + LinkComponent = LinkHorizontalLine; + } else { + LinkComponent = LinkHorizontal; + } + return LinkComponent; +} diff --git a/packages/vx-demo/src/docs-v2/examples/vx-linktypes/index.tsx b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/index.tsx new file mode 100644 index 000000000..3313ec317 --- /dev/null +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/index.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { render } from 'react-dom'; +import ParentSize from '@vx/responsive/lib/components/ParentSize'; + +import Example from './Example'; +import './sandbox-styles.css'; + +render( + {({ width, height }) => }, + document.getElementById('root'), +); diff --git a/packages/vx-demo/src/docs-v2/examples/vx-linktypes/package.json b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/package.json new file mode 100644 index 000000000..91fd8e98a --- /dev/null +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/package.json @@ -0,0 +1,28 @@ +{ + "name": "@vx/demo-linktypes", + "description": "Standalone vx link types demo.", + "main": "index.tsx", + "dependencies": { + "@babel/runtime": "^7.8.4", + "@types/react": "^16", + "@types/react-dom": "^16", + "@vx/gradient": "latest", + "@vx/group": "latest", + "@vx/hierarchy": "latest", + "@vx/responsive": "latest", + "@vx/shape": "latest", + "d3-shape": "1.3.7", + "react": "^16.8", + "react-dom": "^16.8", + "react-scripts-ts": "3.1.0", + "typescript": "^3" + }, + "keywords": [ + "visualization", + "d3", + "react", + "vx", + "link", + "shape" + ] +} diff --git a/packages/vx-demo/src/docs-v2/examples/vx-linktypes/sandbox-styles.css b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/sandbox-styles.css new file mode 100644 index 000000000..b91993723 --- /dev/null +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/sandbox-styles.css @@ -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; +} diff --git a/packages/vx-demo/src/docs-v2/examples/vx-linktypes/useForceUpdate.ts b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/useForceUpdate.ts new file mode 100644 index 000000000..f67f64a76 --- /dev/null +++ b/packages/vx-demo/src/docs-v2/examples/vx-linktypes/useForceUpdate.ts @@ -0,0 +1,6 @@ +import { useState } from 'react'; + +export default function useForceUpdate() { + const [, setValue] = useState(0); + return () => setValue(value => value + 1); // update state to force render +} diff --git a/packages/vx-demo/src/pages/LinkTypes.tsx b/packages/vx-demo/src/pages/LinkTypes.tsx index 3c8e1c2bd..56a92a7ad 100644 --- a/packages/vx-demo/src/pages/LinkTypes.tsx +++ b/packages/vx-demo/src/pages/LinkTypes.tsx @@ -1,13 +1,14 @@ import React from 'react'; import Show from '../components/Show'; -import LinkTypes from '../components/tiles/LinkTypes'; -import LinkTypesSource from '!!raw-loader!../components/tiles/LinkTypes'; +import LinkTypes from '../docs-v2/examples/vx-linktypes/Example'; +import LinkTypesSource from '!!raw-loader!../docs-v2/examples/vx-linktypes/Example'; export default () => { return (