From 0d5bc4948a865c8ac4d5583a2ff93da8e2f8e74f Mon Sep 17 00:00:00 2001
From: Dan Labrecque
Date: Fri, 27 Sep 2024 16:54:42 -0400
Subject: [PATCH 1/2] feat(charts): import charts from
@patternfly/react-charts/victory
---
packages/react-charts/victory/package.json | 1 +
1 file changed, 1 insertion(+)
create mode 100644 packages/react-charts/victory/package.json
diff --git a/packages/react-charts/victory/package.json b/packages/react-charts/victory/package.json
new file mode 100644
index 00000000000..1be7f7b05c5
--- /dev/null
+++ b/packages/react-charts/victory/package.json
@@ -0,0 +1 @@
+{"name":"@patternfly/react-charts-victory","main":"../dist/js/victory/index.js","module":"../dist/esm/victory/index.js","typings":"../dist/esm/victory/index.d.ts","version":"8.0.0-prerelease.12","private":true}
From b998f8dae59251c35ee327bad6bace786ec276a8 Mon Sep 17 00:00:00 2001
From: Dan Labrecque
Date: Fri, 6 Sep 2024 07:54:22 -0400
Subject: [PATCH 2/2] feat(charts): sankey
---
packages/react-charts/package.json | 6 +-
.../react-charts/single-packages.config.json | 2 +-
.../echarts/components/Sankey/Sankey.test.tsx | 83 ++++
.../src/echarts/components/Sankey/Sankey.tsx | 210 +++++++++
.../components/Sankey/examples/Basic.tsx | 96 ++++
.../components/Sankey/examples/Sankey.md | 22 +
.../src/echarts/components/Sankey/index.ts | 1 +
.../src/echarts/components/Sankey/theme.ts | 415 ++++++++++++++++++
.../src/echarts/components/index.ts | 1 +
.../src/echarts/components/utils/misc.ts | 23 +
.../src/echarts/components/utils/observe.ts | 38 ++
.../src/echarts/components/utils/theme.ts | 9 +
packages/react-charts/src/echarts/index.ts | 1 +
packages/react-charts/subpaths.config.json | 2 +-
packages/react-charts/tsconfig.json | 7 +-
packages/react-charts/victory/package.json | 2 +-
packages/react-docs/package.json | 1 +
yarn.lock | 38 +-
18 files changed, 947 insertions(+), 10 deletions(-)
create mode 100644 packages/react-charts/src/echarts/components/Sankey/Sankey.test.tsx
create mode 100644 packages/react-charts/src/echarts/components/Sankey/Sankey.tsx
create mode 100644 packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx
create mode 100644 packages/react-charts/src/echarts/components/Sankey/examples/Sankey.md
create mode 100644 packages/react-charts/src/echarts/components/Sankey/index.ts
create mode 100644 packages/react-charts/src/echarts/components/Sankey/theme.ts
create mode 100644 packages/react-charts/src/echarts/components/index.ts
create mode 100644 packages/react-charts/src/echarts/components/utils/misc.ts
create mode 100644 packages/react-charts/src/echarts/components/utils/observe.ts
create mode 100644 packages/react-charts/src/echarts/components/utils/theme.ts
create mode 100644 packages/react-charts/src/echarts/index.ts
diff --git a/packages/react-charts/package.json b/packages/react-charts/package.json
index 2b8018b615b..3b76bf5b653 100644
--- a/packages/react-charts/package.json
+++ b/packages/react-charts/package.json
@@ -7,6 +7,9 @@
"types": "dist/esm/index.d.ts",
"typesVersions": {
"*": {
+ "echarts": [
+ "dist/esm/echarts/index.d.ts"
+ ],
"victory": [
"dist/esm/victory/index.d.ts"
]
@@ -43,6 +46,7 @@
"tslib": "^2.7.0"
},
"peerDependencies": {
+ "echarts": "^5.5.1",
"react": "^17 || ^18",
"react-dom": "^17 || ^18",
"victory-area": "^37.1.1",
@@ -69,7 +73,7 @@
"subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
},
"devDependencies": {
- "@types/lodash": "^4.17.9",
+ "@types/lodash": "^4.17.7",
"fs-extra": "^11.2.0"
}
}
diff --git a/packages/react-charts/single-packages.config.json b/packages/react-charts/single-packages.config.json
index 4a9651bb17d..8b418fd2095 100644
--- a/packages/react-charts/single-packages.config.json
+++ b/packages/react-charts/single-packages.config.json
@@ -1,4 +1,4 @@
{
"packageName": "@patternfly/react-charts",
- "exclude": ["dist/esm/deprecated/index.js", "dist/esm/next/index.js"]
+ "exclude": ["dist/esm/deprecated/index.js"]
}
diff --git a/packages/react-charts/src/echarts/components/Sankey/Sankey.test.tsx b/packages/react-charts/src/echarts/components/Sankey/Sankey.test.tsx
new file mode 100644
index 00000000000..ff3418f6d94
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/Sankey/Sankey.test.tsx
@@ -0,0 +1,83 @@
+import * as React from 'react';
+// import * as echarts from 'echarts';
+import { render } from '@testing-library/react';
+import { Sankey } from './Sankey';
+
+const data = [
+ {
+ name: 'a'
+ },
+ {
+ name: 'b'
+ },
+ {
+ name: 'a1'
+ },
+ {
+ name: 'a2'
+ },
+ {
+ name: 'b1'
+ },
+ {
+ name: 'c'
+ }
+];
+
+const links = [
+ {
+ source: 'a',
+ target: 'a1',
+ value: 5
+ },
+ {
+ source: 'a',
+ target: 'a2',
+ value: 3
+ },
+ {
+ source: 'b',
+ target: 'b1',
+ value: 8
+ },
+ {
+ source: 'a',
+ target: 'b1',
+ value: 3
+ },
+ {
+ source: 'b1',
+ target: 'a1',
+ value: 1
+ },
+ {
+ source: 'b1',
+ target: 'c',
+ value: 2
+ }
+];
+
+let spy: any;
+
+// beforeAll(() => {
+// console.log(`*** TEST 1`);
+// spy = jest.spyOn(echarts, 'getInstanceByDom').mockImplementation(
+// () =>
+// ({
+// hideLoading: jest.fn(),
+// setOption: jest.fn(),
+// showLoading: jest.fn()
+// }) as any
+// );
+// });
+//
+// afterAll(() => {
+// console.log(`*** TEST 2`);
+// spy.mockRestore();
+// });
+
+// See https://stackoverflow.com/questions/54921743/testing-echarts-react-component-with-jest-echartelement-is-null
+xtest('renders component data', () => {
+ const { asFragment } = render();
+ expect(asFragment()).toMatchSnapshot();
+});
diff --git a/packages/react-charts/src/echarts/components/Sankey/Sankey.tsx b/packages/react-charts/src/echarts/components/Sankey/Sankey.tsx
new file mode 100644
index 00000000000..0ec68e11a66
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/Sankey/Sankey.tsx
@@ -0,0 +1,210 @@
+/* eslint-disable camelcase */
+import chart_voronoi_flyout_stroke_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_flyout_stroke_Fill';
+import chart_voronoi_labels_Fill from '@patternfly/react-tokens/dist/esm/chart_voronoi_labels_Fill';
+
+import * as React from 'react';
+import * as echarts from 'echarts';
+import { useCallback, useRef, useState } from 'react';
+import defaultsDeep from 'lodash/defaultsDeep';
+import { getMutationObserver } from '../utils/observe';
+import { getComputedStyle } from '../utils/theme';
+
+// import { BarChart, SankeyChart } from 'echarts/charts';
+// import { CanvasRenderer } from 'echarts/renderers';
+
+// import {
+// TitleComponent,
+// TooltipComponent,
+// GridComponent,
+// DatasetComponent,
+// TransformComponent
+// } from 'echarts/components';
+
+// Register the required components
+// echarts.use([
+// BarChart,
+// SankeyChart,
+// TitleComponent,
+// TooltipComponent,
+// GridComponent,
+// DatasetComponent,
+// TransformComponent,
+// LabelLayout,
+// UniversalTransition,
+// CanvasRenderer
+// ]);
+
+import { getTheme } from './theme';
+import { getClassName } from '../utils/misc';
+
+/**
+ */
+export interface SankeyProps {
+ className?: string;
+ destinationLabel?: string;
+ height?: number;
+ id?: string;
+ legend?: {
+ symbolSize?: number; // Todo: move into tooltip?
+ };
+ lineStyle?: any;
+
+ /**
+ * This creates a Mutation Observer to watch the given DOM selector.
+ *
+ * When the pf-v6-theme-dark selector is added or removed, this component will be notified to update its computed
+ * theme styles. However, if the dark theme is not updated dynamically (e.g., via a toggle), there is no need to add
+ * this Mutation Observer.
+ *
+ * Note: Don't provide ".pf-v6-theme-dark" as the node selector as it won't exist in the page for light theme.
+ * The underlying querySelectorAll() function needs to find the element the dark theme selector will be added to.
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Locating_DOM_elements_using_selectors
+ *
+ * @propType string
+ * @example
+ * @example
+ * @example
+ */
+ nodeSelector?: string;
+ opts?: any;
+ series: any[];
+ sourceLabel?: string;
+ theme?: any;
+ title?: any;
+ tooltip?: any;
+ width?: number;
+}
+
+export const Sankey: React.FunctionComponent = ({
+ className,
+ destinationLabel = 'Destination',
+ height,
+ id,
+ legend = {
+ symbolSize: 10
+ },
+ lineStyle = {
+ color: 'source',
+ opacity: 0.6
+ },
+ nodeSelector,
+ opts,
+ series,
+ sourceLabel = 'Source',
+ theme,
+ title,
+ tooltip = {
+ valueFormatter: (value: number | string) => value
+ },
+ width
+}: SankeyProps) => {
+ const containerRef = useRef();
+ const echart = useRef();
+ const [chartTheme, setChartTheme] = useState(theme || getTheme());
+
+ const getItemColor = useCallback(
+ (params: any) => {
+ const serie = series[params.seriesIndex];
+ const sourceData = serie?.data.find((datum: any) => datum.name === params.data?.source);
+ const targetData = serie?.data.find((datum: any) => datum.name === params.data?.target);
+ const sourceColor = sourceData?.itemStyle?.color;
+ const targetColor = targetData?.itemStyle?.color;
+ return { sourceColor, targetColor };
+ },
+ [series]
+ );
+
+ const getTooltip = useCallback(() => {
+ const symbolSize = `${legend.symbolSize}px`;
+ const defaults = {
+ backgroundColor: getComputedStyle(chart_voronoi_flyout_stroke_Fill),
+ confine: true,
+ formatter: (params: any) => {
+ const result = `
+
+ ${params.name} ${params.value}
+ `;
+ if (params.data.source && params.data.target) {
+ const { sourceColor, targetColor } = getItemColor(params);
+ return `
+ ${sourceLabel}
+
+ ${params.data.source}
+ ${destinationLabel}
+
+
+ ${params.data.target}
+
+ ${tooltip.valueFormatter(params.value, params.dataIndex)}
+
+
+ `;
+ }
+ return result.replace(/\s\s+/g, ' ');
+ },
+ textStyle: {
+ color: getComputedStyle(chart_voronoi_labels_Fill)
+ },
+ trigger: 'item',
+ triggerOn: 'mousemove'
+ };
+ return defaultsDeep(tooltip, defaults);
+ }, [destinationLabel, getItemColor, legend.symbolSize, sourceLabel, tooltip]);
+
+ React.useEffect(() => {
+ echarts.registerTheme('pf-v5-sankey', chartTheme);
+ echart.current = echarts.init(containerRef.current, 'pf-v5-sankey', { renderer: 'svg' }); // renderer: 'svg'
+
+ const newSeries = series.map((serie: any) => {
+ const defaults = {
+ data: serie.data.map((datum: any, index: number) => ({
+ itemStyle: {
+ color: chartTheme?.color[index % chartTheme?.color.length]
+ }
+ })),
+ emphasis: {
+ focus: 'adjacency'
+ },
+ layout: 'none',
+ lineStyle,
+ type: 'sankey'
+ };
+ return defaultsDeep(serie, defaults);
+ });
+
+ echart.current?.setOption({
+ series: newSeries,
+ title,
+ tooltip: getTooltip()
+ });
+
+ return () => {
+ echart.current?.dispose();
+ };
+ }, [chartTheme, containerRef, getTooltip, lineStyle, opts, series, title, tooltip]);
+
+ // Resize observer
+ React.useEffect(() => {
+ echart.current?.resize();
+ }, [height, width]);
+
+ // Dark theme observer
+ React.useEffect(() => {
+ let observer = () => {};
+ observer = getMutationObserver(nodeSelector, () => {
+ setChartTheme(getTheme());
+ });
+ return () => {
+ observer();
+ };
+ }, [nodeSelector]);
+
+ const getSize = () => ({
+ ...(height && { height: `${height}px` }),
+ ...(width && { width: `${width}px` })
+ });
+
+ return ;
+};
+Sankey.displayName = 'Sankey';
diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx b/packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx
new file mode 100644
index 00000000000..93737ce1028
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/Sankey/examples/Basic.tsx
@@ -0,0 +1,96 @@
+import React from 'react';
+import { Sankey } from '@patternfly/react-charts/echarts';
+import { getResizeObserver } from '@patternfly/react-core';
+
+export const FormBasic: React.FunctionComponent = () => {
+ const data = [
+ {
+ name: 'a'
+ },
+ {
+ name: 'b'
+ },
+ {
+ name: 'a1'
+ },
+ {
+ name: 'a2'
+ },
+ {
+ name: 'b1'
+ },
+ {
+ name: 'c'
+ }
+ ];
+
+ const links = [
+ {
+ source: 'a',
+ target: 'a1',
+ value: 5
+ },
+ {
+ source: 'a',
+ target: 'a2',
+ value: 3
+ },
+ {
+ source: 'b',
+ target: 'b1',
+ value: 8
+ },
+ {
+ source: 'a',
+ target: 'b1',
+ value: 3
+ },
+ {
+ source: 'b1',
+ target: 'a1',
+ value: 1
+ },
+ {
+ source: 'b1',
+ target: 'c',
+ value: 2
+ }
+ ];
+
+ // let observer = () => {};
+ const containerRef = React.useRef();
+ const [width, setWidth] = React.useState(0);
+
+ React.useEffect(() => {
+ const handleResize = () => {
+ if (containerRef.current && containerRef.current.clientWidth) {
+ setWidth(containerRef.current.clientWidth);
+ }
+ };
+ let observer = () => {};
+ observer = getResizeObserver(containerRef.current, handleResize);
+
+ return () => {
+ observer();
+ };
+ }, [containerRef, width]);
+
+ return (
+
+ `${value} GiB`
+ }}
+ width={width}
+ />
+
+ );
+};
diff --git a/packages/react-charts/src/echarts/components/Sankey/examples/Sankey.md b/packages/react-charts/src/echarts/components/Sankey/examples/Sankey.md
new file mode 100644
index 00000000000..7e8565e150a
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/Sankey/examples/Sankey.md
@@ -0,0 +1,22 @@
+---
+id: Sankey
+section: charts
+propComponents: [
+ 'Sankey',
+]
+beta: true
+---
+
+import { Sankey } from '@patternfly/react-charts/echarts';
+
+## Introduction
+Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)!
+
+PatternFly React charts are based on the [Apache ECharts](https://echarts.apache.org/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior.
+
+## Examples
+### Basic
+
+```ts file="./Basic.tsx"
+
+```
diff --git a/packages/react-charts/src/echarts/components/Sankey/index.ts b/packages/react-charts/src/echarts/components/Sankey/index.ts
new file mode 100644
index 00000000000..4bb44aaee6a
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/Sankey/index.ts
@@ -0,0 +1 @@
+export * from './Sankey';
diff --git a/packages/react-charts/src/echarts/components/Sankey/theme.ts b/packages/react-charts/src/echarts/components/Sankey/theme.ts
new file mode 100644
index 00000000000..41fbab2f64c
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/Sankey/theme.ts
@@ -0,0 +1,415 @@
+/* eslint-disable camelcase */
+import chart_theme_multi_color_ordered_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_100';
+import chart_theme_multi_color_ordered_ColorScale_200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_200';
+import chart_theme_multi_color_ordered_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_300';
+import chart_theme_multi_color_ordered_ColorScale_400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_400';
+import chart_theme_multi_color_ordered_ColorScale_500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_500';
+import chart_theme_multi_color_ordered_ColorScale_600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_600';
+import chart_theme_multi_color_ordered_ColorScale_700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_700';
+import chart_theme_multi_color_ordered_ColorScale_800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_800';
+import chart_theme_multi_color_ordered_ColorScale_900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_900';
+import chart_theme_multi_color_ordered_ColorScale_1000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1000';
+import chart_theme_multi_color_ordered_ColorScale_1100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1100';
+import chart_theme_multi_color_ordered_ColorScale_1200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1200';
+import chart_theme_multi_color_ordered_ColorScale_1300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1300';
+import chart_theme_multi_color_ordered_ColorScale_1400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1400';
+import chart_theme_multi_color_ordered_ColorScale_1500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1500';
+import chart_theme_multi_color_ordered_ColorScale_1600 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1600';
+import chart_theme_multi_color_ordered_ColorScale_1700 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1700';
+import chart_theme_multi_color_ordered_ColorScale_1800 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1800';
+import chart_theme_multi_color_ordered_ColorScale_1900 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_1900';
+import chart_theme_multi_color_ordered_ColorScale_2000 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2000';
+import chart_theme_multi_color_ordered_ColorScale_2100 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2100';
+import chart_theme_multi_color_ordered_ColorScale_2200 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2200';
+import chart_theme_multi_color_ordered_ColorScale_2300 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2300';
+import chart_theme_multi_color_ordered_ColorScale_2400 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2400';
+import chart_theme_multi_color_ordered_ColorScale_2500 from '@patternfly/react-tokens/dist/esm/chart_theme_multi_color_ordered_ColorScale_2500';
+import chart_global_label_Fill from '@patternfly/react-tokens/dist/esm/chart_global_label_Fill';
+
+import { getComputedStyle } from '../utils/theme';
+
+export const getTheme = () => {
+ // The color order below improves the color contrast in unordered charts; area & line
+ // See https://github.com/patternfly/patternfly-next/issues/1551
+ const COLOR_SCALE = [
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_100),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_200),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_300),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_400),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_500),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_600),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_700),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_800),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_900),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1000),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1100),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1200),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1300),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1400),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1500),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1600),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1700),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1800),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_1900),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_2000),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_2100),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_2200),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_2300),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_2400),
+ getComputedStyle(chart_theme_multi_color_ordered_ColorScale_2500)
+ ];
+
+ return {
+ color: COLOR_SCALE,
+ backgroundColor: 'rgba(0,0,0,0)',
+ label: {
+ color: getComputedStyle(chart_global_label_Fill)
+ },
+ textStyle: {},
+ title: {
+ textStyle: {
+ // color: '#464646'
+ color: getComputedStyle(chart_global_label_Fill)
+ },
+ subtextStyle: {
+ // color: '#6e7079'
+ color: getComputedStyle(chart_global_label_Fill)
+ }
+ },
+ line: {
+ itemStyle: {
+ borderWidth: 1
+ },
+ lineStyle: {
+ width: 2
+ },
+ symbolSize: 4,
+ symbol: 'emptyCircle',
+ smooth: false
+ },
+ radar: {
+ itemStyle: {
+ borderWidth: 1
+ },
+ lineStyle: {
+ width: 2
+ },
+ symbolSize: 4,
+ symbol: 'emptyCircle',
+ smooth: false
+ },
+ bar: {
+ itemStyle: {
+ barBorderWidth: 0,
+ barBorderColor: '#ccc'
+ }
+ },
+ pie: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ scatter: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ boxplot: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ parallel: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ sankey: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ funnel: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ gauge: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ }
+ },
+ candlestick: {
+ itemStyle: {
+ color: '#eb5454',
+ color0: '#47b262',
+ borderColor: '#eb5454',
+ borderColor0: '#47b262',
+ borderWidth: 1
+ }
+ },
+ graph: {
+ itemStyle: {
+ borderWidth: 0,
+ borderColor: '#ccc'
+ },
+ lineStyle: {
+ width: 1,
+ color: '#aaaaaa'
+ },
+ symbolSize: 4,
+ symbol: 'emptyCircle',
+ smooth: false,
+ color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
+ label: {
+ color: '#eeeeee'
+ }
+ },
+ map: {
+ itemStyle: {
+ areaColor: '#eee',
+ borderColor: '#444',
+ borderWidth: 0.5
+ },
+ label: {
+ color: '#000'
+ },
+ emphasis: {
+ itemStyle: {
+ areaColor: 'rgba(255,215,0,0.8)',
+ borderColor: '#444',
+ borderWidth: 1
+ },
+ label: {
+ color: 'rgb(100,0,0)'
+ }
+ }
+ },
+ geo: {
+ itemStyle: {
+ areaColor: '#eee',
+ borderColor: '#444',
+ borderWidth: 0.5
+ },
+ label: {
+ color: '#000'
+ },
+ emphasis: {
+ itemStyle: {
+ areaColor: 'rgba(255,215,0,0.8)',
+ borderColor: '#444',
+ borderWidth: 1
+ },
+ label: {
+ color: 'rgb(100,0,0)'
+ }
+ }
+ },
+ categoryAxis: {
+ axisLine: {
+ show: true,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisTick: {
+ show: true,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisLabel: {
+ show: true,
+ color: '#6E7079'
+ },
+ splitLine: {
+ show: false,
+ lineStyle: {
+ color: ['#E0E6F1']
+ }
+ },
+ splitArea: {
+ show: false,
+ areaStyle: {
+ color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)']
+ }
+ }
+ },
+ valueAxis: {
+ axisLine: {
+ show: false,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisTick: {
+ show: false,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisLabel: {
+ show: true,
+ color: '#6E7079'
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: ['#E0E6F1']
+ }
+ },
+ splitArea: {
+ show: false,
+ areaStyle: {
+ color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)']
+ }
+ }
+ },
+ logAxis: {
+ axisLine: {
+ show: false,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisTick: {
+ show: false,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisLabel: {
+ show: true,
+ color: '#6E7079'
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: ['#E0E6F1']
+ }
+ },
+ splitArea: {
+ show: false,
+ areaStyle: {
+ color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)']
+ }
+ }
+ },
+ timeAxis: {
+ axisLine: {
+ show: true,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisTick: {
+ show: true,
+ lineStyle: {
+ color: '#6E7079'
+ }
+ },
+ axisLabel: {
+ show: true,
+ color: '#6E7079'
+ },
+ splitLine: {
+ show: false,
+ lineStyle: {
+ color: ['#E0E6F1']
+ }
+ },
+ splitArea: {
+ show: false,
+ areaStyle: {
+ color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)']
+ }
+ }
+ },
+ toolbox: {
+ iconStyle: {
+ borderColor: '#999999'
+ },
+ emphasis: {
+ iconStyle: {
+ borderColor: '#666666'
+ }
+ }
+ },
+ legend: {
+ textStyle: {
+ color: '#333333'
+ }
+ },
+ tooltip: {
+ axisPointer: {
+ lineStyle: {
+ color: '#cccccc',
+ width: 1
+ },
+ crossStyle: {
+ color: '#cccccc',
+ width: 1
+ }
+ }
+ },
+ timeline: {
+ lineStyle: {
+ color: '#dae1f5',
+ width: 2
+ },
+ itemStyle: {
+ color: '#a4b1d7',
+ borderWidth: 1
+ },
+ controlStyle: {
+ color: '#a4b1d7',
+ borderColor: '#a4b1d7',
+ borderWidth: 1
+ },
+ checkpointStyle: {
+ color: '#316bf3',
+ borderColor: '#ffffff'
+ },
+ label: {
+ color: '#a4b1d7'
+ },
+ emphasis: {
+ itemStyle: {
+ color: '#ffffff'
+ },
+ controlStyle: {
+ color: '#a4b1d7',
+ borderColor: '#a4b1d7',
+ borderWidth: 1
+ },
+ label: {
+ color: '#a4b1d7'
+ }
+ }
+ },
+ visualMap: {
+ color: ['#bf444c', '#d88273', '#f6efa6']
+ },
+ dataZoom: {
+ handleSize: 'undefined%',
+ textStyle: {}
+ },
+ markPoint: {
+ label: {
+ color: '#eeeeee'
+ },
+ emphasis: {
+ label: {
+ color: '#eeeeee'
+ }
+ }
+ }
+ };
+};
diff --git a/packages/react-charts/src/echarts/components/index.ts b/packages/react-charts/src/echarts/components/index.ts
new file mode 100644
index 00000000000..4bb44aaee6a
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/index.ts
@@ -0,0 +1 @@
+export * from './Sankey';
diff --git a/packages/react-charts/src/echarts/components/utils/misc.ts b/packages/react-charts/src/echarts/components/utils/misc.ts
new file mode 100644
index 00000000000..ea6255e57f9
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/utils/misc.ts
@@ -0,0 +1,23 @@
+/**
+ * Copied from exenv
+ * @private
+ */
+export const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
+
+/**
+ * Returns the class name that will be applied to the outermost div rendered by the chart's container
+ * @private
+ */
+export const getClassName = (className: string) => {
+ let cleanClassName;
+
+ // Cleanup class name
+ if (className) {
+ cleanClassName = className
+ .replace(/pf-v6-c-chart/g, '')
+ .replace(/pf-c-chart/g, '')
+ .replace(/\s+/g, ' ')
+ .trim();
+ }
+ return cleanClassName?.length ? `pf-v6-c-chart ${cleanClassName}` : 'pf-v6-c-chart';
+};
diff --git a/packages/react-charts/src/echarts/components/utils/observe.ts b/packages/react-charts/src/echarts/components/utils/observe.ts
new file mode 100644
index 00000000000..364efdba387
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/utils/observe.ts
@@ -0,0 +1,38 @@
+/**
+ * Mutation Observer Helper function
+ * //developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe
+ *
+ * @param {string} selector The DOM selector to watch
+ * @param {object} opt MutationObserver options
+ * @param {function} cb Pass Mutation object to a callback function
+ * @private
+ */
+export const observe = (selector: any, opt: any, cb: any) => {
+ let unobserve: any;
+
+ if (selector) {
+ const Obs = new MutationObserver((m) => [...m].forEach(cb));
+ document.querySelectorAll(selector).forEach((el) => Obs.observe(el, opt));
+ unobserve = () => Obs.disconnect();
+ }
+ return () => {
+ if (unobserve) {
+ unobserve();
+ }
+ };
+};
+
+// See https://stackoverflow.com/questions/17134823/detect-element-style-changes-with-javascript
+export const getMutationObserver = (nodeSelector: string, cb: any) =>
+ observe(
+ nodeSelector,
+ {
+ attributesList: ['style'], // Only the "style" attribute
+ attributeOldValue: true // Report also the oldValue
+ },
+ (m: any) => {
+ if (cb) {
+ cb(m);
+ }
+ }
+ );
diff --git a/packages/react-charts/src/echarts/components/utils/theme.ts b/packages/react-charts/src/echarts/components/utils/theme.ts
new file mode 100644
index 00000000000..e6dff369fc9
--- /dev/null
+++ b/packages/react-charts/src/echarts/components/utils/theme.ts
@@ -0,0 +1,9 @@
+import { canUseDOM } from '../utils/misc';
+
+// See https://github.com/apache/echarts/issues/19743
+export const getComputedStyle = (token: any) => {
+ if (canUseDOM) {
+ return window.getComputedStyle(document.body).getPropertyValue(token.name);
+ }
+ return token.value;
+};
diff --git a/packages/react-charts/src/echarts/index.ts b/packages/react-charts/src/echarts/index.ts
new file mode 100644
index 00000000000..07635cbbc8e
--- /dev/null
+++ b/packages/react-charts/src/echarts/index.ts
@@ -0,0 +1 @@
+export * from './components';
diff --git a/packages/react-charts/subpaths.config.json b/packages/react-charts/subpaths.config.json
index 5c5e5d1baff..706c0581100 100644
--- a/packages/react-charts/subpaths.config.json
+++ b/packages/react-charts/subpaths.config.json
@@ -1,4 +1,4 @@
{
"packageName": "@patternfly/react-charts",
- "paths": ["victory"]
+ "paths": ["echarts", "victory"]
}
diff --git a/packages/react-charts/tsconfig.json b/packages/react-charts/tsconfig.json
index 30bec2faa4a..cfd3101ef1b 100644
--- a/packages/react-charts/tsconfig.json
+++ b/packages/react-charts/tsconfig.json
@@ -1,9 +1,14 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
+ "jsx": "react",
"rootDir": "./src",
"outDir": "./dist/esm",
- "tsBuildInfoFile": "dist/esm.tsbuildinfo"
+ "tsBuildInfoFile": "dist/esm.tsbuildinfo",
+ "baseUrl": ".",
+ "paths": {
+ "./next": ["./src/next"]
+ }
},
"include": [
"./src/*",
diff --git a/packages/react-charts/victory/package.json b/packages/react-charts/victory/package.json
index 1be7f7b05c5..1e36a9be341 100644
--- a/packages/react-charts/victory/package.json
+++ b/packages/react-charts/victory/package.json
@@ -1 +1 @@
-{"name":"@patternfly/react-charts-victory","main":"../dist/js/victory/index.js","module":"../dist/esm/victory/index.js","typings":"../dist/esm/victory/index.d.ts","version":"8.0.0-prerelease.12","private":true}
+{"name":"@patternfly/react-charts-victory","main":"../dist/js/victory/index.js","module":"../dist/esm/victory/index.js","typings":"../dist/esm/victory/index.d.ts","version":"8.0.0-prerelease.13","private":true}
diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json
index 42bf69df1b9..4acd330d4bf 100644
--- a/packages/react-docs/package.json
+++ b/packages/react-docs/package.json
@@ -33,6 +33,7 @@
"@patternfly/react-table": "workspace:^",
"@patternfly/react-templates": "workspace:^",
"@patternfly/react-tokens": "workspace:^",
+ "echarts": "^5.5.1",
"victory": "^37.1.1"
},
"devDependencies": {
diff --git a/yarn.lock b/yarn.lock
index 4d07318fdd8..266467a9f5f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3160,12 +3160,13 @@ __metadata:
dependencies:
"@patternfly/react-styles": "workspace:^"
"@patternfly/react-tokens": "workspace:^"
- "@types/lodash": "npm:^4.17.9"
+ "@types/lodash": "npm:^4.17.7"
fs-extra: "npm:^11.2.0"
hoist-non-react-statics: "npm:^3.3.2"
lodash: "npm:^4.17.21"
tslib: "npm:^2.7.0"
peerDependencies:
+ echarts: ^5.5.1
react: ^17 || ^18
react-dom: ^17 || ^18
victory-area: ^37.1.1
@@ -3241,6 +3242,7 @@ __metadata:
"@patternfly/react-table": "workspace:^"
"@patternfly/react-templates": "workspace:^"
"@patternfly/react-tokens": "workspace:^"
+ echarts: "npm:^5.5.1"
victory: "npm:^37.1.1"
languageName: unknown
linkType: soft
@@ -4457,10 +4459,10 @@ __metadata:
languageName: node
linkType: hard
-"@types/lodash@npm:^4.17.9":
- version: 4.17.9
- resolution: "@types/lodash@npm:4.17.9"
- checksum: 10c0/54de935e835508b5f835a5dfaedd2b9a299685a21d11e9c5cd2dde57331d03bc2f98b71d2424ca8460f447ecd55a673e45ccdb70e58f9f72745710f6b91abc60
+"@types/lodash@npm:^4.17.7":
+ version: 4.17.7
+ resolution: "@types/lodash@npm:4.17.7"
+ checksum: 10c0/40c965b5ffdcf7ff5c9105307ee08b782da228c01b5c0529122c554c64f6b7168fc8f11dc79aa7bae4e67e17efafaba685dc3a47e294dbf52a65ed2b67100561
languageName: node
linkType: hard
@@ -8703,6 +8705,16 @@ __metadata:
languageName: node
linkType: hard
+"echarts@npm:^5.5.1":
+ version: 5.5.1
+ resolution: "echarts@npm:5.5.1"
+ dependencies:
+ tslib: "npm:2.3.0"
+ zrender: "npm:5.6.0"
+ checksum: 10c0/2f7e3037f17fda99d977092767943f4d9b0c8f886f86701ec88591707713b5e5fd683e56086b6ba5245b322f088184bdb06eac488234c20a1869b08cb6b4e523
+ languageName: node
+ linkType: hard
+
"editions@npm:^2.2.0":
version: 2.3.1
resolution: "editions@npm:2.3.1"
@@ -20038,6 +20050,13 @@ __metadata:
languageName: node
linkType: hard
+"tslib@npm:2.3.0":
+ version: 2.3.0
+ resolution: "tslib@npm:2.3.0"
+ checksum: 10c0/a845aed84e7e7dbb4c774582da60d7030ea39d67307250442d35c4c5dd77e4b44007098c37dd079e100029c76055f2a362734b8442ba828f8cc934f15ed9be61
+ languageName: node
+ linkType: hard
+
"tslib@npm:^1.8.1, tslib@npm:^1.9.0":
version: 1.14.1
resolution: "tslib@npm:1.14.1"
@@ -22172,3 +22191,12 @@ __metadata:
checksum: 10c0/856117aa15cf5103d2a2fb173f0ab4acb12b4b4d0ed3ab249fdbbf612e55d1cadfd27a6110940e24746fb0a78cf640b522cc8bca76f30a3b00b66e90cf82abe0
languageName: node
linkType: hard
+
+"zrender@npm:5.6.0":
+ version: 5.6.0
+ resolution: "zrender@npm:5.6.0"
+ dependencies:
+ tslib: "npm:2.3.0"
+ checksum: 10c0/f7c5a1739dfec60b9bead0d0657c47868391b1009cc82a603f9dbf247fa625df28dcdb3e7b2e18404657e2c987f95e0e1bb5613519c2d823854f3dda44e2ee96
+ languageName: node
+ linkType: hard