From 524108e710c9d1fc46dd4345b8eda6cf85311c8d Mon Sep 17 00:00:00 2001 From: Sameer Rai Date: Wed, 2 Dec 2020 16:05:47 +0545 Subject: [PATCH] Add PieChart --- package.json | 5 +- src/components/PieChart/index.tsx | 90 ++++++++++++++++++++++++++++++ src/components/PieChart/styles.css | 4 ++ src/index.tsx | 2 + src/stories/PieChart.stories.tsx | 38 +++++++++++++ yarn.lock | 12 ++++ 6 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 src/components/PieChart/index.tsx create mode 100644 src/components/PieChart/styles.css create mode 100644 src/stories/PieChart.stories.tsx diff --git a/package.json b/package.json index 6ee0f32..8aae431 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,10 @@ "@babel/runtime-corejs3": "^7.11.2", "@storybook/client-api": "^6.0.21", "@togglecorp/fujs": "^1.9.2-beta.0", - "file-saver": "^2.0.2", "d3-axis": "^2.0.0", "d3-scale": "^3.2.3", + "d3-shape": "^2.0.0", + "file-saver": "^2.0.2", "react-icons": "^3.11.0", "resize-observer": "^1.0.0" }, @@ -75,9 +76,9 @@ "@storybook/addon-links": "^6.0.21", "@storybook/node-logger": "^6.0.21", "@storybook/react": "^6.0.21", - "@types/file-saver": "^2.0.1", "@types/d3-axis": "^2.0.0", "@types/d3-scale": "^3.1.0", + "@types/file-saver": "^2.0.1", "@types/node": "^14.11.2", "@types/react": "^16.9.49", "@types/react-dom": "^16.9.8", diff --git a/src/components/PieChart/index.tsx b/src/components/PieChart/index.tsx new file mode 100644 index 0000000..502bacc --- /dev/null +++ b/src/components/PieChart/index.tsx @@ -0,0 +1,90 @@ +import React, { useMemo } from 'react'; + +import { pie, arc } from 'd3-shape'; + +import styles from './styles.css'; + +export interface PieChartProps { + width: number; + height: number; + innerRadius: number; + data: K[]; + valueSelector: (v: K) => number; + labelSelector: (v: K) => string; + colorSelector?: (v: K) => string; + showLabels?: boolean; +} + +const colorAccent = getComputedStyle(document.documentElement) + .getPropertyValue('--tui-color-accent') + .trim(); + +const defaultColorSelector = () => colorAccent; + +function PieChart(props: PieChartProps) { + const { + width, + height, + data, + valueSelector, + labelSelector, + colorSelector = defaultColorSelector, + innerRadius = 0, + showLabels = true, + } = props; + + const pieGenerator = useMemo( + () => pie() + .value(valueSelector), + [valueSelector], + ); + + const arcGenerator = useMemo( + () => arc() + .innerRadius(innerRadius) + .outerRadius(Math.min(width, height) / 2 - 1), + [innerRadius, width, height], + ); + + const arcs = pieGenerator(data); + + return ( + + + + {arcs.map((d) => ( + + {labelSelector(d.data)} + + ))} + + { showLabels && ( + + {arcs.map((d) => ( + + + {labelSelector(d.data)} + + + ))} + + )} + + + ); +} + +export default PieChart; diff --git a/src/components/PieChart/styles.css b/src/components/PieChart/styles.css new file mode 100644 index 0000000..8ba6952 --- /dev/null +++ b/src/components/PieChart/styles.css @@ -0,0 +1,4 @@ +.text-label { + fill: var(--tui-color-text); + font-size: var(--tui-font-size-medium); +} diff --git a/src/index.tsx b/src/index.tsx index 0dbacd2..e9eedc8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -89,3 +89,5 @@ export { default as ToggleButton } from './components/ToggleButton'; export type { ToggleButtonProps } from './components/ToggleButton'; export { default as VisualFeedback } from './components/VisualFeedback'; export type { VisualFeedbackProps } from './components/VisualFeedback'; +export { default as PieChart } from './components/PieChart'; +export type { PieChartProps } from './components/PieChart'; diff --git a/src/stories/PieChart.stories.tsx b/src/stories/PieChart.stories.tsx new file mode 100644 index 0000000..1d31748 --- /dev/null +++ b/src/stories/PieChart.stories.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { Story } from '@storybook/react/types-6-0'; + +import PieChart, { PieChartProps } from '#components/PieChart'; + +export default { + title: 'Visualization/PieChart', + component: PieChart, + argTypes: {}, +}; + +interface Item { + label: string; + value: number; +} + +const data = [ + { label: 'Jhapa', value: 20000, color: '#7fc97f' }, + { label: 'Illam', value: 10000, color: '#beaed4' }, + { label: 'Panchthar', value: 30000, color: '#fdc086' }, + { label: 'Taplejung', value: 50000, color: '#ffff99' }, +]; + +const Template: Story> = (props) => ( + d.value} + labelSelector={(d) => d.label} + colorSelector={(d) => d.color} + /> +); + +export const Default = Template.bind({}); +Default.args = { +}; diff --git a/yarn.lock b/yarn.lock index 655b98b..6390976 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5877,6 +5877,11 @@ d3-axis@^2.0.0: dependencies: d3-color "1 - 2" +"d3-path@1 - 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-2.0.0.tgz#55d86ac131a0548adae241eebfb56b4582dd09d8" + integrity sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA== + d3-scale@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.2.3.tgz#be380f57f1f61d4ff2e6cbb65a40593a51649cfd" @@ -5888,6 +5893,13 @@ d3-scale@^3.2.3: d3-time "1 - 2" d3-time-format "2 - 3" +d3-shape@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-2.0.0.tgz#2331b62fa784a2a1daac47a7233cfd69301381fd" + integrity sha512-djpGlA779ua+rImicYyyjnOjeubyhql1Jyn1HK0bTyawuH76UQRWXd+pftr67H6Fa8hSwetkgb/0id3agKWykw== + dependencies: + d3-path "1 - 2" + "d3-time-format@2 - 3": version "3.0.0" resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6"